From 88549f403042195e955cd4f86221b09bb50d1c4c Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Fri, 22 Mar 2024 16:13:05 +0100 Subject: [PATCH] Feat: Deep search support --- cli/packages/api/api.go | 4 ++++ cli/packages/api/model.go | 1 + cli/packages/cmd/agent.go | 2 +- cli/packages/cmd/run.go | 8 +++++++- cli/packages/cmd/secrets.go | 17 +++++++++++++++-- cli/packages/models/cli.go | 1 + cli/packages/util/secrets.go | 15 +++++++++------ 7 files changed, 38 insertions(+), 10 deletions(-) diff --git a/cli/packages/api/api.go b/cli/packages/api/api.go index 38d82a0a5..38af4630e 100644 --- a/cli/packages/api/api.go +++ b/cli/packages/api/api.go @@ -277,6 +277,10 @@ func CallGetSecretsV3(httpClient *resty.Client, request GetEncryptedSecretsV3Req SetQueryParam("environment", request.Environment). SetQueryParam("workspaceId", request.WorkspaceId) + if request.DeepSearch { + httpRequest.SetQueryParam("deep", "true") + } + if request.IncludeImport { httpRequest.SetQueryParam("include_imports", "true") } diff --git a/cli/packages/api/model.go b/cli/packages/api/model.go index b49cb1581..1b91c8b64 100644 --- a/cli/packages/api/model.go +++ b/cli/packages/api/model.go @@ -291,6 +291,7 @@ type GetEncryptedSecretsV3Request struct { WorkspaceId string `json:"workspaceId"` SecretPath string `json:"secretPath"` IncludeImport bool `json:"include_imports"` + DeepSearch bool `json:"deep"` } type GetFoldersV1Request struct { diff --git a/cli/packages/cmd/agent.go b/cli/packages/cmd/agent.go index ce3f7a8b0..80f321396 100644 --- a/cli/packages/cmd/agent.go +++ b/cli/packages/cmd/agent.go @@ -332,7 +332,7 @@ func ParseAgentConfig(configFile []byte) (*Config, error) { func secretTemplateFunction(accessToken string, existingEtag string, currentEtag *string) func(string, string, string) ([]models.SingleEnvironmentVariable, error) { return func(projectID, envSlug, secretPath string) ([]models.SingleEnvironmentVariable, error) { - res, err := util.GetPlainTextSecretsViaMachineIdentity(accessToken, projectID, envSlug, secretPath, false) + res, err := util.GetPlainTextSecretsViaMachineIdentity(accessToken, projectID, envSlug, secretPath, false, false) if err != nil { return nil, err } diff --git a/cli/packages/cmd/run.go b/cli/packages/cmd/run.go index d008af1ec..f6e675096 100644 --- a/cli/packages/cmd/run.go +++ b/cli/packages/cmd/run.go @@ -98,7 +98,12 @@ 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}, projectConfigDir) + deepSearch, err := cmd.Flags().GetBool("deep") + if err != nil { + util.HandleError(err, "Unable to parse flag") + } + + secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: includeImports, DeepSearch: deepSearch}, 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") @@ -202,6 +207,7 @@ func init() { 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 ") + runCmd.Flags().Bool("deep", false, "Fetch secrets from all sub-folders") runCmd.Flags().Bool("secret-overriding", true, "Prioritizes personal secrets, if any, with the same name over shared secrets") runCmd.Flags().StringP("command", "c", "", "chained commands to execute (e.g. \"npm install && npm run dev; echo ...\")") runCmd.Flags().StringP("tags", "t", "", "filter secrets by tag slugs ") diff --git a/cli/packages/cmd/secrets.go b/cli/packages/cmd/secrets.go index cf9c89b47..1db565b76 100644 --- a/cli/packages/cmd/secrets.go +++ b/cli/packages/cmd/secrets.go @@ -63,6 +63,13 @@ var secretsCmd = &cobra.Command{ util.HandleError(err) } + deepSearch, err := cmd.Flags().GetBool("deep") + if err != nil { + util.HandleError(err) + } + + fmt.Printf("Is deep search: %v\n", deepSearch) + tagSlugs, err := cmd.Flags().GetString("tags") if err != nil { util.HandleError(err, "Unable to parse flag") @@ -73,7 +80,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}, "") + secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: includeImports, DeepSearch: deepSearch}, "") if err != nil { util.HandleError(err) } @@ -413,12 +420,17 @@ func getSecretsByNames(cmd *cobra.Command, args []string) { util.HandleError(err, "Unable to parse path flag") } + deepSearch, err := cmd.Flags().GetBool("deep") + if err != nil { + util.HandleError(err, "Unable to parse deep flag") + } + showOnlyValue, err := cmd.Flags().GetBool("raw-value") if err != nil { util.HandleError(err, "Unable to parse path 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, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: true, DeepSearch: deepSearch}, "") if err != nil { util.HandleError(err, "To fetch all secrets") } @@ -727,6 +739,7 @@ func init() { 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 ") + secretsCmd.Flags().Bool("deep", false, "Fetch secrets from all sub-folders") secretsCmd.PersistentFlags().StringP("tags", "t", "", "filter secrets by tag slugs") secretsCmd.Flags().String("path", "/", "get secrets within a folder path") rootCmd.AddCommand(secretsCmd) diff --git a/cli/packages/models/cli.go b/cli/packages/models/cli.go index 4a7dc782a..69319e2b2 100644 --- a/cli/packages/models/cli.go +++ b/cli/packages/models/cli.go @@ -93,6 +93,7 @@ type GetAllSecretsParameters struct { WorkspaceId string SecretsPath string IncludeImport bool + DeepSearch bool } type GetAllFoldersParameters struct { diff --git a/cli/packages/util/secrets.go b/cli/packages/util/secrets.go index 6f56bc84a..89d094f43 100644 --- a/cli/packages/util/secrets.go +++ b/cli/packages/util/secrets.go @@ -17,7 +17,7 @@ import ( "github.com/rs/zerolog/log" ) -func GetPlainTextSecretsViaServiceToken(fullServiceToken string, environment string, secretPath string, includeImports bool) ([]models.SingleEnvironmentVariable, api.GetServiceTokenDetailsResponse, error) { +func GetPlainTextSecretsViaServiceToken(fullServiceToken string, environment string, secretPath string, includeImports bool, deepSearch bool) ([]models.SingleEnvironmentVariable, api.GetServiceTokenDetailsResponse, error) { serviceTokenParts := strings.SplitN(fullServiceToken, ".", 4) if len(serviceTokenParts) < 4 { return nil, api.GetServiceTokenDetailsResponse{}, fmt.Errorf("invalid service token entered. Please double check your service token and try again") @@ -49,6 +49,7 @@ func GetPlainTextSecretsViaServiceToken(fullServiceToken string, environment str Environment: environment, SecretPath: secretPath, IncludeImport: includeImports, + DeepSearch: deepSearch, }) if err != nil { @@ -80,7 +81,7 @@ func GetPlainTextSecretsViaServiceToken(fullServiceToken string, environment str return plainTextSecrets, serviceTokenDetails, nil } -func GetPlainTextSecretsViaJTW(JTWToken string, receiversPrivateKey string, workspaceId string, environmentName string, tagSlugs string, secretsPath string, includeImports bool) ([]models.SingleEnvironmentVariable, error) { +func GetPlainTextSecretsViaJTW(JTWToken string, receiversPrivateKey string, workspaceId string, environmentName string, tagSlugs string, secretsPath string, includeImports bool, deepSearch bool) ([]models.SingleEnvironmentVariable, error) { httpClient := resty.New() httpClient.SetAuthToken(JTWToken). SetHeader("Accept", "application/json") @@ -125,6 +126,7 @@ func GetPlainTextSecretsViaJTW(JTWToken string, receiversPrivateKey string, work WorkspaceId: workspaceId, Environment: environmentName, IncludeImport: includeImports, + DeepSearch: deepSearch, // TagSlugs: tagSlugs, } @@ -152,7 +154,7 @@ func GetPlainTextSecretsViaJTW(JTWToken string, receiversPrivateKey string, work return plainTextSecrets, nil } -func GetPlainTextSecretsViaMachineIdentity(accessToken string, workspaceId string, environmentName string, secretsPath string, includeImports bool) (models.PlaintextSecretResult, error) { +func GetPlainTextSecretsViaMachineIdentity(accessToken string, workspaceId string, environmentName string, secretsPath string, includeImports bool, deepSearch bool) (models.PlaintextSecretResult, error) { httpClient := resty.New() httpClient.SetAuthToken(accessToken). SetHeader("Accept", "application/json") @@ -161,6 +163,7 @@ func GetPlainTextSecretsViaMachineIdentity(accessToken string, workspaceId strin WorkspaceId: workspaceId, Environment: environmentName, IncludeImport: includeImports, + DeepSearch: deepSearch, // TagSlugs: tagSlugs, } @@ -329,7 +332,7 @@ func GetAllEnvironmentVariables(params models.GetAllSecretsParameters, projectCo } secretsToReturn, errorToReturn = GetPlainTextSecretsViaJTW(loggedInUserDetails.UserCredentials.JTWToken, loggedInUserDetails.UserCredentials.PrivateKey, infisicalDotJson.WorkspaceId, - params.Environment, params.TagSlugs, params.SecretsPath, params.IncludeImport) + params.Environment, params.TagSlugs, params.SecretsPath, params.IncludeImport, params.DeepSearch) log.Debug().Msgf("GetAllEnvironmentVariables: Trying to fetch secrets JTW token [err=%s]", errorToReturn) backupSecretsEncryptionKey := []byte(loggedInUserDetails.UserCredentials.PrivateKey)[0:32] @@ -350,10 +353,10 @@ func GetAllEnvironmentVariables(params models.GetAllSecretsParameters, projectCo } else { if params.InfisicalToken != "" { log.Debug().Msg("Trying to fetch secrets using service token") - secretsToReturn, _, errorToReturn = GetPlainTextSecretsViaServiceToken(params.InfisicalToken, params.Environment, params.SecretsPath, params.IncludeImport) + secretsToReturn, _, errorToReturn = GetPlainTextSecretsViaServiceToken(params.InfisicalToken, params.Environment, params.SecretsPath, params.IncludeImport, params.DeepSearch) } else if params.UniversalAuthAccessToken != "" { log.Debug().Msg("Trying to fetch secrets using universal auth") - res, err := GetPlainTextSecretsViaMachineIdentity(params.UniversalAuthAccessToken, params.WorkspaceId, params.Environment, params.SecretsPath, params.IncludeImport) + res, err := GetPlainTextSecretsViaMachineIdentity(params.UniversalAuthAccessToken, params.WorkspaceId, params.Environment, params.SecretsPath, params.IncludeImport, params.DeepSearch) errorToReturn = err secretsToReturn = res.Secrets