From 13629223fb16f5908c35eba6f6ea1912cd0bbe6f Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Tue, 26 Mar 2024 23:30:56 +0100 Subject: [PATCH 01/35] Chore: Moved universalAuthLogin function to utils --- cli/packages/cmd/agent.go | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/cli/packages/cmd/agent.go b/cli/packages/cmd/agent.go index 80f321396..d32afa986 100644 --- a/cli/packages/cmd/agent.go +++ b/cli/packages/cmd/agent.go @@ -509,7 +509,7 @@ func (tm *AgentManager) FetchNewAccessToken() error { // save as cache in memory tm.cachedClientSecret = clientSecret - err, loginResponse := universalAuthLogin(clientID, clientSecret) + loginResponse, err := util.UniversalAuthLogin(clientID, clientSecret) if err != nil { return err } @@ -725,20 +725,6 @@ func (tm *AgentManager) MonitorSecretChanges(secretTemplate Template, templateId } } -func universalAuthLogin(clientId string, clientSecret string) (error, api.UniversalAuthLoginResponse) { - httpClient := resty.New() - httpClient.SetRetryCount(10000). - SetRetryMaxWaitTime(20 * time.Second). - SetRetryWaitTime(5 * time.Second) - - tokenResponse, err := api.CallUniversalAuthLogin(httpClient, api.UniversalAuthLoginRequest{ClientId: clientId, ClientSecret: clientSecret}) - if err != nil { - return err, api.UniversalAuthLoginResponse{} - } - - return nil, tokenResponse -} - // runCmd represents the run command var agentCmd = &cobra.Command{ Example: ` From fa33f35fcd2825b1b5d513008956105aa295cf9e Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Tue, 26 Mar 2024 23:31:35 +0100 Subject: [PATCH 02/35] Feat: Export support for Machine Identities --- cli/packages/cmd/export.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/cli/packages/cmd/export.go b/cli/packages/cmd/export.go index 1a34219eb..2a11274a1 100644 --- a/cli/packages/cmd/export.go +++ b/cli/packages/cmd/export.go @@ -60,11 +60,16 @@ var exportCmd = &cobra.Command{ } infisicalToken, err := util.GetInfisicalServiceToken(cmd) - if err != nil { util.HandleError(err, "Unable to parse flag") } + identityAccessToken, err := util.GetInfisicalUniversalAuthAccessToken(cmd) + + if err != nil { + util.HandleError(err, "Authentication with universal auth failed") + } + tagSlugs, err := cmd.Flags().GetString("tags") if err != nil { util.HandleError(err, "Unable to parse flag") @@ -75,7 +80,7 @@ var exportCmd = &cobra.Command{ util.HandleError(err, "Unable to parse flag") } - secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, WorkspaceId: projectId, SecretsPath: secretsPath}, "") + secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, UniversalAuthAccessToken: identityAccessToken, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, WorkspaceId: projectId, SecretsPath: secretsPath}, "") if err != nil { util.HandleError(err, "Unable to fetch secrets") } @@ -111,6 +116,8 @@ func init() { exportCmd.Flags().StringP("format", "f", "dotenv", "Set the format of the output file (dotenv, json, csv)") exportCmd.Flags().Bool("secret-overriding", true, "Prioritizes personal secrets, if any, with the same name over shared secrets") exportCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") + exportCmd.Flags().String("universal-auth-client-id", "", "Machine Identity universal auth client ID") + exportCmd.Flags().String("universal-auth-client-secret", "", "Machine Identity universal auth client secret") exportCmd.Flags().StringP("tags", "t", "", "filter secrets by tag slugs") exportCmd.Flags().String("projectId", "", "manually set the projectId to fetch secrets from") exportCmd.Flags().String("path", "/", "get secrets within a folder path") From 4d61188d0f075653eeb9ef9d97f40b3d3efa429a Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Tue, 26 Mar 2024 23:31:46 +0100 Subject: [PATCH 03/35] Feat: Folder support for Machine Identities --- cli/packages/cmd/folder.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/cli/packages/cmd/folder.go b/cli/packages/cmd/folder.go index 290f32c38..dc2298980 100644 --- a/cli/packages/cmd/folder.go +++ b/cli/packages/cmd/folder.go @@ -36,8 +36,16 @@ var getCmd = &cobra.Command{ } } - infisicalToken, err := util.GetInfisicalServiceToken(cmd) + projectId, err := cmd.Flags().GetString("projectId") + if err != nil { + util.HandleError(err, "Unable to parse flag") + } + infisicalToken, err := util.GetInfisicalServiceToken(cmd) + if err != nil { + util.HandleError(err, "Unable to parse flag") + } + identityAccessToken, err := util.GetInfisicalUniversalAuthAccessToken(cmd) if err != nil { util.HandleError(err, "Unable to parse flag") } @@ -47,7 +55,7 @@ var getCmd = &cobra.Command{ util.HandleError(err, "Unable to parse flag") } - folders, err := util.GetAllFolders(models.GetAllFoldersParameters{Environment: environmentName, InfisicalToken: infisicalToken, FoldersPath: foldersPath}) + folders, err := util.GetAllFolders(models.GetAllFoldersParameters{Environment: environmentName, InfisicalToken: infisicalToken, UniversalAuthAccessToken: identityAccessToken, FoldersPath: foldersPath, WorkspaceId: projectId}) if err != nil { util.HandleError(err, "Unable to get folders") } From 4123177133bb9c6bbc7c0f54d4a9d2a923835496 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Tue, 26 Mar 2024 23:33:33 +0100 Subject: [PATCH 04/35] Feat: Run cmd support for Machine Identities --- cli/packages/cmd/run.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/cli/packages/cmd/run.go b/cli/packages/cmd/run.go index cb44e3d7e..fe5afb782 100644 --- a/cli/packages/cmd/run.go +++ b/cli/packages/cmd/run.go @@ -63,7 +63,10 @@ var runCmd = &cobra.Command{ } infisicalToken, err := util.GetInfisicalServiceToken(cmd) - + if err != nil { + util.HandleError(err, "Unable to parse flag") + } + identityAccessToken, err := util.GetInfisicalUniversalAuthAccessToken(cmd) if err != nil { util.HandleError(err, "Unable to parse flag") } @@ -73,6 +76,11 @@ var runCmd = &cobra.Command{ util.HandleError(err, "Unable to parse flag") } + projectId, err := cmd.Flags().GetString("projectId") + if err != nil { + util.HandleError(err, "Unable to parse flag") + } + secretOverriding, err := cmd.Flags().GetBool("secret-overriding") if err != nil { util.HandleError(err, "Unable to parse flag") @@ -103,7 +111,7 @@ var runCmd = &cobra.Command{ util.HandleError(err, "Unable to parse flag") } - secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: includeImports, Recursive: recursive}, projectConfigDir) + secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, UniversalAuthAccessToken: identityAccessToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: includeImports, Recursive: recursive}, projectConfigDir) if err != nil { util.HandleError(err, "Could not fetch secrets", "If you are using a service token to fetch secrets, please ensure it is valid") @@ -204,6 +212,9 @@ func filterReservedEnvVars(env map[string]models.SingleEnvironmentVariable) { func init() { rootCmd.AddCommand(runCmd) runCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") + runCmd.Flags().String("universal-auth-client-id", "", "Machine Identity universal auth client ID") + runCmd.Flags().String("universal-auth-client-secret", "", "Machine Identity universal auth client secret") + runCmd.Flags().String("projectId", "", "manually set the projectId to fetch folders from for machine identity") runCmd.Flags().StringP("env", "e", "dev", "Set the environment (dev, prod, etc.) from which your secrets should be pulled from") runCmd.Flags().Bool("expand", true, "Parse shell parameter expansions in your secrets") runCmd.Flags().Bool("include-imports", true, "Import linked secrets ") From 3d391b4e2d3c2d496125f922bd3fcdd4f40afb07 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Tue, 26 Mar 2024 23:35:35 +0100 Subject: [PATCH 05/35] Feat: Secrets cmd support for Machine Identities --- cli/packages/cmd/secrets.go | 49 ++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/cli/packages/cmd/secrets.go b/cli/packages/cmd/secrets.go index 4e1b09c9e..e0b564f53 100644 --- a/cli/packages/cmd/secrets.go +++ b/cli/packages/cmd/secrets.go @@ -39,11 +39,16 @@ var secretsCmd = &cobra.Command{ } infisicalToken, err := util.GetInfisicalServiceToken(cmd) - if err != nil { util.HandleError(err, "Unable to parse flag") } + identityAccessToken, err := util.GetInfisicalUniversalAuthAccessToken(cmd) + if err != nil { + util.HandleError(err, "Unable to parse flag") + } + + projectId, err := cmd.Flags().GetString("projectId") if err != nil { util.HandleError(err, "Unable to parse flag") } @@ -78,7 +83,7 @@ var secretsCmd = &cobra.Command{ util.HandleError(err, "Unable to parse flag") } - secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: includeImports, Recursive: recursive}, "") + secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, WorkspaceId: projectId, InfisicalToken: infisicalToken, UniversalAuthAccessToken: identityAccessToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: includeImports, Recursive: recursive}, "") if err != nil { util.HandleError(err) } @@ -403,7 +408,10 @@ func getSecretsByNames(cmd *cobra.Command, args []string) { } infisicalToken, err := util.GetInfisicalServiceToken(cmd) - + if err != nil { + util.HandleError(err, "Unable to parse flag") + } + identityAccessToken, err := util.GetInfisicalUniversalAuthAccessToken(cmd) if err != nil { util.HandleError(err, "Unable to parse flag") } @@ -413,6 +421,11 @@ func getSecretsByNames(cmd *cobra.Command, args []string) { util.HandleError(err, "Unable to parse flag") } + projectId, err := cmd.Flags().GetString("projectId") + if err != nil { + util.HandleError(err, "Unable to parse flag") + } + secretsPath, err := cmd.Flags().GetString("path") if err != nil { util.HandleError(err, "Unable to parse path flag") @@ -428,7 +441,7 @@ func getSecretsByNames(cmd *cobra.Command, args []string) { util.HandleError(err, "Unable to parse path flag") } - secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: true, Recursive: recursive}, "") + secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, WorkspaceId: projectId, InfisicalToken: infisicalToken, UniversalAuthAccessToken: identityAccessToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: true, Recursive: recursive}, "") if err != nil { util.HandleError(err, "To fetch all secrets") } @@ -476,7 +489,16 @@ func generateExampleEnv(cmd *cobra.Command, args []string) { } infisicalToken, err := util.GetInfisicalServiceToken(cmd) + if err != nil { + util.HandleError(err, "Unable to parse flag") + } + identityAccessToken, err := util.GetInfisicalUniversalAuthAccessToken(cmd) + if err != nil { + util.HandleError(err, "Unable to parse flag") + } + + projectId, err := cmd.Flags().GetString("projectId") if err != nil { util.HandleError(err, "Unable to parse flag") } @@ -486,7 +508,7 @@ func generateExampleEnv(cmd *cobra.Command, args []string) { util.HandleError(err, "Unable to parse flag") } - secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: true}, "") + secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, WorkspaceId: projectId, InfisicalToken: infisicalToken, UniversalAuthAccessToken: identityAccessToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: true}, "") if err != nil { util.HandleError(err, "To fetch all secrets") } @@ -686,19 +708,26 @@ func getSecretsByKeys(secrets []models.SingleEnvironmentVariable) map[string]mod func init() { secretsGenerateExampleEnvCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") + secretsGenerateExampleEnvCmd.Flags().String("universal-auth-client-id", "", "Machine Identity universal auth client ID") + secretsGenerateExampleEnvCmd.Flags().String("universal-auth-client-secret", "", "Machine Identity universal auth client secret") + secretsGenerateExampleEnvCmd.Flags().String("projectId", "", "manually set the projectId to fetch folders from for machine identity") secretsGenerateExampleEnvCmd.Flags().String("path", "/", "Fetch secrets from within a folder path") secretsCmd.AddCommand(secretsGenerateExampleEnvCmd) secretsGetCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") - secretsCmd.AddCommand(secretsGetCmd) + secretsGetCmd.Flags().String("universal-auth-client-id", "", "Machine Identity universal auth client ID") + secretsGetCmd.Flags().String("universal-auth-client-secret", "", "Machine Identity universal auth client secret") + secretsGetCmd.Flags().String("projectId", "", "manually set the projectId to fetch folders from for machine identity") secretsGetCmd.Flags().String("path", "/", "get secrets within a folder path") secretsGetCmd.Flags().Bool("raw-value", false, "Returns only the value of secret, only works with one secret") secretsGetCmd.Flags().Bool("recursive", false, "Fetch secrets from all sub-folders") + secretsCmd.AddCommand(secretsGetCmd) secretsCmd.Flags().Bool("secret-overriding", true, "Prioritizes personal secrets, if any, with the same name over shared secrets") secretsCmd.AddCommand(secretsSetCmd) secretsSetCmd.Flags().String("path", "/", "set secrets within a folder path") + // Only supports logged in users (JWT auth) secretsSetCmd.PersistentPreRun = func(cmd *cobra.Command, args []string) { util.RequireLogin() util.RequireLocalWorkspaceFile() @@ -707,6 +736,8 @@ func init() { secretsDeleteCmd.Flags().String("type", "personal", "the type of secret to delete: personal or shared (default: personal)") secretsDeleteCmd.Flags().String("path", "/", "get secrets within a folder path") secretsCmd.AddCommand(secretsDeleteCmd) + + // Only supports logged in users (JWT auth) secretsDeleteCmd.PersistentPreRun = func(cmd *cobra.Command, args []string) { util.RequireLogin() util.RequireLocalWorkspaceFile() @@ -718,6 +749,9 @@ func init() { // Add getCmd, createCmd and deleteCmd flags here getCmd.Flags().StringP("path", "p", "/", "The path from where folders should be fetched from") getCmd.Flags().String("token", "", "Fetch folders using the infisical token") + getCmd.Flags().String("universal-auth-client-id", "", "Machine Identity universal auth client ID") + getCmd.Flags().String("universal-auth-client-secret", "", "Machine Identity universal auth client secret") + getCmd.Flags().String("projectId", "", "manually set the projectId to fetch folders from for machine identity") folderCmd.AddCommand(getCmd) // Add createCmd flags here @@ -735,6 +769,9 @@ func init() { // ** End of folders sub command secretsCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") + secretsCmd.Flags().String("universal-auth-client-id", "", "Machine Identity universal auth client ID") + secretsCmd.Flags().String("universal-auth-client-secret", "", "Machine Identity universal auth client secret") + secretsCmd.Flags().String("projectId", "", "manually set the projectId to fetch folders from for machine identity") secretsCmd.PersistentFlags().String("env", "dev", "Used to select the environment name on which actions should be taken on") secretsCmd.Flags().Bool("expand", true, "Parse shell parameter expansions in your secrets") secretsCmd.Flags().Bool("include-imports", true, "Imported linked secrets ") From 3981d61853fec3aebb709d8a304b8c0d4b8a4bd3 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Tue, 26 Mar 2024 23:36:00 +0100 Subject: [PATCH 06/35] Feat: Support for Machine Identities auth --- cli/packages/models/cli.go | 14 ++++++++++---- cli/packages/util/constants.go | 24 +++++++++++++----------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/cli/packages/models/cli.go b/cli/packages/models/cli.go index e197218e0..73db3d908 100644 --- a/cli/packages/models/cli.go +++ b/cli/packages/models/cli.go @@ -97,10 +97,11 @@ type GetAllSecretsParameters struct { } type GetAllFoldersParameters struct { - WorkspaceId string - Environment string - FoldersPath string - InfisicalToken string + WorkspaceId string + Environment string + FoldersPath string + InfisicalToken string + UniversalAuthAccessToken string } type CreateFolderParameters struct { @@ -123,3 +124,8 @@ type ExpandSecretsAuthentication struct { InfisicalToken string UniversalAuthAccessToken string } + +type MachineIdentityCredentials struct { + ClientId string + ClientSecret string +} diff --git a/cli/packages/util/constants.go b/cli/packages/util/constants.go index ee2532ee8..d4243208a 100644 --- a/cli/packages/util/constants.go +++ b/cli/packages/util/constants.go @@ -1,17 +1,19 @@ package util const ( - CONFIG_FILE_NAME = "infisical-config.json" - CONFIG_FOLDER_NAME = ".infisical" - INFISICAL_DEFAULT_API_URL = "https://app.infisical.com/api" - INFISICAL_DEFAULT_URL = "https://app.infisical.com" - INFISICAL_WORKSPACE_CONFIG_FILE_NAME = ".infisical.json" - INFISICAL_TOKEN_NAME = "INFISICAL_TOKEN" - SECRET_TYPE_PERSONAL = "personal" - SECRET_TYPE_SHARED = "shared" - KEYRING_SERVICE_NAME = "infisical" - PERSONAL_SECRET_TYPE_NAME = "personal" - SHARED_SECRET_TYPE_NAME = "shared" + CONFIG_FILE_NAME = "infisical-config.json" + CONFIG_FOLDER_NAME = ".infisical" + INFISICAL_DEFAULT_API_URL = "https://app.infisical.com/api" + INFISICAL_DEFAULT_URL = "https://app.infisical.com" + INFISICAL_WORKSPACE_CONFIG_FILE_NAME = ".infisical.json" + INFISICAL_TOKEN_NAME = "INFISICAL_TOKEN" + INFISICAL_UNIVERSAL_AUTH_CLIENT_ID = "INFISICAL_UNIVERSAL_AUTH_CLIENT_ID" + INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET = "INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET" + SECRET_TYPE_PERSONAL = "personal" + SECRET_TYPE_SHARED = "shared" + KEYRING_SERVICE_NAME = "infisical" + PERSONAL_SECRET_TYPE_NAME = "personal" + SHARED_SECRET_TYPE_NAME = "shared" ) var ( From 6ea7b04efaffd0961c745012741afb357a345d48 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Tue, 26 Mar 2024 23:36:57 +0100 Subject: [PATCH 07/35] Feat: Folder support for Machine Identities --- cli/packages/util/folders.go | 42 ++++++++++++++++++++++++++++-- cli/packages/util/helper.go | 50 ++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/cli/packages/util/folders.go b/cli/packages/util/folders.go index 0f837ee71..bccf11dbc 100644 --- a/cli/packages/util/folders.go +++ b/cli/packages/util/folders.go @@ -19,7 +19,7 @@ func GetAllFolders(params models.GetAllFoldersParameters) ([]models.SingleFolder var foldersToReturn []models.SingleFolder var folderErr error - if params.InfisicalToken == "" { + if params.InfisicalToken == "" && params.UniversalAuthAccessToken == "" { log.Debug().Msg("GetAllFolders: Trying to fetch folders using logged in details") @@ -44,11 +44,21 @@ func GetAllFolders(params models.GetAllFoldersParameters) ([]models.SingleFolder folders, err := GetFoldersViaJTW(loggedInUserDetails.UserCredentials.JTWToken, workspaceFile.WorkspaceId, params.Environment, params.FoldersPath) folderErr = err foldersToReturn = folders - } else { + } else if params.InfisicalToken != "" { // get folders via service token folders, err := GetFoldersViaServiceToken(params.InfisicalToken, params.WorkspaceId, params.Environment, params.FoldersPath) folderErr = err foldersToReturn = folders + } else if params.UniversalAuthAccessToken != "" { + + if params.WorkspaceId == "" { + PrintErrorMessageAndExit("Workspace ID is required when using machine identity") + } + + // get folders via machine identity + folders, err := GetFoldersViaMachineIdentity(params.UniversalAuthAccessToken, params.WorkspaceId, params.Environment, params.FoldersPath) + folderErr = err + foldersToReturn = folders } return foldersToReturn, folderErr } @@ -132,6 +142,34 @@ func GetFoldersViaServiceToken(fullServiceToken string, workspaceId string, envi return folders, nil } +func GetFoldersViaMachineIdentity(accessToken string, workspaceId string, envSlug string, foldersPath string) ([]models.SingleFolder, error) { + httpClient := resty.New() + httpClient.SetAuthToken(accessToken). + SetHeader("Accept", "application/json") + + getFoldersRequest := api.GetFoldersV1Request{ + WorkspaceId: workspaceId, + Environment: envSlug, + FoldersPath: foldersPath, + } + + apiResponse, err := api.CallGetFoldersV1(httpClient, getFoldersRequest) + if err != nil { + return nil, err + } + + var folders []models.SingleFolder + + for _, folder := range apiResponse.Folders { + folders = append(folders, models.SingleFolder{ + Name: folder.Name, + ID: folder.ID, + }) + } + + return folders, nil +} + // CreateFolder creates a folder in Infisical func CreateFolder(params models.CreateFolderParameters) (models.SingleFolder, error) { loggedInUserDetails, err := GetCurrentLoggedInUserDetails() diff --git a/cli/packages/util/helper.go b/cli/packages/util/helper.go index 11b3396dc..4d8074ddd 100644 --- a/cli/packages/util/helper.go +++ b/cli/packages/util/helper.go @@ -9,8 +9,11 @@ import ( "os/exec" "path" "strings" + "time" + "github.com/Infisical/infisical-merge/packages/api" "github.com/Infisical/infisical-merge/packages/models" + "github.com/go-resty/resty/v2" "github.com/spf13/cobra" ) @@ -78,6 +81,53 @@ func GetInfisicalServiceToken(cmd *cobra.Command) (serviceToken string, err erro return infisicalToken, nil } +func GetInfisicalUniversalAuthAccessToken(cmd *cobra.Command) (accessToken string, err error) { + + var token string + + universalAuthClientId, err := cmd.Flags().GetString("universal-auth-client-id") + if err != nil { + return token, err + } + universalAuthClientSecret, err := cmd.Flags().GetString("universal-auth-client-secret") + if err != nil { + return token, err + } + + if universalAuthClientId == "" { + universalAuthClientId = os.Getenv(INFISICAL_UNIVERSAL_AUTH_CLIENT_ID) + } + + if universalAuthClientSecret == "" { + universalAuthClientSecret = os.Getenv(INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET) + } + + if universalAuthClientId != "" || universalAuthClientSecret != "" { + res, err := UniversalAuthLogin(universalAuthClientId, universalAuthClientSecret) + + if err != nil { + return token, err + } + token = res.AccessToken + } + + return token, nil +} + +func UniversalAuthLogin(clientId string, clientSecret string) (api.UniversalAuthLoginResponse, error) { + httpClient := resty.New() + httpClient.SetRetryCount(10000). + SetRetryMaxWaitTime(20 * time.Second). + SetRetryWaitTime(5 * time.Second) + + tokenResponse, err := api.CallUniversalAuthLogin(httpClient, api.UniversalAuthLoginRequest{ClientId: clientId, ClientSecret: clientSecret}) + if err != nil { + return api.UniversalAuthLoginResponse{}, err + } + + return tokenResponse, nil +} + // Checks if the passed in email already exists in the users slice func ConfigContainsEmail(users []models.LoggedInUser, email string) bool { for _, value := range users { From 4d7182c9b105d072708448bb47d339f4fad905ef Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Tue, 26 Mar 2024 23:37:29 +0100 Subject: [PATCH 08/35] Fix: Removed unused struct and included secret type on secret response --- cli/packages/util/secrets.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/cli/packages/util/secrets.go b/cli/packages/util/secrets.go index 23e95db64..59d80ea77 100644 --- a/cli/packages/util/secrets.go +++ b/cli/packages/util/secrets.go @@ -159,7 +159,7 @@ func GetPlainTextSecretsViaMachineIdentity(accessToken string, workspaceId strin httpClient.SetAuthToken(accessToken). SetHeader("Accept", "application/json") - getSecretsRequest := api.GetEncryptedSecretsV3Request{ + getSecretsRequest := api.GetRawSecretsV3Request{ WorkspaceId: workspaceId, Environment: environmentName, IncludeImport: includeImports, @@ -171,7 +171,8 @@ func GetPlainTextSecretsViaMachineIdentity(accessToken string, workspaceId strin getSecretsRequest.SecretPath = secretsPath } - rawSecrets, err := api.CallGetRawSecretsV3(httpClient, api.GetRawSecretsV3Request{WorkspaceId: workspaceId, SecretPath: secretsPath, Environment: environmentName}) + rawSecrets, err := api.CallGetRawSecretsV3(httpClient, getSecretsRequest) + if err != nil { return models.PlaintextSecretResult{}, err } @@ -182,7 +183,7 @@ func GetPlainTextSecretsViaMachineIdentity(accessToken string, workspaceId strin } for _, secret := range rawSecrets.Secrets { - plainTextSecrets = append(plainTextSecrets, models.SingleEnvironmentVariable{Key: secret.SecretKey, Value: secret.SecretValue, WorkspaceId: secret.Workspace}) + plainTextSecrets = append(plainTextSecrets, models.SingleEnvironmentVariable{Key: secret.SecretKey, Value: secret.SecretValue, Type: secret.Type, WorkspaceId: secret.Workspace}) } // if includeImports { @@ -355,6 +356,11 @@ func GetAllEnvironmentVariables(params models.GetAllSecretsParameters, projectCo log.Debug().Msg("Trying to fetch secrets using service token") secretsToReturn, _, errorToReturn = GetPlainTextSecretsViaServiceToken(params.InfisicalToken, params.Environment, params.SecretsPath, params.IncludeImport, params.Recursive) } else if params.UniversalAuthAccessToken != "" { + + if params.WorkspaceId == "" { + PrintErrorMessageAndExit("Project ID is required when using machine identity") + } + log.Debug().Msg("Trying to fetch secrets using universal auth") res, err := GetPlainTextSecretsViaMachineIdentity(params.UniversalAuthAccessToken, params.WorkspaceId, params.Environment, params.SecretsPath, params.IncludeImport, params.Recursive) From 016f22c295df2dbc5a18e0c50a635dcf20d6e876 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Tue, 26 Mar 2024 23:54:11 +0100 Subject: [PATCH 09/35] Fix: Cleanup --- cli/packages/cmd/agent.go | 2 +- cli/packages/util/constants.go | 26 +++++++++++++------------- cli/packages/util/helper.go | 4 ++-- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/cli/packages/cmd/agent.go b/cli/packages/cmd/agent.go index d32afa986..7e8babb85 100644 --- a/cli/packages/cmd/agent.go +++ b/cli/packages/cmd/agent.go @@ -479,7 +479,7 @@ func (tm *AgentManager) GetToken() string { // Fetches a new access token using client credentials func (tm *AgentManager) FetchNewAccessToken() error { - clientID := os.Getenv("INFISICAL_UNIVERSAL_AUTH_CLIENT_ID") + clientID := os.Getenv(util.INFISICAL_UNIVERSAL_AUTH_CLIENT_ID_NAME) if clientID == "" { clientIDAsByte, err := ReadFile(tm.clientIdPath) if err != nil { diff --git a/cli/packages/util/constants.go b/cli/packages/util/constants.go index d4243208a..4525fe81c 100644 --- a/cli/packages/util/constants.go +++ b/cli/packages/util/constants.go @@ -1,19 +1,19 @@ package util const ( - CONFIG_FILE_NAME = "infisical-config.json" - CONFIG_FOLDER_NAME = ".infisical" - INFISICAL_DEFAULT_API_URL = "https://app.infisical.com/api" - INFISICAL_DEFAULT_URL = "https://app.infisical.com" - INFISICAL_WORKSPACE_CONFIG_FILE_NAME = ".infisical.json" - INFISICAL_TOKEN_NAME = "INFISICAL_TOKEN" - INFISICAL_UNIVERSAL_AUTH_CLIENT_ID = "INFISICAL_UNIVERSAL_AUTH_CLIENT_ID" - INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET = "INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET" - SECRET_TYPE_PERSONAL = "personal" - SECRET_TYPE_SHARED = "shared" - KEYRING_SERVICE_NAME = "infisical" - PERSONAL_SECRET_TYPE_NAME = "personal" - SHARED_SECRET_TYPE_NAME = "shared" + CONFIG_FILE_NAME = "infisical-config.json" + CONFIG_FOLDER_NAME = ".infisical" + INFISICAL_DEFAULT_API_URL = "https://app.infisical.com/api" + INFISICAL_DEFAULT_URL = "https://app.infisical.com" + INFISICAL_WORKSPACE_CONFIG_FILE_NAME = ".infisical.json" + INFISICAL_TOKEN_NAME = "INFISICAL_TOKEN" + INFISICAL_UNIVERSAL_AUTH_CLIENT_ID_NAME = "INFISICAL_UNIVERSAL_AUTH_CLIENT_ID" + INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET_NAME = "INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET" + SECRET_TYPE_PERSONAL = "personal" + SECRET_TYPE_SHARED = "shared" + KEYRING_SERVICE_NAME = "infisical" + PERSONAL_SECRET_TYPE_NAME = "personal" + SHARED_SECRET_TYPE_NAME = "shared" ) var ( diff --git a/cli/packages/util/helper.go b/cli/packages/util/helper.go index 4d8074ddd..932a2d068 100644 --- a/cli/packages/util/helper.go +++ b/cli/packages/util/helper.go @@ -95,11 +95,11 @@ func GetInfisicalUniversalAuthAccessToken(cmd *cobra.Command) (accessToken strin } if universalAuthClientId == "" { - universalAuthClientId = os.Getenv(INFISICAL_UNIVERSAL_AUTH_CLIENT_ID) + universalAuthClientId = os.Getenv(INFISICAL_UNIVERSAL_AUTH_CLIENT_ID_NAME) } if universalAuthClientSecret == "" { - universalAuthClientSecret = os.Getenv(INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET) + universalAuthClientSecret = os.Getenv(INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET_NAME) } if universalAuthClientId != "" || universalAuthClientSecret != "" { From 9193f13970d5d930ba3515232dc47ed3c887b4e6 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Fri, 5 Apr 2024 15:05:59 -0700 Subject: [PATCH 10/35] Feat: Added UA support to export command --- cli/packages/cmd/export.go | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/cli/packages/cmd/export.go b/cli/packages/cmd/export.go index 2a11274a1..34deaff67 100644 --- a/cli/packages/cmd/export.go +++ b/cli/packages/cmd/export.go @@ -59,17 +59,11 @@ var exportCmd = &cobra.Command{ util.HandleError(err, "Unable to parse flag") } - infisicalToken, err := util.GetInfisicalServiceToken(cmd) + token, err := util.GetInfisicalToken(cmd) if err != nil { util.HandleError(err, "Unable to parse flag") } - identityAccessToken, err := util.GetInfisicalUniversalAuthAccessToken(cmd) - - if err != nil { - util.HandleError(err, "Authentication with universal auth failed") - } - tagSlugs, err := cmd.Flags().GetString("tags") if err != nil { util.HandleError(err, "Unable to parse flag") @@ -80,7 +74,20 @@ var exportCmd = &cobra.Command{ util.HandleError(err, "Unable to parse flag") } - secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, UniversalAuthAccessToken: identityAccessToken, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, WorkspaceId: projectId, SecretsPath: secretsPath}, "") + request := models.GetAllSecretsParameters{ + Environment: environmentName, + TagSlugs: tagSlugs, + WorkspaceId: projectId, + SecretsPath: secretsPath, + } + + if token != nil && token.Type == "service-token" { + request.InfisicalToken = token.Token + } else if token != nil && token.Type == "universal-auth-token" { + request.UniversalAuthAccessToken = token.Token + } + + secrets, err := util.GetAllEnvironmentVariables(request, "") if err != nil { util.HandleError(err, "Unable to fetch secrets") } @@ -93,9 +100,16 @@ var exportCmd = &cobra.Command{ var output string if shouldExpandSecrets { - secrets = util.ExpandSecrets(secrets, models.ExpandSecretsAuthentication{ - InfisicalToken: infisicalToken, - }, "") + + authParams := models.ExpandSecretsAuthentication{} + + if token != nil && token.Type == "service-token" { + authParams.InfisicalToken = token.Token + } else if token != nil && token.Type == "universal-auth-token" { + authParams.UniversalAuthAccessToken = token.Token + } + + secrets = util.ExpandSecrets(secrets, authParams, "") } secrets = util.FilterSecretsByTag(secrets, tagSlugs) output, err = formatEnvs(secrets, format) @@ -116,8 +130,6 @@ func init() { exportCmd.Flags().StringP("format", "f", "dotenv", "Set the format of the output file (dotenv, json, csv)") exportCmd.Flags().Bool("secret-overriding", true, "Prioritizes personal secrets, if any, with the same name over shared secrets") exportCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") - exportCmd.Flags().String("universal-auth-client-id", "", "Machine Identity universal auth client ID") - exportCmd.Flags().String("universal-auth-client-secret", "", "Machine Identity universal auth client secret") exportCmd.Flags().StringP("tags", "t", "", "filter secrets by tag slugs") exportCmd.Flags().String("projectId", "", "manually set the projectId to fetch secrets from") exportCmd.Flags().String("path", "/", "get secrets within a folder path") From c4e3dd84e3b84112a9f328de920abc2ddf1fc07c Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Fri, 5 Apr 2024 15:06:14 -0700 Subject: [PATCH 11/35] Feat: Added UA support to folder command --- cli/packages/cmd/folder.go | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/cli/packages/cmd/folder.go b/cli/packages/cmd/folder.go index dc2298980..247050c90 100644 --- a/cli/packages/cmd/folder.go +++ b/cli/packages/cmd/folder.go @@ -41,21 +41,28 @@ var getCmd = &cobra.Command{ util.HandleError(err, "Unable to parse flag") } - infisicalToken, err := util.GetInfisicalServiceToken(cmd) + token, err := util.GetInfisicalToken(cmd) if err != nil { util.HandleError(err, "Unable to parse flag") } - identityAccessToken, err := util.GetInfisicalUniversalAuthAccessToken(cmd) - if err != nil { - util.HandleError(err, "Unable to parse flag") - } - foldersPath, err := cmd.Flags().GetString("path") if err != nil { util.HandleError(err, "Unable to parse flag") } - folders, err := util.GetAllFolders(models.GetAllFoldersParameters{Environment: environmentName, InfisicalToken: infisicalToken, UniversalAuthAccessToken: identityAccessToken, FoldersPath: foldersPath, WorkspaceId: projectId}) + request := models.GetAllFoldersParameters{ + Environment: environmentName, + WorkspaceId: projectId, + FoldersPath: foldersPath, + } + + if token != nil && token.Type == "service-token" { + request.InfisicalToken = token.Token + } else if token != nil && token.Type == "universal-auth-token" { + request.UniversalAuthAccessToken = token.Token + } + + folders, err := util.GetAllFolders(request) if err != nil { util.HandleError(err, "Unable to get folders") } From 7d0a535f46a2a610af68145b019958f2ee60521e Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Fri, 5 Apr 2024 15:06:44 -0700 Subject: [PATCH 12/35] Feat: Added UA login support (defaults to 'user') --- cli/packages/cmd/login.go | 206 ++++++++++++++++++++++++-------------- 1 file changed, 131 insertions(+), 75 deletions(-) diff --git a/cli/packages/cmd/login.go b/cli/packages/cmd/login.go index f0337f658..039540865 100644 --- a/cli/packages/cmd/login.go +++ b/cli/packages/cmd/login.go @@ -55,95 +55,148 @@ var loginCmd = &cobra.Command{ Short: "Login into your Infisical account", DisableFlagsInUseLine: true, Run: func(cmd *cobra.Command, args []string) { - currentLoggedInUserDetails, err := util.GetCurrentLoggedInUserDetails() - // if the key can't be found or there is an error getting current credentials from key ring, allow them to override - if err != nil && (strings.Contains(err.Error(), "we couldn't find your logged in details")) { - log.Debug().Err(err) - } else if err != nil { + + loginMethod, err := cmd.Flags().GetString("method") + + if err != nil { util.HandleError(err) } - if currentLoggedInUserDetails.IsUserLoggedIn && !currentLoggedInUserDetails.LoginExpired && len(currentLoggedInUserDetails.UserCredentials.PrivateKey) != 0 { - shouldOverride, err := userLoginMenu(currentLoggedInUserDetails.UserCredentials.Email) - if err != nil { + if loginMethod != "user" && loginMethod != "universal-auth" { + util.PrintErrorMessageAndExit("Invalid login method. Please use either 'user' or 'universal-auth'") + } + + if loginMethod == "user" { + + currentLoggedInUserDetails, err := util.GetCurrentLoggedInUserDetails() + // if the key can't be found or there is an error getting current credentials from key ring, allow them to override + if err != nil && (strings.Contains(err.Error(), "we couldn't find your logged in details")) { + log.Debug().Err(err) + } else if err != nil { util.HandleError(err) } - if !shouldOverride { - return + if currentLoggedInUserDetails.IsUserLoggedIn && !currentLoggedInUserDetails.LoginExpired && len(currentLoggedInUserDetails.UserCredentials.PrivateKey) != 0 { + shouldOverride, err := userLoginMenu(currentLoggedInUserDetails.UserCredentials.Email) + if err != nil { + util.HandleError(err) + } + + if !shouldOverride { + return + } } - } - //override domain - domainQuery := true - if config.INFISICAL_URL_MANUAL_OVERRIDE != "" && config.INFISICAL_URL_MANUAL_OVERRIDE != util.INFISICAL_DEFAULT_API_URL { - overrideDomain, err := DomainOverridePrompt() - if err != nil { - util.HandleError(err) + //override domain + domainQuery := true + if config.INFISICAL_URL_MANUAL_OVERRIDE != "" && config.INFISICAL_URL_MANUAL_OVERRIDE != util.INFISICAL_DEFAULT_API_URL { + overrideDomain, err := DomainOverridePrompt() + if err != nil { + util.HandleError(err) + } + + //if not override set INFISICAL_URL to exported var + //set domainQuery to false + if !overrideDomain { + domainQuery = false + config.INFISICAL_URL = config.INFISICAL_URL_MANUAL_OVERRIDE + } + } - //if not override set INFISICAL_URL to exported var - //set domainQuery to false - if !overrideDomain { - domainQuery = false - config.INFISICAL_URL = config.INFISICAL_URL_MANUAL_OVERRIDE + //prompt user to select domain between Infisical cloud and self hosting + if domainQuery { + err = askForDomain() + if err != nil { + util.HandleError(err, "Unable to parse domain url") + } } + var userCredentialsToBeStored models.UserCredentials - } - - //prompt user to select domain between Infisical cloud and self hosting - if domainQuery { - err = askForDomain() - if err != nil { - util.HandleError(err, "Unable to parse domain url") - } - } - var userCredentialsToBeStored models.UserCredentials - - interactiveLogin := false - if cmd.Flags().Changed("interactive") { - interactiveLogin = true - cliDefaultLogin(&userCredentialsToBeStored) - } - - //call browser login function - if !interactiveLogin { - fmt.Println("Logging in via browser... To login via interactive mode run [infisical login -i]") - userCredentialsToBeStored, err = browserCliLogin() - if err != nil { - //default to cli login on error + interactiveLogin := false + if cmd.Flags().Changed("interactive") { + interactiveLogin = true cliDefaultLogin(&userCredentialsToBeStored) } + + //call browser login function + if !interactiveLogin { + fmt.Println("Logging in via browser... To login via interactive mode run [infisical login -i]") + userCredentialsToBeStored, err = browserCliLogin() + if err != nil { + //default to cli login on error + cliDefaultLogin(&userCredentialsToBeStored) + } + } + + err = util.StoreUserCredsInKeyRing(&userCredentialsToBeStored) + if err != nil { + log.Error().Msgf("Unable to store your credentials in system vault [%s]") + log.Error().Msgf("\nTo trouble shoot further, read https://infisical.com/docs/cli/faq") + log.Debug().Err(err) + //return here + util.HandleError(err) + } + + err = util.WriteInitalConfig(&userCredentialsToBeStored) + if err != nil { + util.HandleError(err, "Unable to write write to Infisical Config file. Please try again") + } + + // clear backed up secrets from prev account + util.DeleteBackupSecrets() + + whilte := color.New(color.FgGreen) + boldWhite := whilte.Add(color.Bold) + time.Sleep(time.Second * 1) + boldWhite.Printf(">>>> Welcome to Infisical!") + boldWhite.Printf(" You are now logged in as %v <<<< \n", userCredentialsToBeStored.Email) + + plainBold := color.New(color.Bold) + + plainBold.Println("\nQuick links") + fmt.Println("- Learn to inject secrets into your application at https://infisical.com/docs/cli/usage") + fmt.Println("- Stuck? Join our slack for quick support https://infisical.com/slack") + Telemetry.CaptureEvent("cli-command:login", posthog.NewProperties().Set("infisical-backend", config.INFISICAL_URL).Set("version", util.CLI_VERSION)) + } else if loginMethod == "universal-auth" { + + clientId, err := cmd.Flags().GetString("client-id") + if err != nil { + util.HandleError(err) + } + + clientSecret, err := cmd.Flags().GetString("client-secret") + if err != nil { + util.HandleError(err) + } + + if clientId == "" { + clientId = os.Getenv(util.INFISICAL_UNIVERSAL_AUTH_CLIENT_ID_NAME) + if clientId == "" { + util.PrintErrorMessageAndExit("Please provide client-id") + } + } + if clientSecret == "" { + clientSecret = os.Getenv(util.INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET_NAME) + if clientSecret == "" { + util.PrintErrorMessageAndExit("Please provide client-secret") + } + } + + res, err := util.UniversalAuthLogin(clientId, clientSecret) + + if err != nil { + util.HandleError(err) + } + + boldGreen := color.New(color.FgGreen).Add(color.Bold) + time.Sleep(time.Second * 1) + boldGreen.Printf(">>>> Successfully authenticated with Universal Auth!\n\n") + boldGreen.Printf("Universal Auth Access Token:\n%v", res.AccessToken) + + plainBold := color.New(color.Bold) + plainBold.Println("\n\nYou can use this access token to authenticate through other commands in the CLI.") + } - - err = util.StoreUserCredsInKeyRing(&userCredentialsToBeStored) - if err != nil { - log.Error().Msgf("Unable to store your credentials in system vault [%s]") - log.Error().Msgf("\nTo trouble shoot further, read https://infisical.com/docs/cli/faq") - log.Debug().Err(err) - //return here - util.HandleError(err) - } - - err = util.WriteInitalConfig(&userCredentialsToBeStored) - if err != nil { - util.HandleError(err, "Unable to write write to Infisical Config file. Please try again") - } - - // clear backed up secrets from prev account - util.DeleteBackupSecrets() - - whilte := color.New(color.FgGreen) - boldWhite := whilte.Add(color.Bold) - time.Sleep(time.Second * 1) - boldWhite.Printf(">>>> Welcome to Infisical!") - boldWhite.Printf(" You are now logged in as %v <<<< \n", userCredentialsToBeStored.Email) - - plainBold := color.New(color.Bold) - - plainBold.Println("\nQuick links") - fmt.Println("- Learn to inject secrets into your application at https://infisical.com/docs/cli/usage") - fmt.Println("- Stuck? Join our slack for quick support https://infisical.com/slack") - Telemetry.CaptureEvent("cli-command:login", posthog.NewProperties().Set("infisical-backend", config.INFISICAL_URL).Set("version", util.CLI_VERSION)) }, } @@ -313,6 +366,9 @@ func cliDefaultLogin(userCredentialsToBeStored *models.UserCredentials) { func init() { rootCmd.AddCommand(loginCmd) loginCmd.Flags().BoolP("interactive", "i", false, "login via the command line") + loginCmd.Flags().String("method", "user", "login method [user, universal-auth]") + loginCmd.Flags().String("client-id", "", "client id for universal auth") + loginCmd.Flags().String("client-secret", "", "client secret for universal auth") } func DomainOverridePrompt() (bool, error) { From a651de53d13b270998a3ae304118ac30b13ff74b Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Fri, 5 Apr 2024 15:06:52 -0700 Subject: [PATCH 13/35] Feat: Added UA support to run command --- cli/packages/cmd/run.go | 48 ++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/cli/packages/cmd/run.go b/cli/packages/cmd/run.go index fe5afb782..8481277e9 100644 --- a/cli/packages/cmd/run.go +++ b/cli/packages/cmd/run.go @@ -62,11 +62,7 @@ var runCmd = &cobra.Command{ } } - infisicalToken, err := util.GetInfisicalServiceToken(cmd) - if err != nil { - util.HandleError(err, "Unable to parse flag") - } - identityAccessToken, err := util.GetInfisicalUniversalAuthAccessToken(cmd) + token, err := util.GetInfisicalToken(cmd) if err != nil { util.HandleError(err, "Unable to parse flag") } @@ -111,7 +107,22 @@ var runCmd = &cobra.Command{ util.HandleError(err, "Unable to parse flag") } - secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, UniversalAuthAccessToken: identityAccessToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: includeImports, Recursive: recursive}, projectConfigDir) + request := models.GetAllSecretsParameters{ + Environment: environmentName, + WorkspaceId: projectId, + TagSlugs: tagSlugs, + SecretsPath: secretsPath, + IncludeImport: includeImports, + Recursive: recursive, + } + + if token != nil && token.Type == "service-token" { + request.InfisicalToken = token.Token + } else if token != nil && token.Type == "universal-auth-token" { + request.UniversalAuthAccessToken = token.Token + } + + secrets, err := util.GetAllEnvironmentVariables(request, projectConfigDir) if err != nil { util.HandleError(err, "Could not fetch secrets", "If you are using a service token to fetch secrets, please ensure it is valid") @@ -124,9 +135,16 @@ var runCmd = &cobra.Command{ } if shouldExpandSecrets { - secrets = util.ExpandSecrets(secrets, models.ExpandSecretsAuthentication{ - InfisicalToken: infisicalToken, - }, projectConfigDir) + + authParams := models.ExpandSecretsAuthentication{} + + if token != nil && token.Type == "service-token" { + authParams.InfisicalToken = token.Token + } else if token != nil && token.Type == "universal-auth-token" { + authParams.UniversalAuthAccessToken = token.Token + } + + secrets = util.ExpandSecrets(secrets, authParams, projectConfigDir) } secretsByKey := getSecretsByKeys(secrets) @@ -157,7 +175,15 @@ var runCmd = &cobra.Command{ log.Debug().Msgf("injecting the following environment variables into shell: %v", env) - Telemetry.CaptureEvent("cli-command:run", posthog.NewProperties().Set("secretsCount", len(secrets)).Set("environment", environmentName).Set("isUsingServiceToken", infisicalToken != "").Set("single-command", strings.Join(args, " ")).Set("multi-command", cmd.Flag("command").Value.String()).Set("version", util.CLI_VERSION)) + Telemetry.CaptureEvent("cli-command:run", + posthog.NewProperties(). + Set("secretsCount", len(secrets)). + Set("environment", environmentName). + Set("isUsingServiceToken", token.Type == "service-token"). + Set("isUsingUniversalAuthToken", token.Type == "universal-auth-token"). + Set("single-command", strings.Join(args, " ")). + Set("multi-command", cmd.Flag("command").Value.String()). + Set("version", util.CLI_VERSION)) if cmd.Flags().Changed("command") { command := cmd.Flag("command").Value.String() @@ -212,8 +238,6 @@ func filterReservedEnvVars(env map[string]models.SingleEnvironmentVariable) { func init() { rootCmd.AddCommand(runCmd) runCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") - runCmd.Flags().String("universal-auth-client-id", "", "Machine Identity universal auth client ID") - runCmd.Flags().String("universal-auth-client-secret", "", "Machine Identity universal auth client secret") runCmd.Flags().String("projectId", "", "manually set the projectId to fetch folders from for machine identity") runCmd.Flags().StringP("env", "e", "dev", "Set the environment (dev, prod, etc.) from which your secrets should be pulled from") runCmd.Flags().Bool("expand", true, "Parse shell parameter expansions in your secrets") From b135258cce36d4a9b0111784a92b47b9e37f3ec0 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Fri, 5 Apr 2024 15:06:58 -0700 Subject: [PATCH 14/35] Feat: Added UA support to secret commands --- cli/packages/cmd/secrets.go | 91 ++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 32 deletions(-) diff --git a/cli/packages/cmd/secrets.go b/cli/packages/cmd/secrets.go index e0b564f53..8c28b4cbc 100644 --- a/cli/packages/cmd/secrets.go +++ b/cli/packages/cmd/secrets.go @@ -38,12 +38,7 @@ var secretsCmd = &cobra.Command{ } } - infisicalToken, err := util.GetInfisicalServiceToken(cmd) - if err != nil { - util.HandleError(err, "Unable to parse flag") - } - - identityAccessToken, err := util.GetInfisicalUniversalAuthAccessToken(cmd) + token, err := util.GetInfisicalToken(cmd) if err != nil { util.HandleError(err, "Unable to parse flag") } @@ -83,7 +78,22 @@ var secretsCmd = &cobra.Command{ util.HandleError(err, "Unable to parse flag") } - secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, WorkspaceId: projectId, InfisicalToken: infisicalToken, UniversalAuthAccessToken: identityAccessToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: includeImports, Recursive: recursive}, "") + request := models.GetAllSecretsParameters{ + Environment: environmentName, + WorkspaceId: projectId, + TagSlugs: tagSlugs, + SecretsPath: secretsPath, + IncludeImport: includeImports, + Recursive: recursive, + } + + if token != nil && token.Type == "service-token" { + request.InfisicalToken = token.Token + } else if token != nil && token.Type == "universal-auth-token" { + request.UniversalAuthAccessToken = token.Token + } + + secrets, err := util.GetAllEnvironmentVariables(request, "") if err != nil { util.HandleError(err) } @@ -95,9 +105,15 @@ var secretsCmd = &cobra.Command{ } if shouldExpandSecrets { - secrets = util.ExpandSecrets(secrets, models.ExpandSecretsAuthentication{ - InfisicalToken: infisicalToken, - }, "") + + authParams := models.ExpandSecretsAuthentication{} + if token != nil && token.Type == "service-token" { + authParams.InfisicalToken = token.Token + } else if token != nil && token.Type == "universal-auth-token" { + authParams.UniversalAuthAccessToken = token.Token + } + + secrets = util.ExpandSecrets(secrets, authParams, "") } visualize.PrintAllSecretDetails(secrets) @@ -407,15 +423,10 @@ func getSecretsByNames(cmd *cobra.Command, args []string) { } } - infisicalToken, err := util.GetInfisicalServiceToken(cmd) + token, err := util.GetInfisicalToken(cmd) if err != nil { util.HandleError(err, "Unable to parse flag") } - identityAccessToken, err := util.GetInfisicalUniversalAuthAccessToken(cmd) - if err != nil { - util.HandleError(err, "Unable to parse flag") - } - tagSlugs, err := cmd.Flags().GetString("tags") if err != nil { util.HandleError(err, "Unable to parse flag") @@ -441,7 +452,22 @@ func getSecretsByNames(cmd *cobra.Command, args []string) { util.HandleError(err, "Unable to parse path flag") } - secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, WorkspaceId: projectId, InfisicalToken: infisicalToken, UniversalAuthAccessToken: identityAccessToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: true, Recursive: recursive}, "") + request := models.GetAllSecretsParameters{ + Environment: environmentName, + WorkspaceId: projectId, + TagSlugs: tagSlugs, + SecretsPath: secretsPath, + IncludeImport: true, + Recursive: recursive, + } + + if token != nil && token.Type == "service-token" { + request.InfisicalToken = token.Token + } else if token != nil && token.Type == "universal-auth-token" { + request.UniversalAuthAccessToken = token.Token + } + + secrets, err := util.GetAllEnvironmentVariables(request, "") if err != nil { util.HandleError(err, "To fetch all secrets") } @@ -488,12 +514,7 @@ func generateExampleEnv(cmd *cobra.Command, args []string) { util.HandleError(err, "Unable to parse flag") } - infisicalToken, err := util.GetInfisicalServiceToken(cmd) - if err != nil { - util.HandleError(err, "Unable to parse flag") - } - - identityAccessToken, err := util.GetInfisicalUniversalAuthAccessToken(cmd) + token, err := util.GetInfisicalToken(cmd) if err != nil { util.HandleError(err, "Unable to parse flag") } @@ -508,7 +529,21 @@ func generateExampleEnv(cmd *cobra.Command, args []string) { util.HandleError(err, "Unable to parse flag") } - secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, WorkspaceId: projectId, InfisicalToken: infisicalToken, UniversalAuthAccessToken: identityAccessToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: true}, "") + request := models.GetAllSecretsParameters{ + Environment: environmentName, + WorkspaceId: projectId, + TagSlugs: tagSlugs, + SecretsPath: secretsPath, + IncludeImport: true, + } + + if token != nil && token.Type == "service-token" { + request.InfisicalToken = token.Token + } else if token != nil && token.Type == "universal-auth-token" { + request.UniversalAuthAccessToken = token.Token + } + + secrets, err := util.GetAllEnvironmentVariables(request, "") if err != nil { util.HandleError(err, "To fetch all secrets") } @@ -708,15 +743,11 @@ func getSecretsByKeys(secrets []models.SingleEnvironmentVariable) map[string]mod func init() { secretsGenerateExampleEnvCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") - secretsGenerateExampleEnvCmd.Flags().String("universal-auth-client-id", "", "Machine Identity universal auth client ID") - secretsGenerateExampleEnvCmd.Flags().String("universal-auth-client-secret", "", "Machine Identity universal auth client secret") secretsGenerateExampleEnvCmd.Flags().String("projectId", "", "manually set the projectId to fetch folders from for machine identity") secretsGenerateExampleEnvCmd.Flags().String("path", "/", "Fetch secrets from within a folder path") secretsCmd.AddCommand(secretsGenerateExampleEnvCmd) secretsGetCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") - secretsGetCmd.Flags().String("universal-auth-client-id", "", "Machine Identity universal auth client ID") - secretsGetCmd.Flags().String("universal-auth-client-secret", "", "Machine Identity universal auth client secret") secretsGetCmd.Flags().String("projectId", "", "manually set the projectId to fetch folders from for machine identity") secretsGetCmd.Flags().String("path", "/", "get secrets within a folder path") secretsGetCmd.Flags().Bool("raw-value", false, "Returns only the value of secret, only works with one secret") @@ -749,8 +780,6 @@ func init() { // Add getCmd, createCmd and deleteCmd flags here getCmd.Flags().StringP("path", "p", "/", "The path from where folders should be fetched from") getCmd.Flags().String("token", "", "Fetch folders using the infisical token") - getCmd.Flags().String("universal-auth-client-id", "", "Machine Identity universal auth client ID") - getCmd.Flags().String("universal-auth-client-secret", "", "Machine Identity universal auth client secret") getCmd.Flags().String("projectId", "", "manually set the projectId to fetch folders from for machine identity") folderCmd.AddCommand(getCmd) @@ -769,8 +798,6 @@ func init() { // ** End of folders sub command secretsCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") - secretsCmd.Flags().String("universal-auth-client-id", "", "Machine Identity universal auth client ID") - secretsCmd.Flags().String("universal-auth-client-secret", "", "Machine Identity universal auth client secret") secretsCmd.Flags().String("projectId", "", "manually set the projectId to fetch folders from for machine identity") secretsCmd.PersistentFlags().String("env", "dev", "Used to select the environment name on which actions should be taken on") secretsCmd.Flags().Bool("expand", true, "Parse shell parameter expansions in your secrets") From f1805811aad7d6ba1aed8def0754b259d7dbc91f Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Fri, 5 Apr 2024 15:07:14 -0700 Subject: [PATCH 15/35] Feat: Added token renew command --- cli/packages/cmd/token.go | 63 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 cli/packages/cmd/token.go diff --git a/cli/packages/cmd/token.go b/cli/packages/cmd/token.go new file mode 100644 index 000000000..3e5d42765 --- /dev/null +++ b/cli/packages/cmd/token.go @@ -0,0 +1,63 @@ +/* +Copyright (c) 2023 Infisical Inc. +*/ +package cmd + +import ( + "strings" + "time" + + "github.com/Infisical/infisical-merge/packages/util" + "github.com/fatih/color" + "github.com/spf13/cobra" +) + +var tokenCmd = &cobra.Command{ + Use: "token", + Short: "Manage your access tokens", + DisableFlagsInUseLine: true, + Example: "infisical token", + Args: cobra.ExactArgs(0), + PreRun: func(cmd *cobra.Command, args []string) { + util.RequireLogin() + }, + Run: func(cmd *cobra.Command, args []string) { + }, +} + +var tokenRenewCmd = &cobra.Command{ + Use: "renew [token]", + Short: "Used to renew your universal auth access token", + DisableFlagsInUseLine: true, + Example: "infisical token renew ", + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + // args[0] will be the from your command call + token := args[0] + + if strings.HasPrefix(token, "st.") { + util.PrintErrorMessageAndExit("You are trying to renew a service token. You can only renew universal auth access tokens.") + } + + renewedAccessToken, err := util.RenewUniversalAuthAccessToken(token) + + if err != nil { + util.HandleError(err, "Unable to renew token") + } + + boldGreen := color.New(color.FgGreen).Add(color.Bold) + time.Sleep(time.Second * 1) + boldGreen.Printf(">>>> Successfully renewed token!\n\n") + boldGreen.Printf("Renewed Access Token:\n%v", renewedAccessToken) + + plainBold := color.New(color.Bold) + plainBold.Println("\n\nYou can use the new access token to authenticate through other commands in the CLI.") + + }, +} + +func init() { + tokenCmd.AddCommand(tokenRenewCmd) + + rootCmd.AddCommand(tokenCmd) +} From 9ad5e082e2572d955f4729f870d03b71fca0c466 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Fri, 5 Apr 2024 15:07:24 -0700 Subject: [PATCH 16/35] Feat: UA CLI support --- cli/packages/util/constants.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cli/packages/util/constants.go b/cli/packages/util/constants.go index 4525fe81c..120548c10 100644 --- a/cli/packages/util/constants.go +++ b/cli/packages/util/constants.go @@ -9,6 +9,7 @@ const ( INFISICAL_TOKEN_NAME = "INFISICAL_TOKEN" INFISICAL_UNIVERSAL_AUTH_CLIENT_ID_NAME = "INFISICAL_UNIVERSAL_AUTH_CLIENT_ID" INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET_NAME = "INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET" + INFISICAL_UNIVERSAL_AUTH_ACCESS_TOKEN_NAME = "INFISICAL_UNIVERSAL_AUTH_ACCESS_TOKEN" SECRET_TYPE_PERSONAL = "personal" SECRET_TYPE_SHARED = "shared" KEYRING_SERVICE_NAME = "infisical" From b6b040375bd294901847bfd422995f355c0a9931 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Fri, 5 Apr 2024 15:08:32 -0700 Subject: [PATCH 17/35] Feat: UA CLI Support --- cli/packages/models/cli.go | 5 ++++ cli/packages/util/helper.go | 54 ++++++++++++++++++++++++++++++++----- 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/cli/packages/models/cli.go b/cli/packages/models/cli.go index 73db3d908..68527c469 100644 --- a/cli/packages/models/cli.go +++ b/cli/packages/models/cli.go @@ -59,6 +59,11 @@ type DynamicSecretLease struct { Data map[string]interface{} `json:"data"` } +type TokenDetails struct { + Type string + Token string +} + type SingleFolder struct { ID string `json:"_id"` Name string `json:"name"` diff --git a/cli/packages/util/helper.go b/cli/packages/util/helper.go index 932a2d068..46eacb8af 100644 --- a/cli/packages/util/helper.go +++ b/cli/packages/util/helper.go @@ -67,18 +67,39 @@ func IsSecretTypeValid(s string) bool { return false } -func GetInfisicalServiceToken(cmd *cobra.Command) (serviceToken string, err error) { +func GetInfisicalToken(cmd *cobra.Command) (token *models.TokenDetails, err error) { infisicalToken, err := cmd.Flags().GetString("token") - if infisicalToken == "" { - infisicalToken = os.Getenv(INFISICAL_TOKEN_NAME) - } - if err != nil { - return "", err + return nil, err } - return infisicalToken, 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) + // If it's still empty after the first env check, we check for the service token env variable. + if infisicalToken == "" { + infisicalToken = os.Getenv(INFISICAL_TOKEN_NAME) + } + } + + // If it's empty, we return nothing at all. + if infisicalToken == "" { + return nil, nil + } + + if strings.HasPrefix(infisicalToken, "st.") { + return &models.TokenDetails{ + Type: "service-token", + Token: infisicalToken, + }, nil + } + + return &models.TokenDetails{ + Type: "universal-auth-token", + Token: infisicalToken, + }, nil + } func GetInfisicalUniversalAuthAccessToken(cmd *cobra.Command) (accessToken string, err error) { @@ -128,6 +149,25 @@ func UniversalAuthLogin(clientId string, clientSecret string) (api.UniversalAuth return tokenResponse, nil } +func RenewUniversalAuthAccessToken(accessToken string) (string, error) { + + httpClient := resty.New() + httpClient.SetRetryCount(10000). + SetRetryMaxWaitTime(20 * time.Second). + SetRetryWaitTime(5 * time.Second) + + request := api.UniversalAuthRefreshRequest{ + AccessToken: accessToken, + } + + tokenResponse, err := api.CallUniversalAuthRefreshAccessToken(httpClient, request) + if err != nil { + return "", err + } + + return tokenResponse.AccessToken, nil +} + // Checks if the passed in email already exists in the users slice func ConfigContainsEmail(users []models.LoggedInUser, email string) bool { for _, value := range users { From 66c48fbff873dc46ddc4cea71e7f457a80c25afa Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Fri, 5 Apr 2024 15:16:12 -0700 Subject: [PATCH 18/35] Update model.go --- cli/packages/api/model.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cli/packages/api/model.go b/cli/packages/api/model.go index ed9a1d629..0a5bfee6d 100644 --- a/cli/packages/api/model.go +++ b/cli/packages/api/model.go @@ -528,6 +528,7 @@ type GetRawSecretsV3Request struct { WorkspaceId string `json:"workspaceId"` SecretPath string `json:"secretPath"` IncludeImport bool `json:"include_imports"` + Recursive bool `json:"recursive"` } type GetRawSecretsV3Response struct { From 3793858f0a0f1a49769f8304dc291b0d5c5c42bc Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Tue, 26 Mar 2024 23:31:35 +0100 Subject: [PATCH 19/35] Feat: Export support for Machine Identities --- cli/packages/cmd/export.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cli/packages/cmd/export.go b/cli/packages/cmd/export.go index 34deaff67..c2159bf54 100644 --- a/cli/packages/cmd/export.go +++ b/cli/packages/cmd/export.go @@ -64,6 +64,10 @@ var exportCmd = &cobra.Command{ util.HandleError(err, "Unable to parse flag") } + if err != nil { + util.HandleError(err, "Authentication with universal auth failed") + } + tagSlugs, err := cmd.Flags().GetString("tags") if err != nil { util.HandleError(err, "Unable to parse flag") @@ -130,6 +134,8 @@ func init() { exportCmd.Flags().StringP("format", "f", "dotenv", "Set the format of the output file (dotenv, json, csv)") exportCmd.Flags().Bool("secret-overriding", true, "Prioritizes personal secrets, if any, with the same name over shared secrets") exportCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") + exportCmd.Flags().String("universal-auth-client-id", "", "Machine Identity universal auth client ID") + exportCmd.Flags().String("universal-auth-client-secret", "", "Machine Identity universal auth client secret") exportCmd.Flags().StringP("tags", "t", "", "filter secrets by tag slugs") exportCmd.Flags().String("projectId", "", "manually set the projectId to fetch secrets from") exportCmd.Flags().String("path", "/", "get secrets within a folder path") From a97737ab90ce9ffabf3edba1aeb24d1026b57050 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Tue, 26 Mar 2024 23:36:57 +0100 Subject: [PATCH 20/35] Feat: Folder support for Machine Identities --- cli/packages/util/helper.go | 47 +++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/cli/packages/util/helper.go b/cli/packages/util/helper.go index 46eacb8af..32da1c6ab 100644 --- a/cli/packages/util/helper.go +++ b/cli/packages/util/helper.go @@ -168,6 +168,53 @@ func RenewUniversalAuthAccessToken(accessToken string) (string, error) { return tokenResponse.AccessToken, nil } +func GetInfisicalUniversalAuthAccessToken(cmd *cobra.Command) (accessToken string, err error) { + + var token string + + universalAuthClientId, err := cmd.Flags().GetString("universal-auth-client-id") + if err != nil { + return token, err + } + universalAuthClientSecret, err := cmd.Flags().GetString("universal-auth-client-secret") + if err != nil { + return token, err + } + + if universalAuthClientId == "" { + universalAuthClientId = os.Getenv(INFISICAL_UNIVERSAL_AUTH_CLIENT_ID) + } + + if universalAuthClientSecret == "" { + universalAuthClientSecret = os.Getenv(INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET) + } + + if universalAuthClientId != "" || universalAuthClientSecret != "" { + res, err := UniversalAuthLogin(universalAuthClientId, universalAuthClientSecret) + + if err != nil { + return token, err + } + token = res.AccessToken + } + + return token, nil +} + +func UniversalAuthLogin(clientId string, clientSecret string) (api.UniversalAuthLoginResponse, error) { + httpClient := resty.New() + httpClient.SetRetryCount(10000). + SetRetryMaxWaitTime(20 * time.Second). + SetRetryWaitTime(5 * time.Second) + + tokenResponse, err := api.CallUniversalAuthLogin(httpClient, api.UniversalAuthLoginRequest{ClientId: clientId, ClientSecret: clientSecret}) + if err != nil { + return api.UniversalAuthLoginResponse{}, err + } + + return tokenResponse, nil +} + // Checks if the passed in email already exists in the users slice func ConfigContainsEmail(users []models.LoggedInUser, email string) bool { for _, value := range users { From 85ea6d2585b76e5cce406fb4217d0775d126f575 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Tue, 26 Mar 2024 23:54:11 +0100 Subject: [PATCH 21/35] Fix: Cleanup --- cli/packages/util/helper.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/packages/util/helper.go b/cli/packages/util/helper.go index 32da1c6ab..5bcade988 100644 --- a/cli/packages/util/helper.go +++ b/cli/packages/util/helper.go @@ -182,11 +182,11 @@ func GetInfisicalUniversalAuthAccessToken(cmd *cobra.Command) (accessToken strin } if universalAuthClientId == "" { - universalAuthClientId = os.Getenv(INFISICAL_UNIVERSAL_AUTH_CLIENT_ID) + universalAuthClientId = os.Getenv(INFISICAL_UNIVERSAL_AUTH_CLIENT_ID_NAME) } if universalAuthClientSecret == "" { - universalAuthClientSecret = os.Getenv(INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET) + universalAuthClientSecret = os.Getenv(INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET_NAME) } if universalAuthClientId != "" || universalAuthClientSecret != "" { From bf60489fde0c28c615380489ac9ac6fc4e920024 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Fri, 5 Apr 2024 15:05:59 -0700 Subject: [PATCH 22/35] Feat: Added UA support to export command --- cli/packages/cmd/export.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/cli/packages/cmd/export.go b/cli/packages/cmd/export.go index c2159bf54..34deaff67 100644 --- a/cli/packages/cmd/export.go +++ b/cli/packages/cmd/export.go @@ -64,10 +64,6 @@ var exportCmd = &cobra.Command{ util.HandleError(err, "Unable to parse flag") } - if err != nil { - util.HandleError(err, "Authentication with universal auth failed") - } - tagSlugs, err := cmd.Flags().GetString("tags") if err != nil { util.HandleError(err, "Unable to parse flag") @@ -134,8 +130,6 @@ func init() { exportCmd.Flags().StringP("format", "f", "dotenv", "Set the format of the output file (dotenv, json, csv)") exportCmd.Flags().Bool("secret-overriding", true, "Prioritizes personal secrets, if any, with the same name over shared secrets") exportCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") - exportCmd.Flags().String("universal-auth-client-id", "", "Machine Identity universal auth client ID") - exportCmd.Flags().String("universal-auth-client-secret", "", "Machine Identity universal auth client secret") exportCmd.Flags().StringP("tags", "t", "", "filter secrets by tag slugs") exportCmd.Flags().String("projectId", "", "manually set the projectId to fetch secrets from") exportCmd.Flags().String("path", "/", "get secrets within a folder path") From b4236966306f4c29ed81bc4a60d318727f75484c Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Fri, 5 Apr 2024 15:08:32 -0700 Subject: [PATCH 23/35] Feat: UA CLI Support --- cli/packages/util/helper.go | 47 ------------------------------------- 1 file changed, 47 deletions(-) diff --git a/cli/packages/util/helper.go b/cli/packages/util/helper.go index 5bcade988..46eacb8af 100644 --- a/cli/packages/util/helper.go +++ b/cli/packages/util/helper.go @@ -168,53 +168,6 @@ func RenewUniversalAuthAccessToken(accessToken string) (string, error) { return tokenResponse.AccessToken, nil } -func GetInfisicalUniversalAuthAccessToken(cmd *cobra.Command) (accessToken string, err error) { - - var token string - - universalAuthClientId, err := cmd.Flags().GetString("universal-auth-client-id") - if err != nil { - return token, err - } - universalAuthClientSecret, err := cmd.Flags().GetString("universal-auth-client-secret") - if err != nil { - return token, err - } - - if universalAuthClientId == "" { - universalAuthClientId = os.Getenv(INFISICAL_UNIVERSAL_AUTH_CLIENT_ID_NAME) - } - - if universalAuthClientSecret == "" { - universalAuthClientSecret = os.Getenv(INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET_NAME) - } - - if universalAuthClientId != "" || universalAuthClientSecret != "" { - res, err := UniversalAuthLogin(universalAuthClientId, universalAuthClientSecret) - - if err != nil { - return token, err - } - token = res.AccessToken - } - - return token, nil -} - -func UniversalAuthLogin(clientId string, clientSecret string) (api.UniversalAuthLoginResponse, error) { - httpClient := resty.New() - httpClient.SetRetryCount(10000). - SetRetryMaxWaitTime(20 * time.Second). - SetRetryWaitTime(5 * time.Second) - - tokenResponse, err := api.CallUniversalAuthLogin(httpClient, api.UniversalAuthLoginRequest{ClientId: clientId, ClientSecret: clientSecret}) - if err != nil { - return api.UniversalAuthLoginResponse{}, err - } - - return tokenResponse, nil -} - // Checks if the passed in email already exists in the users slice func ConfigContainsEmail(users []models.LoggedInUser, email string) bool { for _, value := range users { From 18b0766d96544ca9451530e5ff5878531fc72be1 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Fri, 5 Apr 2024 15:47:18 -0700 Subject: [PATCH 24/35] Update folders.go --- cli/packages/util/folders.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/packages/util/folders.go b/cli/packages/util/folders.go index bccf11dbc..cbc10c207 100644 --- a/cli/packages/util/folders.go +++ b/cli/packages/util/folders.go @@ -52,7 +52,7 @@ func GetAllFolders(params models.GetAllFoldersParameters) ([]models.SingleFolder } else if params.UniversalAuthAccessToken != "" { if params.WorkspaceId == "" { - PrintErrorMessageAndExit("Workspace ID is required when using machine identity") + PrintErrorMessageAndExit("Project ID is required when using machine identity") } // get folders via machine identity From c0fb3c905eb54a0ac320cfdfe170eb79dbab7c6a Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Fri, 5 Apr 2024 17:10:38 -0700 Subject: [PATCH 25/35] Docs: UA Auth Docs --- docs/cli/commands/login.mdx | 48 ++++++++++++++++++++++++++++++++++++- docs/cli/commands/token.mdx | 21 ++++++++++++++++ docs/mint.json | 1 + 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 docs/cli/commands/token.mdx diff --git a/docs/cli/commands/login.mdx b/docs/cli/commands/login.mdx index 3028ec110..8deea6a4d 100644 --- a/docs/cli/commands/login.mdx +++ b/docs/cli/commands/login.mdx @@ -12,4 +12,50 @@ The CLI uses authentication to verify your identity. When you enter the correct To change where the login credentials are stored, visit the [vaults command](./vault). -If you have added multiple users, you can switch between the users by using the [user command](./user). \ No newline at end of file +If you have added multiple users, you can switch between the users by using the [user command](./user). + + +### Flags + + ```bash + infisical login --method= # Optional, will default to 'user'. + ``` + + #### Valid values for the `method` flag are: + - `user`: Login using email and password. + - `universal-auth`: Login using a universal auth client ID and client secret. + + + When `method` is set to `universal-auth`, the `client-id` and `client-secret` flags are required. Optionally you can set the `INFISICAL_UNIVERSAL_AUTH_CLIENT_ID` and `INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET` environment variables instead of using the flags. + + When you authenticate with universal auth, an access token will be printed to the console upon successful login. This token can be used to authenticate with the Infisical API and the CLI by passing it in the `--token` flag when applicable. + + + + + ```bash + infisical login --client-id= # Optional, required if --method=universal-auth. + ``` + + #### Description + The client ID of the universal auth client. This is required if the `--method` flag is set to `universal-auth`. + + + The `client-id` flag can be substituted with the `INFISICAL_UNIVERSAL_AUTH_CLIENT_ID` environment variable. + + + + ```bash + infisical login --client-secret= # Optional, required if --method=universal-auth. + ``` + #### Description + The client secret of the universal auth client. This is required if the `--method` flag is set to `universal-auth`. + + + The `client-secret` flag can be substituted with the `INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET` environment variable. + + + + + + \ No newline at end of file diff --git a/docs/cli/commands/token.mdx b/docs/cli/commands/token.mdx new file mode 100644 index 000000000..5b0d4ad5c --- /dev/null +++ b/docs/cli/commands/token.mdx @@ -0,0 +1,21 @@ +--- +title: "infisical token" +description: "Manage your Infisical identity access tokens" +--- + +```bash +infisical service-token renew +``` + +## Description +The Infisical `token` command allows you to manage your universal auth access tokens. +With this command, you can renew your access tokens. In the future more subcommands will be added to better help you manage your tokens through the CLI. + + + Use this command to renew your access token. This command will renew your access token and output a renewed access token to the console. + + ```bash + $ infisical token renew + ``` + + diff --git a/docs/mint.json b/docs/mint.json index ebd4fca0b..595926c8b 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -225,6 +225,7 @@ "cli/commands/run", "cli/commands/secrets", "cli/commands/export", + "cli/commands/token", "cli/commands/service-token", "cli/commands/vault", "cli/commands/user", From dcbbb67f030419c99bbac98dea0d09540e7e4851 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Fri, 5 Apr 2024 17:30:19 -0700 Subject: [PATCH 26/35] Feat: Added secret interpolation to get secret by name command --- cli/packages/cmd/secrets.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/cli/packages/cmd/secrets.go b/cli/packages/cmd/secrets.go index 8c28b4cbc..29f4ea455 100644 --- a/cli/packages/cmd/secrets.go +++ b/cli/packages/cmd/secrets.go @@ -427,6 +427,12 @@ func getSecretsByNames(cmd *cobra.Command, args []string) { if err != nil { util.HandleError(err, "Unable to parse flag") } + + shouldExpand, err := cmd.Flags().GetBool("expand") + if err != nil { + util.HandleError(err, "Unable to parse flag") + } + tagSlugs, err := cmd.Flags().GetString("tags") if err != nil { util.HandleError(err, "Unable to parse flag") @@ -488,6 +494,18 @@ func getSecretsByNames(cmd *cobra.Command, args []string) { } } + if shouldExpand { + + authParams := models.ExpandSecretsAuthentication{} + if token != nil && token.Type == "service-token" { + authParams.InfisicalToken = token.Token + } else if token != nil && token.Type == "universal-auth-token" { + authParams.UniversalAuthAccessToken = token.Token + } + + requestedSecrets = util.ExpandSecrets(requestedSecrets, authParams, "") + } + if showOnlyValue && len(requestedSecrets) > 1 { util.PrintErrorMessageAndExit("--raw-value only works with one secret.") } @@ -750,6 +768,7 @@ func init() { secretsGetCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") secretsGetCmd.Flags().String("projectId", "", "manually set the projectId to fetch folders from for machine identity") secretsGetCmd.Flags().String("path", "/", "get secrets within a folder path") + secretsGetCmd.Flags().Bool("expand", true, "Parse shell parameter expansions in your secrets") secretsGetCmd.Flags().Bool("raw-value", false, "Returns only the value of secret, only works with one secret") secretsGetCmd.Flags().Bool("recursive", false, "Fetch secrets from all sub-folders") secretsCmd.AddCommand(secretsGetCmd) From 8f1e662688cde053d724c7569903c211e2856037 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Fri, 5 Apr 2024 17:30:30 -0700 Subject: [PATCH 27/35] Feat: Added include imports to export command --- cli/packages/cmd/export.go | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/cli/packages/cmd/export.go b/cli/packages/cmd/export.go index 34deaff67..c6841a3f2 100644 --- a/cli/packages/cmd/export.go +++ b/cli/packages/cmd/export.go @@ -44,6 +44,11 @@ var exportCmd = &cobra.Command{ util.HandleError(err) } + includeImports, err := cmd.Flags().GetBool("include-imports") + if err != nil { + util.HandleError(err) + } + projectId, err := cmd.Flags().GetString("projectId") if err != nil { util.HandleError(err) @@ -75,10 +80,11 @@ var exportCmd = &cobra.Command{ } request := models.GetAllSecretsParameters{ - Environment: environmentName, - TagSlugs: tagSlugs, - WorkspaceId: projectId, - SecretsPath: secretsPath, + Environment: environmentName, + TagSlugs: tagSlugs, + WorkspaceId: projectId, + SecretsPath: secretsPath, + IncludeImport: includeImports, } if token != nil && token.Type == "service-token" { @@ -129,6 +135,7 @@ func init() { exportCmd.Flags().Bool("expand", true, "Parse shell parameter expansions in your secrets") exportCmd.Flags().StringP("format", "f", "dotenv", "Set the format of the output file (dotenv, json, csv)") exportCmd.Flags().Bool("secret-overriding", true, "Prioritizes personal secrets, if any, with the same name over shared secrets") + exportCmd.Flags().Bool("include-imports", true, "Imported linked secrets") exportCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") exportCmd.Flags().StringP("tags", "t", "", "filter secrets by tag slugs") exportCmd.Flags().String("projectId", "", "manually set the projectId to fetch secrets from") From 0baea4c5fdac1f6e7b8818227df9fdb07ec91dac Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Mon, 8 Apr 2024 15:18:15 -0700 Subject: [PATCH 28/35] Draft --- cli/packages/util/helper.go | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/cli/packages/util/helper.go b/cli/packages/util/helper.go index 46eacb8af..155990d42 100644 --- a/cli/packages/util/helper.go +++ b/cli/packages/util/helper.go @@ -102,39 +102,6 @@ func GetInfisicalToken(cmd *cobra.Command) (token *models.TokenDetails, err erro } -func GetInfisicalUniversalAuthAccessToken(cmd *cobra.Command) (accessToken string, err error) { - - var token string - - universalAuthClientId, err := cmd.Flags().GetString("universal-auth-client-id") - if err != nil { - return token, err - } - universalAuthClientSecret, err := cmd.Flags().GetString("universal-auth-client-secret") - if err != nil { - return token, err - } - - if universalAuthClientId == "" { - universalAuthClientId = os.Getenv(INFISICAL_UNIVERSAL_AUTH_CLIENT_ID_NAME) - } - - if universalAuthClientSecret == "" { - universalAuthClientSecret = os.Getenv(INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET_NAME) - } - - if universalAuthClientId != "" || universalAuthClientSecret != "" { - res, err := UniversalAuthLogin(universalAuthClientId, universalAuthClientSecret) - - if err != nil { - return token, err - } - token = res.AccessToken - } - - return token, nil -} - func UniversalAuthLogin(clientId string, clientSecret string) (api.UniversalAuthLoginResponse, error) { httpClient := resty.New() httpClient.SetRetryCount(10000). From 51f164c399a64da1342c36eae1308aed955afcf0 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Fri, 12 Apr 2024 13:42:42 +0200 Subject: [PATCH 29/35] Chore: Add debug logs --- cli/packages/util/folders.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cli/packages/util/folders.go b/cli/packages/util/folders.go index cbc10c207..165b97534 100644 --- a/cli/packages/util/folders.go +++ b/cli/packages/util/folders.go @@ -45,11 +45,14 @@ func GetAllFolders(params models.GetAllFoldersParameters) ([]models.SingleFolder folderErr = err foldersToReturn = folders } else if params.InfisicalToken != "" { + log.Debug().Msg("GetAllFolders: Trying to fetch folders using service token") + // get folders via service token folders, err := GetFoldersViaServiceToken(params.InfisicalToken, params.WorkspaceId, params.Environment, params.FoldersPath) folderErr = err foldersToReturn = folders } else if params.UniversalAuthAccessToken != "" { + log.Debug().Msg("GetAllFolders: Trying to fetch folders using universal auth") if params.WorkspaceId == "" { PrintErrorMessageAndExit("Project ID is required when using machine identity") From 71575b1d2ee49fb4103c91dca7fe06fc599de705 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Fri, 12 Apr 2024 14:05:43 +0200 Subject: [PATCH 30/35] Fix: Secret interpolation not working as intended for fetching secrets by name --- cli/packages/cmd/secrets.go | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/cli/packages/cmd/secrets.go b/cli/packages/cmd/secrets.go index 29f4ea455..8175edd76 100644 --- a/cli/packages/cmd/secrets.go +++ b/cli/packages/cmd/secrets.go @@ -478,6 +478,17 @@ func getSecretsByNames(cmd *cobra.Command, args []string) { util.HandleError(err, "To fetch all secrets") } + if shouldExpand { + authParams := models.ExpandSecretsAuthentication{} + if token != nil && token.Type == "service-token" { + authParams.InfisicalToken = token.Token + } else if token != nil && token.Type == "universal-auth-token" { + authParams.UniversalAuthAccessToken = token.Token + } + + secrets = util.ExpandSecrets(secrets, authParams, "") + } + requestedSecrets := []models.SingleEnvironmentVariable{} secretsMap := getSecretsByKeys(secrets) @@ -494,18 +505,6 @@ func getSecretsByNames(cmd *cobra.Command, args []string) { } } - if shouldExpand { - - authParams := models.ExpandSecretsAuthentication{} - if token != nil && token.Type == "service-token" { - authParams.InfisicalToken = token.Token - } else if token != nil && token.Type == "universal-auth-token" { - authParams.UniversalAuthAccessToken = token.Token - } - - requestedSecrets = util.ExpandSecrets(requestedSecrets, authParams, "") - } - if showOnlyValue && len(requestedSecrets) > 1 { util.PrintErrorMessageAndExit("--raw-value only works with one secret.") } From a4a961996b7d6af782e70dbc3c11942ea72e9490 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Tue, 16 Apr 2024 10:14:41 +0200 Subject: [PATCH 31/35] Fix: Formatting and plain token output --- cli/packages/cmd/login.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/cli/packages/cmd/login.go b/cli/packages/cmd/login.go index 039540865..bbb2c3a05 100644 --- a/cli/packages/cmd/login.go +++ b/cli/packages/cmd/login.go @@ -57,7 +57,10 @@ var loginCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { loginMethod, err := cmd.Flags().GetString("method") - + if err != nil { + util.HandleError(err) + } + plainOutput, err := cmd.Flags().GetBool("plain") if err != nil { util.HandleError(err) } @@ -188,10 +191,16 @@ var loginCmd = &cobra.Command{ util.HandleError(err) } + if plainOutput { + fmt.Println(res.AccessToken) + return + } + boldGreen := color.New(color.FgGreen).Add(color.Bold) + boldPlain := color.New(color.Bold) time.Sleep(time.Second * 1) boldGreen.Printf(">>>> Successfully authenticated with Universal Auth!\n\n") - boldGreen.Printf("Universal Auth Access Token:\n%v", res.AccessToken) + boldPlain.Printf("Universal Auth Access Token:\n%v", res.AccessToken) plainBold := color.New(color.Bold) plainBold.Println("\n\nYou can use this access token to authenticate through other commands in the CLI.") @@ -368,6 +377,7 @@ func init() { loginCmd.Flags().BoolP("interactive", "i", false, "login via the command line") loginCmd.Flags().String("method", "user", "login method [user, universal-auth]") loginCmd.Flags().String("client-id", "", "client id for universal auth") + loginCmd.Flags().Bool("plain", false, "only output the token without any formatting") loginCmd.Flags().String("client-secret", "", "client secret for universal auth") } From 3a6ec3717bfbd0614237cf4ab1c89a642be6b4f4 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Tue, 16 Apr 2024 10:15:07 +0200 Subject: [PATCH 32/35] Fix: Use constant identifiers --- cli/packages/cmd/export.go | 8 ++++---- cli/packages/cmd/folder.go | 4 ++-- cli/packages/cmd/run.go | 12 ++++++------ cli/packages/cmd/secrets.go | 20 ++++++++++---------- cli/packages/util/constants.go | 3 +++ cli/packages/util/helper.go | 4 ++-- 6 files changed, 27 insertions(+), 24 deletions(-) diff --git a/cli/packages/cmd/export.go b/cli/packages/cmd/export.go index c6841a3f2..4e08e5fa8 100644 --- a/cli/packages/cmd/export.go +++ b/cli/packages/cmd/export.go @@ -87,9 +87,9 @@ var exportCmd = &cobra.Command{ IncludeImport: includeImports, } - if token != nil && token.Type == "service-token" { + if token != nil && token.Type == util.SERVICE_TOKEN_IDENTIFIER { request.InfisicalToken = token.Token - } else if token != nil && token.Type == "universal-auth-token" { + } else if token != nil && token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER { request.UniversalAuthAccessToken = token.Token } @@ -109,9 +109,9 @@ var exportCmd = &cobra.Command{ authParams := models.ExpandSecretsAuthentication{} - if token != nil && token.Type == "service-token" { + if token != nil && token.Type == util.SERVICE_TOKEN_IDENTIFIER { authParams.InfisicalToken = token.Token - } else if token != nil && token.Type == "universal-auth-token" { + } else if token != nil && token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER { authParams.UniversalAuthAccessToken = token.Token } diff --git a/cli/packages/cmd/folder.go b/cli/packages/cmd/folder.go index 247050c90..b306960f4 100644 --- a/cli/packages/cmd/folder.go +++ b/cli/packages/cmd/folder.go @@ -56,9 +56,9 @@ var getCmd = &cobra.Command{ FoldersPath: foldersPath, } - if token != nil && token.Type == "service-token" { + if token != nil && token.Type == util.SERVICE_TOKEN_IDENTIFIER { request.InfisicalToken = token.Token - } else if token != nil && token.Type == "universal-auth-token" { + } else if token != nil && token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER { request.UniversalAuthAccessToken = token.Token } diff --git a/cli/packages/cmd/run.go b/cli/packages/cmd/run.go index 8481277e9..3fe151d0b 100644 --- a/cli/packages/cmd/run.go +++ b/cli/packages/cmd/run.go @@ -116,9 +116,9 @@ var runCmd = &cobra.Command{ Recursive: recursive, } - if token != nil && token.Type == "service-token" { + if token != nil && token.Type == util.SERVICE_TOKEN_IDENTIFIER { request.InfisicalToken = token.Token - } else if token != nil && token.Type == "universal-auth-token" { + } else if token != nil && token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER { request.UniversalAuthAccessToken = token.Token } @@ -138,9 +138,9 @@ var runCmd = &cobra.Command{ authParams := models.ExpandSecretsAuthentication{} - if token != nil && token.Type == "service-token" { + if token != nil && token.Type == util.SERVICE_TOKEN_IDENTIFIER { authParams.InfisicalToken = token.Token - } else if token != nil && token.Type == "universal-auth-token" { + } else if token != nil && token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER { authParams.UniversalAuthAccessToken = token.Token } @@ -179,8 +179,8 @@ var runCmd = &cobra.Command{ posthog.NewProperties(). Set("secretsCount", len(secrets)). Set("environment", environmentName). - Set("isUsingServiceToken", token.Type == "service-token"). - Set("isUsingUniversalAuthToken", token.Type == "universal-auth-token"). + Set("isUsingServiceToken", token.Type == util.SERVICE_TOKEN_IDENTIFIER). + Set("isUsingUniversalAuthToken", token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER). Set("single-command", strings.Join(args, " ")). Set("multi-command", cmd.Flag("command").Value.String()). Set("version", util.CLI_VERSION)) diff --git a/cli/packages/cmd/secrets.go b/cli/packages/cmd/secrets.go index 8175edd76..7ba6e5411 100644 --- a/cli/packages/cmd/secrets.go +++ b/cli/packages/cmd/secrets.go @@ -87,9 +87,9 @@ var secretsCmd = &cobra.Command{ Recursive: recursive, } - if token != nil && token.Type == "service-token" { + if token != nil && token.Type == util.SERVICE_TOKEN_IDENTIFIER { request.InfisicalToken = token.Token - } else if token != nil && token.Type == "universal-auth-token" { + } else if token != nil && token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER { request.UniversalAuthAccessToken = token.Token } @@ -107,9 +107,9 @@ var secretsCmd = &cobra.Command{ if shouldExpandSecrets { authParams := models.ExpandSecretsAuthentication{} - if token != nil && token.Type == "service-token" { + if token != nil && token.Type == util.SERVICE_TOKEN_IDENTIFIER { authParams.InfisicalToken = token.Token - } else if token != nil && token.Type == "universal-auth-token" { + } else if token != nil && token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER { authParams.UniversalAuthAccessToken = token.Token } @@ -467,9 +467,9 @@ func getSecretsByNames(cmd *cobra.Command, args []string) { Recursive: recursive, } - if token != nil && token.Type == "service-token" { + if token != nil && token.Type == util.SERVICE_TOKEN_IDENTIFIER { request.InfisicalToken = token.Token - } else if token != nil && token.Type == "universal-auth-token" { + } else if token != nil && token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER { request.UniversalAuthAccessToken = token.Token } @@ -480,9 +480,9 @@ func getSecretsByNames(cmd *cobra.Command, args []string) { if shouldExpand { authParams := models.ExpandSecretsAuthentication{} - if token != nil && token.Type == "service-token" { + if token != nil && token.Type == util.SERVICE_TOKEN_IDENTIFIER { authParams.InfisicalToken = token.Token - } else if token != nil && token.Type == "universal-auth-token" { + } else if token != nil && token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER { authParams.UniversalAuthAccessToken = token.Token } @@ -554,9 +554,9 @@ func generateExampleEnv(cmd *cobra.Command, args []string) { IncludeImport: true, } - if token != nil && token.Type == "service-token" { + if token != nil && token.Type == util.SERVICE_TOKEN_IDENTIFIER { request.InfisicalToken = token.Token - } else if token != nil && token.Type == "universal-auth-token" { + } else if token != nil && token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER { request.UniversalAuthAccessToken = token.Token } diff --git a/cli/packages/util/constants.go b/cli/packages/util/constants.go index 120548c10..311a4b0d9 100644 --- a/cli/packages/util/constants.go +++ b/cli/packages/util/constants.go @@ -15,6 +15,9 @@ const ( KEYRING_SERVICE_NAME = "infisical" PERSONAL_SECRET_TYPE_NAME = "personal" SHARED_SECRET_TYPE_NAME = "shared" + + SERVICE_TOKEN_IDENTIFIER = "service-token" + UNIVERSAL_AUTH_TOKEN_IDENTIFIER = "universal-auth-token" ) var ( diff --git a/cli/packages/util/helper.go b/cli/packages/util/helper.go index 155990d42..e2f003619 100644 --- a/cli/packages/util/helper.go +++ b/cli/packages/util/helper.go @@ -90,13 +90,13 @@ func GetInfisicalToken(cmd *cobra.Command) (token *models.TokenDetails, err erro if strings.HasPrefix(infisicalToken, "st.") { return &models.TokenDetails{ - Type: "service-token", + Type: SERVICE_TOKEN_IDENTIFIER, Token: infisicalToken, }, nil } return &models.TokenDetails{ - Type: "universal-auth-token", + Type: UNIVERSAL_AUTH_TOKEN_IDENTIFIER, Token: infisicalToken, }, nil From a975fbd8a4e8e363b90db84821b6cc91b7917b4e Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Tue, 16 Apr 2024 10:16:23 +0200 Subject: [PATCH 33/35] Fix: Moved comments --- cli/packages/util/helper.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/cli/packages/util/helper.go b/cli/packages/util/helper.go index e2f003619..e5b8ab6d9 100644 --- a/cli/packages/util/helper.go +++ b/cli/packages/util/helper.go @@ -74,17 +74,15 @@ func GetInfisicalToken(cmd *cobra.Command) (token *models.TokenDetails, err erro return nil, err } - if infisicalToken == "" { - // If no flag is passed, we first check for the universal auth access token env variable. + 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) - // If it's still empty after the first env check, we check for the service token env variable. - if infisicalToken == "" { + + 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) } } - // If it's empty, we return nothing at all. - if infisicalToken == "" { + if infisicalToken == "" { // If it's empty, we return nothing at all. return nil, nil } From 18d7a14e3ff89694a92efd22b951f8d31afea5df Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Tue, 16 Apr 2024 13:21:05 -0400 Subject: [PATCH 34/35] add silent flag --- cli/packages/cmd/root.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cli/packages/cmd/root.go b/cli/packages/cmd/root.go index 9c7814ecc..06846260f 100644 --- a/cli/packages/cmd/root.go +++ b/cli/packages/cmd/root.go @@ -40,8 +40,14 @@ func init() { rootCmd.PersistentFlags().StringP("log-level", "l", "info", "log level (trace, debug, info, warn, error, fatal)") rootCmd.PersistentFlags().Bool("telemetry", true, "Infisical collects non-sensitive telemetry data to enhance features and improve user experience. Participation is voluntary") rootCmd.PersistentFlags().StringVar(&config.INFISICAL_URL, "domain", util.INFISICAL_DEFAULT_API_URL, "Point the CLI to your own backend [can also set via environment variable name: INFISICAL_API_URL]") + rootCmd.PersistentFlags().Bool("silent", false, "Disable output of tip/info messages. Useful when running in scripts or CI/CD pipelines.") rootCmd.PersistentPreRun = func(cmd *cobra.Command, args []string) { - if !util.IsRunningInDocker() { + silent, err := cmd.Flags().GetBool("silent") + if err != nil { + util.HandleError(err) + } + + if !util.IsRunningInDocker() && !silent { util.CheckForUpdate() } } From 85f257b4dbf32e4d5ec9fedf5e0974468d03c032 Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Tue, 16 Apr 2024 13:24:39 -0400 Subject: [PATCH 35/35] add tip to only print token --- docs/cli/commands/login.mdx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/cli/commands/login.mdx b/docs/cli/commands/login.mdx index 8deea6a4d..2758ced00 100644 --- a/docs/cli/commands/login.mdx +++ b/docs/cli/commands/login.mdx @@ -29,6 +29,9 @@ If you have added multiple users, you can switch between the users by using the When `method` is set to `universal-auth`, the `client-id` and `client-secret` flags are required. Optionally you can set the `INFISICAL_UNIVERSAL_AUTH_CLIENT_ID` and `INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET` environment variables instead of using the flags. When you authenticate with universal auth, an access token will be printed to the console upon successful login. This token can be used to authenticate with the Infisical API and the CLI by passing it in the `--token` flag when applicable. + + Use flag `--plain` along with `--silent` to print only the token in plain text when using the `universal-auth` method. +