From fdbc55f35c95a50b13638dddfadb345570691975 Mon Sep 17 00:00:00 2001 From: kyy Date: Fri, 13 Feb 2026 10:10:27 +0900 Subject: [PATCH] =?UTF-8?q?Kratos=20=EC=97=B0=EA=B2=B0=20=EC=9E=AC?= =?UTF-8?q?=EC=8B=9C=EB=8F=84=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EB=B0=8F=20=EA=B4=80=EB=A6=AC=EC=9E=90=20ID=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/bootstrap/kratos_seed.go | 47 +++++++++++++++++------ 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/backend/internal/bootstrap/kratos_seed.go b/backend/internal/bootstrap/kratos_seed.go index 7ddb4a4c..c1130c65 100644 --- a/backend/internal/bootstrap/kratos_seed.go +++ b/backend/internal/bootstrap/kratos_seed.go @@ -5,19 +5,21 @@ import ( "log/slog" "os" "strings" + "time" ) // SeedAdminIdentity creates the initial admin identity in the configured IDP. -func SeedAdminIdentity(idp domain.IdentityProvider) error { +// Returns the Kratos Identity ID and error. +func SeedAdminIdentity(idp domain.IdentityProvider) (string, error) { if idp == nil { - return nil + return "", nil } adminEmail := strings.TrimSpace(os.Getenv("ADMIN_EMAIL")) adminPassword := os.Getenv("ADMIN_PASSWORD") if adminEmail == "" || adminPassword == "" { slog.Warn("[Bootstrap] ADMIN_EMAIL or ADMIN_PASSWORD not set. Skipping admin identity seed.") - return nil + return "", nil } adminName := strings.TrimSpace(os.Getenv("ADMIN_NAME")) @@ -34,18 +36,41 @@ func SeedAdminIdentity(idp domain.IdentityProvider) error { "affiliationType": "internal", "companyCode": "", "grade": "admin", + "role": "super_admin", // Explicitly set role for Kratos traits }, } - _, err := idp.CreateUser(user, adminPassword) - if err != nil { - if strings.Contains(err.Error(), "already exists") { - slog.Info("[Bootstrap] Admin identity already exists in IDP", "email", adminEmail) - return nil + // Retry logic for Kratos connection + maxRetries := 5 + var err error + var identityID string + + for i := 0; i < maxRetries; i++ { + identityID, err = idp.CreateUser(user, adminPassword) + if err == nil { + slog.Info("[Bootstrap] Admin identity created in IDP", "email", adminEmail, "idp", idp.Name(), "id", identityID) + return identityID, nil } - return err + + if strings.Contains(err.Error(), "already exists") { + slog.Info("[Bootstrap] Admin identity already exists in IDP. Attempting to retrieve ID...", "email", adminEmail) + // Try to sign in to get the identity ID + authInfo, err := idp.SignIn(adminEmail, adminPassword) + if err == nil && authInfo != nil { + slog.Info("[Bootstrap] Retrieved existing admin identity ID", "id", authInfo.Subject) + return authInfo.Subject, nil + } + slog.Warn("[Bootstrap] Failed to retrieve existing admin identity ID via SignIn", "error", err) + return "", nil // Return nil error to avoid stopping bootstrap, but ID is missing + } + + slog.Warn("[Bootstrap] Failed to seed admin identity (retrying...)", + "attempt", i+1, + "max_retries", maxRetries, + "error", err, + ) + time.Sleep(2 * time.Second) } - slog.Info("[Bootstrap] Admin identity created in IDP", "email", adminEmail, "idp", idp.Name()) - return nil + return "", err }