agent-exec transport 0699ed700085214566f19101dc7dab32/f6013519841f
This commit is contained in:
+5
-5
@@ -449,14 +449,14 @@ EOF
|
||||
- mock 档不支持;PG 档须有有效 DSN/dbref
|
||||
|
||||
五个子命令(经 scripts/svc.sh <env> user … 转发到实例二进制):
|
||||
scripts/svc.sh <env> user create --owner <login> [--role user|admin] --out <0600新文件>
|
||||
scripts/svc.sh <env> user initialize-account --user-id <稳定ID> --expected-state-version <版本> --expected-generation <代数> --out <0600新文件>
|
||||
scripts/svc.sh <env> user create --owner <login> [--role user|admin]
|
||||
scripts/svc.sh <env> user initialize-account --user-id <稳定ID> --expected-state-version <版本> --expected-generation <代数>
|
||||
scripts/svc.sh <env> user list
|
||||
scripts/svc.sh <env> user revoke-login-key --id <key-id>
|
||||
scripts/svc.sh <env> user bootstrap-admin --owner <login> --out <0600新文件>
|
||||
|
||||
旧 reset-password、issue-login-key 与带初始密码建号已关闭;本人恢复走管理员提案、
|
||||
目标本人已有可信密码会话确认。凭据只写新建的 0600 交付文件,不回显 stdout。
|
||||
旧 reset-password、issue-login-key 入口已关闭;账号由管理员在网页创建并下发初始密码,
|
||||
首次登录后必须修改。忘记密码时由管理员生成一次性口令(POST /api/admin/users/{owner}/one-time-password)。
|
||||
本帮助描述 U3 代码契约;真实账号操作与生产切换须另行授权。
|
||||
更完整说明:docs/svc.md、docs/svc-deploy/u1-instance-account-binding.md
|
||||
EOF
|
||||
@@ -2451,7 +2451,7 @@ agent_do_user() {
|
||||
local a
|
||||
case "${1:-}" in
|
||||
reset-password|issue-login-key)
|
||||
c_err "[$ENV_NAME] RECOVERY_CONTRACT_REPLACED:旧账号重置/签发入口已关闭;使用本人确认的恢复提案"
|
||||
c_err "[$ENV_NAME] RECOVERY_CONTRACT_REPLACED:旧账号重置/签发入口已关闭;请联系管理员生成一次性口令(POST /api/admin/users/{owner}/one-time-password)"
|
||||
return 2 ;;
|
||||
esac
|
||||
for a in "$@"; do
|
||||
|
||||
@@ -39,10 +39,11 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
aliceOwner = "mi_alice"
|
||||
alicePass = "mi-alice-pass-1"
|
||||
rootPass = "mi-root-pass-1"
|
||||
httpWait = 15 * time.Second
|
||||
aliceOwner = "mi_alice"
|
||||
aliceInitialPass = "MiAliceInitPass123!"
|
||||
alicePass = "mi-alice-pass-1"
|
||||
rootPass = "mi-root-pass-1"
|
||||
httpWait = 15 * time.Second
|
||||
)
|
||||
|
||||
type instance struct {
|
||||
@@ -452,28 +453,35 @@ func (e *env) killNine(t *testing.T, inst *instance) {
|
||||
|
||||
// ---- HTTP 客户端 ----
|
||||
|
||||
// loginAlice 引导 alice 账号并发放 API key(CLI 直连测试库;key 存共享 PG,
|
||||
// 对两实例同时有效——程序化验收的首选凭证,SSE 亦可用 ?key= 兜底)。
|
||||
// U3 后本地无密码创建:user create 只签发待激活账号的一次性激活 Key(凭据
|
||||
// 独占落 JSON),redeem 会话进入 grant-setup 改密设 alicePass,完成后再发 Key。
|
||||
// loginAlice 由管理员创建 alice 初始密码账号,再登录并改密后发放 API key
|
||||
// (CLI 直连测试库;key 存共享 PG,对两实例同时有效——程序化验收的首选凭证,
|
||||
// SSE 亦可用 ?key= 兜底)。
|
||||
func (e *env) loginAlice(t *testing.T) *userClient {
|
||||
t.Helper()
|
||||
// 超级管理员 mi-root 已由 serve 启动时的 SUPER_ADMIN_* 建立;这里只建 alice,
|
||||
// 一次性激活凭据独占落临时 JSON。
|
||||
activation := filepath.Join(t.TempDir(), "activation.json")
|
||||
e.cliIn(t, e.a.dataDir, "user", "create", "--dsn", e.dbDSN, "--owner", aliceOwner, "--name", "Alice", "--out", activation)
|
||||
activateKey := activationSecret(t, activation)
|
||||
// 超级管理员 mi-root 已由 serve 启动时的 SUPER_ADMIN_* 建立;用 root key 走
|
||||
// admin API 创建 alice(带初始密码)。
|
||||
rootKey := e.cliOut(t, "apikey", "create", "--dsn", e.dbDSN, "--owner", "mi-root", "--name", "mi-acceptance-root-create-alice")
|
||||
root := &http.Client{Timeout: httpWait, Transport: bearerRT{key: rootKey}}
|
||||
e.do(t, root, "POST", "/api/admin/users", map[string]any{
|
||||
"owner": aliceOwner,
|
||||
"profile": map[string]any{
|
||||
"name": "Alice",
|
||||
},
|
||||
"password": aliceInitialPass,
|
||||
}, nil)
|
||||
jar, err := cookiejar.New(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sess := &http.Client{Timeout: httpWait, Jar: jar}
|
||||
// e.uc 尚未赋值 → baseFor 走 A;redeem 会话(grant-setup)直接设 alicePass。
|
||||
e.do(t, sess, "POST", "/api/auth/login-key/redeem", map[string]any{
|
||||
"key": activateKey,
|
||||
// e.uc 尚未赋值 → baseFor 走 A;初始密码登录后会话仅允许改密。
|
||||
e.do(t, sess, "POST", "/api/auth/login", map[string]any{
|
||||
"owner": aliceOwner,
|
||||
"password": aliceInitialPass,
|
||||
}, nil)
|
||||
e.do(t, sess, "POST", "/api/auth/password", map[string]any{
|
||||
"next": alicePass,
|
||||
"current": aliceInitialPass,
|
||||
"next": alicePass,
|
||||
}, nil)
|
||||
|
||||
apiKey := e.cliOut(t, "apikey", "create", "--dsn", e.dbDSN, "--owner", aliceOwner, "--name", "mi-acceptance")
|
||||
@@ -540,22 +548,6 @@ func (b bearerRT) RoundTrip(r *http.Request) (*http.Response, error) {
|
||||
return http.DefaultTransport.RoundTrip(r2)
|
||||
}
|
||||
|
||||
// activationSecret 读 CLI 凭据独占文件里的激活 Key(JSON {"kind","owner","secret"})。
|
||||
func activationSecret(t *testing.T, path string) string {
|
||||
t.Helper()
|
||||
b, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var v struct {
|
||||
Secret string `json:"secret"`
|
||||
}
|
||||
if err := json.Unmarshal(b, &v); err != nil || v.Secret == "" {
|
||||
t.Fatalf("activation credential unreadable: %v", err)
|
||||
}
|
||||
return v.Secret
|
||||
}
|
||||
|
||||
// cliOut 运行 CLI 并取 stdout 首行(apikey create 的明文仅此一次输出)。
|
||||
func (e *env) cliOut(t *testing.T, args ...string) string {
|
||||
t.Helper()
|
||||
|
||||
Reference in New Issue
Block a user