Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func init() {
loggedInDetails, err := util.GetCurrentLoggedInUserDetails(false)

if !silent && err == nil && loggedInDetails.IsUserLoggedIn && !loggedInDetails.LoginExpired {
token, err := util.GetInfisicalToken(cmd)
token, err := util.DetectInfisicalToken(cmd)

if err == nil && token != nil {
util.PrintWarningWithWriter(fmt.Sprintf("Your logged-in session is being overwritten by the token provided from the %s.", token.Source), cmd.ErrOrStderr())
Expand Down
122 changes: 99 additions & 23 deletions packages/util/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,59 +279,135 @@ func IsSecretTypeValid(s string) bool {
return false
}

func GetInfisicalToken(cmd *cobra.Command) (token *models.TokenDetails, err error) {
infisicalToken, err := cmd.Flags().GetString("token")
// DetectInfisicalToken checks for locally-available tokens and credentials
// without performing any network calls. Use this when you only need to know
// whether a token source is present (e.g. for the "session overwritten" warning
// in PersistentPreRun).
func DetectInfisicalToken(cmd *cobra.Command) (token *models.TokenDetails, err error) {
infisicalToken, source := lookupLocalToken(cmd)
if infisicalToken != "" {
return classifyToken(infisicalToken, source), nil
}

clientId := os.Getenv(INFISICAL_UNIVERSAL_AUTH_CLIENT_ID_NAME)
clientSecret := os.Getenv(INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET_NAME)
if clientId != "" && clientSecret != "" {
return &models.TokenDetails{
Type: UNIVERSAL_AUTH_TOKEN_IDENTIFIER,
Source: fmt.Sprintf("%s and %s environment variables", INFISICAL_UNIVERSAL_AUTH_CLIENT_ID_NAME, INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET_NAME),
}, nil
}

if err != nil {
return nil, err
return nil, nil
}

func GetInfisicalToken(cmd *cobra.Command) (token *models.TokenDetails, err error) {
infisicalToken, source := lookupLocalToken(cmd)
if infisicalToken != "" {
return classifyToken(infisicalToken, source), nil
}

var source = "--token flag"
// Skip auto-login when an explicit auth method is requested via
// --auth-method flag or INFISICAL_AUTH_METHOD env var, so that
// other auth flows (AWS, GCP, K8s, etc.) are not short-circuited.
if isAuthMethodSpecified(cmd) {
return nil, nil
}

if infisicalToken == "" { // If no flag is passed, we first check for the universal auth access token env variable.
infisicalToken = os.Getenv(INFISICAL_UNIVERSAL_AUTH_ACCESS_TOKEN_NAME)
source = fmt.Sprintf("%s environment variable", INFISICAL_UNIVERSAL_AUTH_ACCESS_TOKEN_NAME)
clientId := os.Getenv(INFISICAL_UNIVERSAL_AUTH_CLIENT_ID_NAME)
clientSecret := os.Getenv(INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET_NAME)

if infisicalToken == "" { // If it's still empty after the first env check, we check for the service token env variable.
infisicalToken = os.Getenv(INFISICAL_TOKEN_NAME)
source = fmt.Sprintf("%s environment variable", INFISICAL_TOKEN_NAME)
if clientId != "" && clientSecret != "" {
log.Debug().Msg("No explicit token found, attempting automatic authentication via Universal Auth client credentials")
loginResponse, err := UniversalAuthLogin(clientId, clientSecret)
if err != nil {
return nil, fmt.Errorf("failed to authenticate with Universal Auth using %s and %s environment variables: %w",
INFISICAL_UNIVERSAL_AUTH_CLIENT_ID_NAME, INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET_NAME, err)
}

if infisicalToken == "" { // if its still empty, check for the `TOKEN` environment variable (for gateway helm)
infisicalToken = os.Getenv(INFISICAL_GATEWAY_TOKEN_NAME_LEGACY)
source = fmt.Sprintf("%s environment variable", INFISICAL_GATEWAY_TOKEN_NAME_LEGACY)
}
return &models.TokenDetails{
Type: UNIVERSAL_AUTH_TOKEN_IDENTIFIER,
Token: loginResponse.AccessToken,
Source: fmt.Sprintf("%s and %s environment variables", INFISICAL_UNIVERSAL_AUTH_CLIENT_ID_NAME, INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET_NAME),
}, nil
}

if infisicalToken == "" { // If it's empty, we return nothing at all.
return nil, nil
return nil, nil
}

// lookupLocalToken checks for an explicit token from flags and env vars.
// No network calls are made.
func lookupLocalToken(cmd *cobra.Command) (token string, source string) {
infisicalToken, err := cmd.Flags().GetString("token")
if err != nil {
return "", ""
}

if infisicalToken != "" {
return infisicalToken, "--token flag"
}

if v := os.Getenv(INFISICAL_UNIVERSAL_AUTH_ACCESS_TOKEN_NAME); v != "" {
return v, fmt.Sprintf("%s environment variable", INFISICAL_UNIVERSAL_AUTH_ACCESS_TOKEN_NAME)
}

if v := os.Getenv(INFISICAL_TOKEN_NAME); v != "" {
return v, fmt.Sprintf("%s environment variable", INFISICAL_TOKEN_NAME)
}

if v := os.Getenv(INFISICAL_GATEWAY_TOKEN_NAME_LEGACY); v != "" {
return v, fmt.Sprintf("%s environment variable", INFISICAL_GATEWAY_TOKEN_NAME_LEGACY)
}

return "", ""
}

func classifyToken(infisicalToken, source string) *models.TokenDetails {
if strings.HasPrefix(infisicalToken, "st.") {
return &models.TokenDetails{
Type: SERVICE_TOKEN_IDENTIFIER,
Token: infisicalToken,
Source: source,
}, nil
}
}

return &models.TokenDetails{
Type: UNIVERSAL_AUTH_TOKEN_IDENTIFIER,
Token: infisicalToken,
Source: source,
}, nil
}
}

// isAuthMethodSpecified returns true when the caller has explicitly requested
// a machine-identity auth strategy, either via the --auth-method CLI flag or
// the INFISICAL_AUTH_METHOD environment variable. The env var is only checked
// when the command actually defines the --auth-method flag (e.g. gateway, relay),
// so that commands like run/export/secrets are not affected by a globally-set
// INFISICAL_AUTH_METHOD.
func isAuthMethodSpecified(cmd *cobra.Command) bool {
f := cmd.Flags().Lookup("auth-method")
if f == nil {
return false
}
if f.Changed {
return true
}
if os.Getenv(INFISICAL_AUTH_METHOD_NAME) != "" {
return true
Comment thread
varonix0 marked this conversation as resolved.
}
return false
}

const universalAuthAutoLoginRetries = 3

func UniversalAuthLogin(clientId string, clientSecret string) (api.UniversalAuthLoginResponse, error) {
httpClient, err := GetRestyClientWithCustomHeaders()
if err != nil {
return api.UniversalAuthLoginResponse{}, err
}

httpClient.SetRetryCount(10000).
SetRetryMaxWaitTime(20 * time.Second).
SetRetryWaitTime(5 * time.Second)
httpClient.SetRetryCount(universalAuthAutoLoginRetries).
SetRetryMaxWaitTime(5 * time.Second).
SetRetryWaitTime(2 * time.Second)

tokenResponse, err := api.CallUniversalAuthLogin(httpClient, api.UniversalAuthLoginRequest{ClientId: clientId, ClientSecret: clientSecret})
if err != nil {
Expand Down
Loading