github.com/anthropics/anthropic-sdk-go@v1.70.1/internal/auth/default.go (about) 1 package auth 2 3 import ( 4 "os" 5 "strings" 6 ) 7 8 // identityProviderFromEnv resolves an [IdentityTokenProvider] from env vars, 9 // preferring ANTHROPIC_IDENTITY_TOKEN_FILE (rotation-safe) over the literal 10 // ANTHROPIC_IDENTITY_TOKEN. Returns nil when neither is set. 11 func identityProviderFromEnv() IdentityTokenProvider { 12 if path, ok := os.LookupEnv(EnvIdentityTokenFile); ok { 13 return &IdentityTokenFile{Path: path} 14 } 15 if token, ok := os.LookupEnv(EnvIdentityToken); ok { 16 return &IdentityTokenValue{Token: token} 17 } 18 return nil 19 } 20 21 // EnvCredentials resolves OIDC-federation credentials from environment 22 // variables. Returns a usable result when the three required vars are all 23 // set. Otherwise returns nil plus a detail + state enum: NotSet when 24 // nothing is configured, Partial with a "missing: ..." detail otherwise. 25 func EnvCredentials() (*CredentialsResult, string, CredentialSourceState) { 26 federationRuleID, hasFedRule := os.LookupEnv(EnvFederationRuleID) 27 _, hasOrgID := os.LookupEnv(EnvOrganizationID) 28 hasTokenFile := os.Getenv(EnvIdentityTokenFile) != "" 29 hasTokenLiteral := os.Getenv(EnvIdentityToken) != "" 30 hasToken := hasTokenFile || hasTokenLiteral 31 32 if !hasFedRule && !hasOrgID && !hasToken { 33 return nil, "", CredentialSourceNotSet 34 } 35 36 if !hasFedRule || !hasOrgID || !hasToken { 37 var missing []string 38 if !hasFedRule { 39 missing = append(missing, EnvFederationRuleID) 40 } 41 if !hasOrgID { 42 missing = append(missing, EnvOrganizationID) 43 } 44 if !hasToken { 45 missing = append(missing, EnvIdentityTokenFile+" (or "+EnvIdentityToken+")") 46 } 47 return nil, "partial configuration, missing: " + strings.Join(missing, ", "), CredentialSourcePartial 48 } 49 50 orgID := os.Getenv(EnvOrganizationID) 51 identityProvider := identityProviderFromEnv() 52 cfg := OIDCFederationConfig{ 53 IdentityProvider: identityProvider, 54 FederationRuleID: federationRuleID, 55 OrganizationID: orgID, 56 } 57 if sa, ok := os.LookupEnv(EnvServiceAccountID); ok { 58 cfg.ServiceAccountID = sa 59 } 60 if ws, ok := os.LookupEnv(EnvWorkspaceID); ok { 61 // An empty ANTHROPIC_WORKSPACE_ID (a defaulted-but-empty CI variable) 62 // is treated as unset: WorkspaceID stays "" and the wire field has 63 // json:"workspace_id,omitempty", so `"workspace_id": ""` is never 64 // serialized. No coercion needed — Go's Getenv + omitempty handle it. 65 cfg.WorkspaceID = ws 66 } 67 68 return &CredentialsResult{ 69 Provider: NewOIDCFederationCredentials(cfg), 70 }, "", CredentialSourceNotSet 71 }