From e65ce932dd9e56661dafb13f55c2140d13f5f4bc Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Sat, 15 Jun 2024 08:44:42 +0200 Subject: [PATCH 01/12] feat: create/update raw secrets --- cli/packages/api/api.go | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/cli/packages/api/api.go b/cli/packages/api/api.go index 01f29a03a..410760d4a 100644 --- a/cli/packages/api/api.go +++ b/cli/packages/api/api.go @@ -391,6 +391,7 @@ func CallCreateSecretsV3(httpClient *resty.Client, request CreateSecretV3Request } func CallDeleteSecretsV3(httpClient *resty.Client, request DeleteSecretV3Request) error { + var secretsResponse GetEncryptedSecretsV3Response response, err := httpClient. R(). @@ -566,3 +567,39 @@ func CallCreateDynamicSecretLeaseV1(httpClient *resty.Client, request CreateDyna return createDynamicSecretLeaseResponse, nil } + +func CallCreateRawSecretsV3(httpClient *resty.Client, request CreateRawSecretV3Request) error { + response, err := httpClient. + R(). + SetHeader("User-Agent", USER_AGENT). + SetBody(request). + Post(fmt.Sprintf("%v/v3/secrets/raw/%s", config.INFISICAL_URL, request.SecretName)) + + if err != nil { + return fmt.Errorf("CallCreateRawSecretsV3: Unable to complete api request [err=%w]", err) + } + + if response.IsError() { + return fmt.Errorf("CallCreateRawSecretsV3: Unsuccessful response [%v %v] [status-code=%v] [response=%v]", response.Request.Method, response.Request.URL, response.StatusCode(), response.String()) + } + + return nil +} + +func CallUpdateRawSecretsV3(httpClient *resty.Client, request UpdateRawSecretByNameV3Request) error { + response, err := httpClient. + R(). + SetHeader("User-Agent", USER_AGENT). + SetBody(request). + Patch(fmt.Sprintf("%v/v3/secrets/raw/%s", config.INFISICAL_URL, request.SecretName)) + + if err != nil { + return fmt.Errorf("CallUpdateRawSecretsV3: Unable to complete api request [err=%w]", err) + } + + if response.IsError() { + return fmt.Errorf("CallUpdateRawSecretsV3: Unsuccessful response [%v %v] [status-code=%v] [response=%v]", response.Request.Method, response.Request.URL, response.StatusCode(), response.String()) + } + + return nil +} From ebdfe31c17057feb9475f2ca711c4d817e543a5a Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Sat, 15 Jun 2024 08:44:55 +0200 Subject: [PATCH 02/12] Raw secrets operations models --- cli/packages/api/model.go | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/cli/packages/api/model.go b/cli/packages/api/model.go index 56b9807f7..4797955c1 100644 --- a/cli/packages/api/model.go +++ b/cli/packages/api/model.go @@ -161,6 +161,14 @@ type Secret struct { PlainTextKey string `json:"plainTextKey"` } +type RawSecret struct { + SecretKey string `json:"secretKey,omitempty"` + SecretValue string `json:"secretValue,omitempty"` + Type string `json:"type,omitempty"` + SecretComment string `json:"secretComment,omitempty"` + ID string `json:"id,omitempty"` +} + type GetEncryptedWorkspaceKeyRequest struct { WorkspaceId string `json:"workspaceId"` } @@ -409,12 +417,23 @@ type CreateSecretV3Request struct { SecretPath string `json:"secretPath"` } +type CreateRawSecretV3Request struct { + SecretName string `json:"-"` + WorkspaceID string `json:"workspaceId"` + Type string `json:"type,omitempty"` + Environment string `json:"environment"` + SecretPath string `json:"secretPath,omitempty"` + SecretValue string `json:"secretValue"` + SecretComment string `json:"secretComment,omitempty"` + SkipMultilineEncoding bool `json:"skipMultilineEncoding,omitempty"` +} + type DeleteSecretV3Request struct { SecretName string `json:"secretName"` WorkspaceId string `json:"workspaceId"` Environment string `json:"environment"` - Type string `json:"type"` - SecretPath string `json:"secretPath"` + Type string `json:"type,omitempty"` + SecretPath string `json:"secretPath,omitempty"` } type UpdateSecretByNameV3Request struct { @@ -427,6 +446,15 @@ type UpdateSecretByNameV3Request struct { SecretValueTag string `json:"secretValueTag"` } +type UpdateRawSecretByNameV3Request struct { + SecretName string `json:"-"` + WorkspaceID string `json:"workspaceId"` + Environment string `json:"environment"` + SecretPath string `json:"secretPath,omitempty"` + SecretValue string `json:"secretValue"` + Type string `json:"type,omitempty"` +} + type GetSingleSecretByNameV3Request struct { SecretName string `json:"secretName"` WorkspaceId string `json:"workspaceId"` From bf8aee25fe5ff0a3cbbb518f6a31ed6fd565111e Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Sat, 15 Jun 2024 08:45:25 +0200 Subject: [PATCH 03/12] Feat: Unify CLI auth methods --- cli/packages/cmd/export.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cli/packages/cmd/export.go b/cli/packages/cmd/export.go index 983c19255..012e21ba6 100644 --- a/cli/packages/cmd/export.go +++ b/cli/packages/cmd/export.go @@ -55,6 +55,11 @@ var exportCmd = &cobra.Command{ util.HandleError(err) } + token, err := util.GetInfisicalToken(cmd) + if err != nil { + util.HandleError(err, "Unable to parse flag") + } + format, err := cmd.Flags().GetString("format") if err != nil { util.HandleError(err) @@ -70,11 +75,6 @@ var exportCmd = &cobra.Command{ util.HandleError(err, "Unable to parse flag") } - token, err := util.GetInfisicalToken(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") From afcf15df55db2f6361af07b31b4ca3a6981c6e2b Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Sat, 15 Jun 2024 08:47:48 +0200 Subject: [PATCH 04/12] Set secrets raw support --- cli/packages/util/secrets.go | 338 +++++++++++++++++++++++++++++++++++ 1 file changed, 338 insertions(+) diff --git a/cli/packages/util/secrets.go b/cli/packages/util/secrets.go index 02c2704bd..1114d9ad9 100644 --- a/cli/packages/util/secrets.go +++ b/cli/packages/util/secrets.go @@ -1,6 +1,7 @@ package util import ( + "crypto/sha256" "encoding/base64" "encoding/json" "errors" @@ -9,6 +10,7 @@ import ( "path" "regexp" "strings" + "unicode" "github.com/Infisical/infisical-merge/packages/api" "github.com/Infisical/infisical-merge/packages/crypto" @@ -806,3 +808,339 @@ func GetPlainTextWorkspaceKey(authenticationToken string, receiverPrivateKey str return crypto.DecryptAsymmetric(encryptedWorkspaceKey, encryptedWorkspaceKeyNonce, encryptedWorkspaceKeySenderPublicKey, currentUsersPrivateKey), nil } + +func SetEncryptedSecrets(secretArgs []string, secretType string, environmentName string, secretsPath string) ([]models.SecretSetOperation, error) { + + workspaceFile, err := GetWorkSpaceFromFile() + if err != nil { + return nil, fmt.Errorf("unable to get your local config details [err=%v]", err) + } + + loggedInUserDetails, err := GetCurrentLoggedInUserDetails() + if err != nil { + return nil, fmt.Errorf("unable to authenticate [err=%v]", err) + } + + if loggedInUserDetails.LoginExpired { + PrintErrorMessageAndExit("Your login session has expired, please run [infisical login] and try again") + } + + httpClient := resty.New(). + SetAuthToken(loggedInUserDetails.UserCredentials.JTWToken). + SetHeader("Accept", "application/json") + + request := api.GetEncryptedWorkspaceKeyRequest{ + WorkspaceId: workspaceFile.WorkspaceId, + } + + workspaceKeyResponse, err := api.CallGetEncryptedWorkspaceKey(httpClient, request) + if err != nil { + return nil, fmt.Errorf("unable to get your encrypted workspace key [err=%v]", err) + } + + encryptedWorkspaceKey, _ := base64.StdEncoding.DecodeString(workspaceKeyResponse.EncryptedKey) + encryptedWorkspaceKeySenderPublicKey, _ := base64.StdEncoding.DecodeString(workspaceKeyResponse.Sender.PublicKey) + encryptedWorkspaceKeyNonce, _ := base64.StdEncoding.DecodeString(workspaceKeyResponse.Nonce) + currentUsersPrivateKey, _ := base64.StdEncoding.DecodeString(loggedInUserDetails.UserCredentials.PrivateKey) + + if len(currentUsersPrivateKey) == 0 || len(encryptedWorkspaceKeySenderPublicKey) == 0 { + log.Debug().Msgf("Missing credentials for generating plainTextEncryptionKey: [currentUsersPrivateKey=%s] [encryptedWorkspaceKeySenderPublicKey=%s]", currentUsersPrivateKey, encryptedWorkspaceKeySenderPublicKey) + PrintErrorMessageAndExit("Some required user credentials are missing to generate your [plainTextEncryptionKey]. Please run [infisical login] then try again") + } + + // decrypt workspace key + plainTextEncryptionKey := crypto.DecryptAsymmetric(encryptedWorkspaceKey, encryptedWorkspaceKeyNonce, encryptedWorkspaceKeySenderPublicKey, currentUsersPrivateKey) + + infisicalTokenEnv := os.Getenv(INFISICAL_TOKEN_NAME) + + // pull current secrets + secrets, err := GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, SecretsPath: secretsPath, InfisicalToken: infisicalTokenEnv}, "") + if err != nil { + return nil, fmt.Errorf("unable to retrieve secrets [err=%v]", err) + } + + secretsToCreate := []api.Secret{} + secretsToModify := []api.Secret{} + secretOperations := []models.SecretSetOperation{} + + sharedSecretMapByName := make(map[string]models.SingleEnvironmentVariable, len(secrets)) + personalSecretMapByName := make(map[string]models.SingleEnvironmentVariable, len(secrets)) + + for _, secret := range secrets { + if secret.Type == SECRET_TYPE_PERSONAL { + personalSecretMapByName[secret.Key] = secret + } else { + sharedSecretMapByName[secret.Key] = secret + } + } + + for _, arg := range secretArgs { + splitKeyValueFromArg := strings.SplitN(arg, "=", 2) + if splitKeyValueFromArg[0] == "" || splitKeyValueFromArg[1] == "" { + PrintErrorMessageAndExit("ensure that each secret has a none empty key and value. Modify the input and try again") + } + + if unicode.IsNumber(rune(splitKeyValueFromArg[0][0])) { + PrintErrorMessageAndExit("keys of secrets cannot start with a number. Modify the key name(s) and try again") + } + + // Key and value from argument + key := splitKeyValueFromArg[0] + value := splitKeyValueFromArg[1] + + hashedKey := fmt.Sprintf("%x", sha256.Sum256([]byte(key))) + encryptedKey, err := crypto.EncryptSymmetric([]byte(key), []byte(plainTextEncryptionKey)) + if err != nil { + return nil, fmt.Errorf("unable to encrypt your secrets [err=%v]", err) + } + + hashedValue := fmt.Sprintf("%x", sha256.Sum256([]byte(value))) + encryptedValue, err := crypto.EncryptSymmetric([]byte(value), []byte(plainTextEncryptionKey)) + if err != nil { + return nil, fmt.Errorf("unable to encrypt your secrets [err=%v]", err) + } + + var existingSecret models.SingleEnvironmentVariable + var doesSecretExist bool + + if secretType == SECRET_TYPE_SHARED { + existingSecret, doesSecretExist = sharedSecretMapByName[key] + } else { + existingSecret, doesSecretExist = personalSecretMapByName[key] + } + + if doesSecretExist { + // case: secret exists in project so it needs to be modified + encryptedSecretDetails := api.Secret{ + ID: existingSecret.ID, + SecretValueCiphertext: base64.StdEncoding.EncodeToString(encryptedValue.CipherText), + SecretValueIV: base64.StdEncoding.EncodeToString(encryptedValue.Nonce), + SecretValueTag: base64.StdEncoding.EncodeToString(encryptedValue.AuthTag), + SecretValueHash: hashedValue, + PlainTextKey: key, + Type: existingSecret.Type, + } + + // Only add to modifications if the value is different + if existingSecret.Value != value { + secretsToModify = append(secretsToModify, encryptedSecretDetails) + secretOperations = append(secretOperations, models.SecretSetOperation{ + SecretKey: key, + SecretValue: value, + SecretOperation: "SECRET VALUE MODIFIED", + }) + } else { + // Current value is same as exisitng so no change + secretOperations = append(secretOperations, models.SecretSetOperation{ + SecretKey: key, + SecretValue: value, + SecretOperation: "SECRET VALUE UNCHANGED", + }) + } + + } else { + // case: secret doesn't exist in project so it needs to be created + encryptedSecretDetails := api.Secret{ + SecretKeyCiphertext: base64.StdEncoding.EncodeToString(encryptedKey.CipherText), + SecretKeyIV: base64.StdEncoding.EncodeToString(encryptedKey.Nonce), + SecretKeyTag: base64.StdEncoding.EncodeToString(encryptedKey.AuthTag), + SecretKeyHash: hashedKey, + SecretValueCiphertext: base64.StdEncoding.EncodeToString(encryptedValue.CipherText), + SecretValueIV: base64.StdEncoding.EncodeToString(encryptedValue.Nonce), + SecretValueTag: base64.StdEncoding.EncodeToString(encryptedValue.AuthTag), + SecretValueHash: hashedValue, + Type: secretType, + PlainTextKey: key, + } + secretsToCreate = append(secretsToCreate, encryptedSecretDetails) + secretOperations = append(secretOperations, models.SecretSetOperation{ + SecretKey: key, + SecretValue: value, + SecretOperation: "SECRET CREATED", + }) + } + } + + for _, secret := range secretsToCreate { + createSecretRequest := api.CreateSecretV3Request{ + WorkspaceID: workspaceFile.WorkspaceId, + Environment: environmentName, + SecretName: secret.PlainTextKey, + SecretKeyCiphertext: secret.SecretKeyCiphertext, + SecretKeyIV: secret.SecretKeyIV, + SecretKeyTag: secret.SecretKeyTag, + SecretValueCiphertext: secret.SecretValueCiphertext, + SecretValueIV: secret.SecretValueIV, + SecretValueTag: secret.SecretValueTag, + Type: secret.Type, + SecretPath: secretsPath, + } + + err = api.CallCreateSecretsV3(httpClient, createSecretRequest) + if err != nil { + return nil, fmt.Errorf("unable to process new secret creations [err=%v]", err) + } + } + + for _, secret := range secretsToModify { + updateSecretRequest := api.UpdateSecretByNameV3Request{ + WorkspaceID: workspaceFile.WorkspaceId, + Environment: environmentName, + SecretValueCiphertext: secret.SecretValueCiphertext, + SecretValueIV: secret.SecretValueIV, + SecretValueTag: secret.SecretValueTag, + Type: secret.Type, + SecretPath: secretsPath, + } + + err = api.CallUpdateSecretsV3(httpClient, updateSecretRequest, secret.PlainTextKey) + if err != nil { + return nil, fmt.Errorf("unable to process secret update request [err=%v]", err) + } + } + + return secretOperations, nil + +} + +func SetRawSecrets(secretArgs []string, secretType string, environmentName string, secretsPath string, projectId string, tokenDetails *models.TokenDetails) ([]models.SecretSetOperation, error) { + + if tokenDetails == nil { + return nil, fmt.Errorf("unable to process set secret operations, token details are missing") + } + + fmt.Printf("\nToken details %v", tokenDetails) + + getAllEnvironmentVariablesRequest := models.GetAllSecretsParameters{Environment: environmentName, SecretsPath: secretsPath, WorkspaceId: projectId} + if tokenDetails.Type == UNIVERSAL_AUTH_TOKEN_IDENTIFIER { + getAllEnvironmentVariablesRequest.UniversalAuthAccessToken = tokenDetails.Token + } else { + getAllEnvironmentVariablesRequest.InfisicalToken = tokenDetails.Token + } + + httpClient := resty.New(). + SetAuthScheme("Bearer"). + SetAuthToken(tokenDetails.Token). + SetHeader("Accept", "application/json") + + // pull current secrets + secrets, err := GetAllEnvironmentVariables(getAllEnvironmentVariablesRequest, "") + if err != nil { + return nil, fmt.Errorf("unable to retrieve secrets [err=%v]", err) + } + + secretsToCreate := []api.RawSecret{} + secretsToModify := []api.RawSecret{} + secretOperations := []models.SecretSetOperation{} + + sharedSecretMapByName := make(map[string]models.SingleEnvironmentVariable, len(secrets)) + personalSecretMapByName := make(map[string]models.SingleEnvironmentVariable, len(secrets)) + + for _, secret := range secrets { + if secret.Type == SECRET_TYPE_PERSONAL { + personalSecretMapByName[secret.Key] = secret + } else { + sharedSecretMapByName[secret.Key] = secret + } + } + + for _, arg := range secretArgs { + splitKeyValueFromArg := strings.SplitN(arg, "=", 2) + if splitKeyValueFromArg[0] == "" || splitKeyValueFromArg[1] == "" { + PrintErrorMessageAndExit("ensure that each secret has a none empty key and value. Modify the input and try again") + } + + if unicode.IsNumber(rune(splitKeyValueFromArg[0][0])) { + PrintErrorMessageAndExit("keys of secrets cannot start with a number. Modify the key name(s) and try again") + } + + // Key and value from argument + key := splitKeyValueFromArg[0] + value := splitKeyValueFromArg[1] + + var existingSecret models.SingleEnvironmentVariable + var doesSecretExist bool + + if secretType == SECRET_TYPE_SHARED { + existingSecret, doesSecretExist = sharedSecretMapByName[key] + } else { + existingSecret, doesSecretExist = personalSecretMapByName[key] + } + + if doesSecretExist { + // case: secret exists in project so it needs to be modified + encryptedSecretDetails := api.RawSecret{ + ID: existingSecret.ID, + SecretValue: value, + SecretKey: key, + Type: existingSecret.Type, + } + + // Only add to modifications if the value is different + if existingSecret.Value != value { + secretsToModify = append(secretsToModify, encryptedSecretDetails) + secretOperations = append(secretOperations, models.SecretSetOperation{ + SecretKey: key, + SecretValue: value, + SecretOperation: "SECRET VALUE MODIFIED", + }) + } else { + // Current value is same as existing so no change + secretOperations = append(secretOperations, models.SecretSetOperation{ + SecretKey: key, + SecretValue: value, + SecretOperation: "SECRET VALUE UNCHANGED", + }) + } + + } else { + // case: secret doesn't exist in project so it needs to be created + encryptedSecretDetails := api.RawSecret{ + SecretKey: key, + SecretValue: value, + Type: secretType, + } + secretsToCreate = append(secretsToCreate, encryptedSecretDetails) + secretOperations = append(secretOperations, models.SecretSetOperation{ + SecretKey: key, + SecretValue: value, + SecretOperation: "SECRET CREATED", + }) + } + } + + for _, secret := range secretsToCreate { + createSecretRequest := api.CreateRawSecretV3Request{ + SecretName: secret.SecretKey, + SecretValue: secret.SecretValue, + Type: secret.Type, + SecretPath: secretsPath, + WorkspaceID: projectId, + Environment: environmentName, + } + + err = api.CallCreateRawSecretsV3(httpClient, createSecretRequest) + if err != nil { + return nil, fmt.Errorf("unable to process new secret creations [err=%v]", err) + } + } + + for _, secret := range secretsToModify { + updateSecretRequest := api.UpdateRawSecretByNameV3Request{ + SecretName: secret.SecretKey, + SecretValue: secret.SecretValue, + SecretPath: secretsPath, + WorkspaceID: projectId, + Environment: environmentName, + Type: secret.Type, + } + + err = api.CallUpdateRawSecretsV3(httpClient, updateSecretRequest) + if err != nil { + return nil, fmt.Errorf("unable to process secret update request [err=%v]", err) + } + } + + return secretOperations, nil + +} From c4f9a3b31e7e4ea062df751dfacc9b8b1e654341 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Sat, 15 Jun 2024 08:48:03 +0200 Subject: [PATCH 05/12] Feat: Unify CLI auth methods --- cli/packages/util/folders.go | 44 ++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/cli/packages/util/folders.go b/cli/packages/util/folders.go index 18fe5c888..80d31a891 100644 --- a/cli/packages/util/folders.go +++ b/cli/packages/util/folders.go @@ -172,19 +172,27 @@ func GetFoldersViaMachineIdentity(accessToken string, workspaceId string, envSlu // CreateFolder creates a folder in Infisical func CreateFolder(params models.CreateFolderParameters) (models.SingleFolder, error) { - loggedInUserDetails, err := GetCurrentLoggedInUserDetails() - if err != nil { - return models.SingleFolder{}, err - } - if loggedInUserDetails.LoginExpired { - PrintErrorMessageAndExit("Your login session has expired, please run [infisical login] and try again") + // If no token is provided, we will try to get the token from the current logged in user + if params.InfisicalToken == "" { + RequireLogin() + loggedInUserDetails, err := GetCurrentLoggedInUserDetails() + + if err != nil { + return models.SingleFolder{}, err + } + + if loggedInUserDetails.LoginExpired { + PrintErrorMessageAndExit("Your login session has expired, please run [infisical login] and try again") + } + + params.InfisicalToken = loggedInUserDetails.UserCredentials.JTWToken } // set up resty client httpClient := resty.New() httpClient. - SetAuthToken(loggedInUserDetails.UserCredentials.JTWToken). + SetAuthToken(params.InfisicalToken). SetHeader("Accept", "application/json"). SetHeader("Content-Type", "application/json") @@ -209,19 +217,27 @@ func CreateFolder(params models.CreateFolderParameters) (models.SingleFolder, er } func DeleteFolder(params models.DeleteFolderParameters) ([]models.SingleFolder, error) { - loggedInUserDetails, err := GetCurrentLoggedInUserDetails() - if err != nil { - return nil, err - } - if loggedInUserDetails.LoginExpired { - PrintErrorMessageAndExit("Your login session has expired, please run [infisical login] and try again") + // If no token is provided, we will try to get the token from the current logged in user + if params.InfisicalToken == "" { + RequireLogin() + loggedInUserDetails, err := GetCurrentLoggedInUserDetails() + + if err != nil { + return nil, err + } + + if loggedInUserDetails.LoginExpired { + PrintErrorMessageAndExit("Your login session has expired, please run [infisical login] and try again") + } + + params.InfisicalToken = loggedInUserDetails.UserCredentials.JTWToken } // set up resty client httpClient := resty.New() httpClient. - SetAuthToken(loggedInUserDetails.UserCredentials.JTWToken). + SetAuthToken(params.InfisicalToken). SetHeader("Accept", "application/json"). SetHeader("Content-Type", "application/json") From f490fb6616c56600640f42fc872117956ef62b0e Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Sat, 15 Jun 2024 08:48:05 +0200 Subject: [PATCH 06/12] Update cli.go --- cli/packages/models/cli.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cli/packages/models/cli.go b/cli/packages/models/cli.go index 68527c469..6f996d667 100644 --- a/cli/packages/models/cli.go +++ b/cli/packages/models/cli.go @@ -134,3 +134,9 @@ type MachineIdentityCredentials struct { ClientId string ClientSecret string } + +type SecretSetOperation struct { + SecretKey string + SecretValue string + SecretOperation string +} From 3b2a2d1a737cd22fb5518adf78709d4a66e14ae1 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Sat, 15 Jun 2024 08:48:11 +0200 Subject: [PATCH 07/12] Feat: Unify CLI auth methods --- cli/packages/cmd/secrets.go | 286 ++++++++---------------------------- 1 file changed, 62 insertions(+), 224 deletions(-) diff --git a/cli/packages/cmd/secrets.go b/cli/packages/cmd/secrets.go index 423fe1657..731a023dc 100644 --- a/cli/packages/cmd/secrets.go +++ b/cli/packages/cmd/secrets.go @@ -4,23 +4,17 @@ Copyright (c) 2023 Infisical Inc. package cmd import ( - "crypto/sha256" - "encoding/base64" "fmt" - "os" "regexp" "sort" "strings" - "unicode" "github.com/Infisical/infisical-merge/packages/api" - "github.com/Infisical/infisical-merge/packages/crypto" "github.com/Infisical/infisical-merge/packages/models" "github.com/Infisical/infisical-merge/packages/util" "github.com/Infisical/infisical-merge/packages/visualize" "github.com/go-resty/resty/v2" "github.com/posthog/posthog-go" - "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) @@ -160,14 +154,19 @@ var secretsSetCmd = &cobra.Command{ } } - secretsPath, err := cmd.Flags().GetString("path") + token, err := util.GetInfisicalToken(cmd) if err != nil { util.HandleError(err, "Unable to parse flag") } - workspaceFile, err := util.GetWorkSpaceFromFile() + projectId, err := cmd.Flags().GetString("projectId") if err != nil { - util.HandleError(err, "Unable to get your local config details") + util.HandleError(err, "Unable to parse flag") + } + + secretsPath, err := cmd.Flags().GetString("path") + if err != nil { + util.HandleError(err, "Unable to parse flag") } secretType, err := cmd.Flags().GetString("type") @@ -175,196 +174,18 @@ var secretsSetCmd = &cobra.Command{ util.HandleError(err, "Unable to parse secret type") } - loggedInUserDetails, err := util.GetCurrentLoggedInUserDetails() + var secretOperations []models.SecretSetOperation + if token != nil && (token.Type == util.SERVICE_TOKEN_IDENTIFIER || token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER) { + secretOperations, err = util.SetRawSecrets(args, secretType, environmentName, secretsPath, projectId, token) + } else { + util.RequireLogin() + util.RequireLocalWorkspaceFile() + + secretOperations, err = util.SetEncryptedSecrets(args, secretType, environmentName, secretsPath) + } + if err != nil { - util.HandleError(err, "Unable to authenticate") - } - - if loggedInUserDetails.LoginExpired { - util.PrintErrorMessageAndExit("Your login session has expired, please run [infisical login] and try again") - } - - - httpClient := resty.New(). - SetAuthToken(loggedInUserDetails.UserCredentials.JTWToken). - SetHeader("Accept", "application/json") - - request := api.GetEncryptedWorkspaceKeyRequest{ - WorkspaceId: workspaceFile.WorkspaceId, - } - - workspaceKeyResponse, err := api.CallGetEncryptedWorkspaceKey(httpClient, request) - if err != nil { - util.HandleError(err, "unable to get your encrypted workspace key") - } - - encryptedWorkspaceKey, _ := base64.StdEncoding.DecodeString(workspaceKeyResponse.EncryptedKey) - encryptedWorkspaceKeySenderPublicKey, _ := base64.StdEncoding.DecodeString(workspaceKeyResponse.Sender.PublicKey) - encryptedWorkspaceKeyNonce, _ := base64.StdEncoding.DecodeString(workspaceKeyResponse.Nonce) - currentUsersPrivateKey, _ := base64.StdEncoding.DecodeString(loggedInUserDetails.UserCredentials.PrivateKey) - - if len(currentUsersPrivateKey) == 0 || len(encryptedWorkspaceKeySenderPublicKey) == 0 { - log.Debug().Msgf("Missing credentials for generating plainTextEncryptionKey: [currentUsersPrivateKey=%s] [encryptedWorkspaceKeySenderPublicKey=%s]", currentUsersPrivateKey, encryptedWorkspaceKeySenderPublicKey) - util.PrintErrorMessageAndExit("Some required user credentials are missing to generate your [plainTextEncryptionKey]. Please run [infisical login] then try again") - } - - // decrypt workspace key - plainTextEncryptionKey := crypto.DecryptAsymmetric(encryptedWorkspaceKey, encryptedWorkspaceKeyNonce, encryptedWorkspaceKeySenderPublicKey, currentUsersPrivateKey) - - infisicalTokenEnv := os.Getenv(util.INFISICAL_TOKEN_NAME) - - // pull current secrets - secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, SecretsPath: secretsPath, InfisicalToken: infisicalTokenEnv}, "") - if err != nil { - util.HandleError(err, "unable to retrieve secrets") - } - - type SecretSetOperation struct { - SecretKey string - SecretValue string - SecretOperation string - } - - secretsToCreate := []api.Secret{} - secretsToModify := []api.Secret{} - secretOperations := []SecretSetOperation{} - - sharedSecretMapByName := make(map[string]models.SingleEnvironmentVariable, len(secrets)) - personalSecretMapByName := make(map[string]models.SingleEnvironmentVariable, len(secrets)) - - for _, secret := range secrets { - if secret.Type == util.SECRET_TYPE_PERSONAL { - personalSecretMapByName[secret.Key] = secret - } else { - sharedSecretMapByName[secret.Key] = secret - } - } - - for _, arg := range args { - splitKeyValueFromArg := strings.SplitN(arg, "=", 2) - if splitKeyValueFromArg[0] == "" || splitKeyValueFromArg[1] == "" { - util.PrintErrorMessageAndExit("ensure that each secret has a none empty key and value. Modify the input and try again") - } - - if unicode.IsNumber(rune(splitKeyValueFromArg[0][0])) { - util.PrintErrorMessageAndExit("keys of secrets cannot start with a number. Modify the key name(s) and try again") - } - - // Key and value from argument - key := splitKeyValueFromArg[0] - value := splitKeyValueFromArg[1] - - hashedKey := fmt.Sprintf("%x", sha256.Sum256([]byte(key))) - encryptedKey, err := crypto.EncryptSymmetric([]byte(key), []byte(plainTextEncryptionKey)) - if err != nil { - util.HandleError(err, "unable to encrypt your secrets") - } - - hashedValue := fmt.Sprintf("%x", sha256.Sum256([]byte(value))) - encryptedValue, err := crypto.EncryptSymmetric([]byte(value), []byte(plainTextEncryptionKey)) - if err != nil { - util.HandleError(err, "unable to encrypt your secrets") - } - - var existingSecret models.SingleEnvironmentVariable - var doesSecretExist bool - - if secretType == util.SECRET_TYPE_SHARED { - existingSecret, doesSecretExist = sharedSecretMapByName[key] - } else { - existingSecret, doesSecretExist = personalSecretMapByName[key] - } - - if doesSecretExist { - // case: secret exists in project so it needs to be modified - encryptedSecretDetails := api.Secret{ - ID: existingSecret.ID, - SecretValueCiphertext: base64.StdEncoding.EncodeToString(encryptedValue.CipherText), - SecretValueIV: base64.StdEncoding.EncodeToString(encryptedValue.Nonce), - SecretValueTag: base64.StdEncoding.EncodeToString(encryptedValue.AuthTag), - SecretValueHash: hashedValue, - PlainTextKey: key, - Type: existingSecret.Type, - } - - // Only add to modifications if the value is different - if existingSecret.Value != value { - secretsToModify = append(secretsToModify, encryptedSecretDetails) - secretOperations = append(secretOperations, SecretSetOperation{ - SecretKey: key, - SecretValue: value, - SecretOperation: "SECRET VALUE MODIFIED", - }) - } else { - // Current value is same as exisitng so no change - secretOperations = append(secretOperations, SecretSetOperation{ - SecretKey: key, - SecretValue: value, - SecretOperation: "SECRET VALUE UNCHANGED", - }) - } - - } else { - // case: secret doesn't exist in project so it needs to be created - encryptedSecretDetails := api.Secret{ - SecretKeyCiphertext: base64.StdEncoding.EncodeToString(encryptedKey.CipherText), - SecretKeyIV: base64.StdEncoding.EncodeToString(encryptedKey.Nonce), - SecretKeyTag: base64.StdEncoding.EncodeToString(encryptedKey.AuthTag), - SecretKeyHash: hashedKey, - SecretValueCiphertext: base64.StdEncoding.EncodeToString(encryptedValue.CipherText), - SecretValueIV: base64.StdEncoding.EncodeToString(encryptedValue.Nonce), - SecretValueTag: base64.StdEncoding.EncodeToString(encryptedValue.AuthTag), - SecretValueHash: hashedValue, - Type: secretType, - PlainTextKey: key, - } - secretsToCreate = append(secretsToCreate, encryptedSecretDetails) - secretOperations = append(secretOperations, SecretSetOperation{ - SecretKey: key, - SecretValue: value, - SecretOperation: "SECRET CREATED", - }) - } - } - - for _, secret := range secretsToCreate { - createSecretRequest := api.CreateSecretV3Request{ - WorkspaceID: workspaceFile.WorkspaceId, - Environment: environmentName, - SecretName: secret.PlainTextKey, - SecretKeyCiphertext: secret.SecretKeyCiphertext, - SecretKeyIV: secret.SecretKeyIV, - SecretKeyTag: secret.SecretKeyTag, - SecretValueCiphertext: secret.SecretValueCiphertext, - SecretValueIV: secret.SecretValueIV, - SecretValueTag: secret.SecretValueTag, - Type: secret.Type, - SecretPath: secretsPath, - } - - err = api.CallCreateSecretsV3(httpClient, createSecretRequest) - if err != nil { - util.HandleError(err, "Unable to process new secret creations") - return - } - } - - for _, secret := range secretsToModify { - updateSecretRequest := api.UpdateSecretByNameV3Request{ - WorkspaceID: workspaceFile.WorkspaceId, - Environment: environmentName, - SecretValueCiphertext: secret.SecretValueCiphertext, - SecretValueIV: secret.SecretValueIV, - SecretValueTag: secret.SecretValueTag, - Type: secret.Type, - SecretPath: secretsPath, - } - - err = api.CallUpdateSecretsV3(httpClient, updateSecretRequest, secret.PlainTextKey) - if err != nil { - util.HandleError(err, "Unable to process secret update request") - return - } + util.HandleError(err, "Unable to set secrets") } // Print secret operations @@ -395,6 +216,16 @@ var secretsDeleteCmd = &cobra.Command{ } } + token, err := util.GetInfisicalToken(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") + } + secretsPath, err := cmd.Flags().GetString("path") if err != nil { util.HandleError(err, "Unable to parse flag") @@ -405,33 +236,44 @@ var secretsDeleteCmd = &cobra.Command{ util.HandleError(err, "Unable to parse flag") } - loggedInUserDetails, err := util.GetCurrentLoggedInUserDetails() - if err != nil { - util.HandleError(err, "Unable to authenticate") + httpClient := resty.New(). + SetHeader("Accept", "application/json") + + if projectId == "" { + workspaceFile, err := util.GetWorkSpaceFromFile() + if err != nil { + util.HandleError(err, "Unable to get local project details") + } + projectId = workspaceFile.WorkspaceId } - if loggedInUserDetails.LoginExpired { - util.PrintErrorMessageAndExit("Your login session has expired, please run [infisical login] and try again") - } + if token != nil && (token.Type == util.SERVICE_TOKEN_IDENTIFIER || token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER) { + httpClient.SetAuthScheme("Bearer").SetAuthToken(token.Token) + } else { + util.RequireLogin() + util.RequireLocalWorkspaceFile() - workspaceFile, err := util.GetWorkSpaceFromFile() - if err != nil { - util.HandleError(err, "Unable to get local project details") + loggedInUserDetails, err := util.GetCurrentLoggedInUserDetails() + if err != nil { + util.HandleError(err, "Unable to authenticate") + } + + if loggedInUserDetails.LoginExpired { + util.PrintErrorMessageAndExit("Your login session has expired, please run [infisical login] and try again") + } + + httpClient.SetAuthToken(loggedInUserDetails.UserCredentials.JTWToken) } for _, secretName := range args { request := api.DeleteSecretV3Request{ - WorkspaceId: workspaceFile.WorkspaceId, + WorkspaceId: projectId, Environment: environmentName, SecretName: secretName, Type: secretType, SecretPath: secretsPath, } - httpClient := resty.New(). - SetAuthToken(loggedInUserDetails.UserCredentials.JTWToken). - SetHeader("Accept", "application/json") - err = api.CallDeleteSecretsV3(httpClient, request) if err != nil { util.HandleError(err, "Unable to complete your delete request") @@ -804,25 +646,17 @@ func init() { secretsCmd.Flags().Bool("secret-overriding", true, "Prioritizes personal secrets, if any, with the same name over shared secrets") secretsCmd.AddCommand(secretsSetCmd) + secretsSetCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") + secretsSetCmd.Flags().String("projectId", "", "manually set the projectId to fetch folders from for machine identity") secretsSetCmd.Flags().String("path", "/", "set secrets within a folder path") secretsSetCmd.Flags().String("type", util.SECRET_TYPE_SHARED, "the type of secret to create: personal or shared") - // Only supports logged in users (JWT auth) - secretsSetCmd.PersistentPreRun = func(cmd *cobra.Command, args []string) { - util.RequireLogin() - util.RequireLocalWorkspaceFile() - } - secretsDeleteCmd.Flags().String("type", "personal", "the type of secret to delete: personal or shared (default: personal)") + secretsDeleteCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") + secretsDeleteCmd.Flags().String("projectId", "", "manually set the projectId to fetch folders from for machine identity") 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() - } - // *** Folders sub command *** folderCmd.PersistentFlags().String("env", "dev", "Used to select the environment name on which actions should be taken on") @@ -835,10 +669,14 @@ func init() { // Add createCmd flags here createCmd.Flags().StringP("path", "p", "/", "Path to where the folder should be created") createCmd.Flags().StringP("name", "n", "", "Name of the folder to be created in selected `--path`") + createCmd.Flags().String("token", "", "Fetch folders using the infisical token") + createCmd.Flags().String("projectId", "", "manually set the projectId to fetch folders from for machine identity") folderCmd.AddCommand(createCmd) // Add deleteCmd flags here deleteCmd.Flags().StringP("path", "p", "/", "Path to the folder to be deleted") + deleteCmd.Flags().String("token", "", "Fetch folders using the infisical token") + deleteCmd.Flags().String("projectId", "", "manually set the projectId to fetch folders from for machine identity") deleteCmd.Flags().StringP("name", "n", "", "Name of the folder to be deleted within selected `--path`") folderCmd.AddCommand(deleteCmd) From 49d2ea6f2e562b7108a0fcae340401cccbce5bd9 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Sat, 15 Jun 2024 08:48:14 +0200 Subject: [PATCH 08/12] Feat: Unify CLI auth methods --- cli/packages/cmd/folder.go | 71 +++++++++++++++++++++++++++++--------- 1 file changed, 55 insertions(+), 16 deletions(-) diff --git a/cli/packages/cmd/folder.go b/cli/packages/cmd/folder.go index 9cb76a312..cd50322d0 100644 --- a/cli/packages/cmd/folder.go +++ b/cli/packages/cmd/folder.go @@ -1,6 +1,7 @@ package cmd import ( + "errors" "fmt" "github.com/Infisical/infisical-merge/packages/models" @@ -71,10 +72,6 @@ var getCmd = &cobra.Command{ var createCmd = &cobra.Command{ Use: "create", Short: "Create a folder", - PersistentPreRun: func(cmd *cobra.Command, args []string) { - util.RequireLogin() - util.RequireLocalWorkspaceFile() - }, Run: func(cmd *cobra.Command, args []string) { environmentName, _ := cmd.Flags().GetString("env") if !cmd.Flags().Changed("env") { @@ -84,6 +81,16 @@ var createCmd = &cobra.Command{ } } + token, err := util.GetInfisicalToken(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") + } + folderPath, err := cmd.Flags().GetString("path") if err != nil { util.HandleError(err, "Unable to parse flag") @@ -95,19 +102,34 @@ var createCmd = &cobra.Command{ } if folderName == "" { - util.HandleError(fmt.Errorf("Invalid folder name"), "Folder name cannot be empty") + util.HandleError(errors.New("invalid folder name, folder name cannot be empty")) } - workspaceFile, err := util.GetWorkSpaceFromFile() if err != nil { util.HandleError(err, "Unable to get workspace file") } + if projectId == "" { + workspaceFile, err := util.GetWorkSpaceFromFile() + if err != nil { + util.HandleError(err, "Unable to get workspace file") + } + + projectId = workspaceFile.WorkspaceId + } + params := models.CreateFolderParameters{ FolderName: folderName, - WorkspaceId: workspaceFile.WorkspaceId, Environment: environmentName, FolderPath: folderPath, + WorkspaceId: projectId, + } + + if token != nil && (token.Type == util.SERVICE_TOKEN_IDENTIFIER || token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER) { + params.InfisicalToken = token.Token + } else { + util.RequireLogin() + util.RequireLocalWorkspaceFile() } _, err = util.CreateFolder(params) @@ -124,10 +146,6 @@ var createCmd = &cobra.Command{ var deleteCmd = &cobra.Command{ Use: "delete", Short: "Delete a folder", - PersistentPreRun: func(cmd *cobra.Command, args []string) { - util.RequireLogin() - util.RequireLocalWorkspaceFile() - }, Run: func(cmd *cobra.Command, args []string) { environmentName, _ := cmd.Flags().GetString("env") @@ -138,6 +156,16 @@ var deleteCmd = &cobra.Command{ } } + token, err := util.GetInfisicalToken(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") + } + folderPath, err := cmd.Flags().GetString("path") if err != nil { util.HandleError(err, "Unable to parse flag") @@ -149,21 +177,32 @@ var deleteCmd = &cobra.Command{ } if folderName == "" { - util.HandleError(fmt.Errorf("Invalid folder name"), "Folder name cannot be empty") + util.HandleError(errors.New("invalid folder name, folder name cannot be empty")) } - workspaceFile, err := util.GetWorkSpaceFromFile() - if err != nil { - util.HandleError(err, "Unable to get workspace file") + if projectId == "" { + workspaceFile, err := util.GetWorkSpaceFromFile() + if err != nil { + util.HandleError(err, "Unable to get workspace file") + } + + projectId = workspaceFile.WorkspaceId } params := models.DeleteFolderParameters{ FolderName: folderName, - WorkspaceId: workspaceFile.WorkspaceId, + WorkspaceId: projectId, Environment: environmentName, FolderPath: folderPath, } + if token != nil && (token.Type == util.SERVICE_TOKEN_IDENTIFIER || token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER) { + params.InfisicalToken = token.Token + } else { + util.RequireLogin() + util.RequireLocalWorkspaceFile() + } + _, err = util.DeleteFolder(params) if err != nil { util.HandleError(err, "Unable to delete folder") From cb237831c787d9cb2d0122081457be5b04a21642 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Sat, 15 Jun 2024 08:56:48 +0200 Subject: [PATCH 09/12] Remove log --- cli/packages/util/secrets.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/cli/packages/util/secrets.go b/cli/packages/util/secrets.go index 1114d9ad9..9bcf66f31 100644 --- a/cli/packages/util/secrets.go +++ b/cli/packages/util/secrets.go @@ -1009,8 +1009,6 @@ func SetRawSecrets(secretArgs []string, secretType string, environmentName strin return nil, fmt.Errorf("unable to process set secret operations, token details are missing") } - fmt.Printf("\nToken details %v", tokenDetails) - getAllEnvironmentVariablesRequest := models.GetAllSecretsParameters{Environment: environmentName, SecretsPath: secretsPath, WorkspaceId: projectId} if tokenDetails.Type == UNIVERSAL_AUTH_TOKEN_IDENTIFIER { getAllEnvironmentVariablesRequest.UniversalAuthAccessToken = tokenDetails.Token From 1835777832b52b0823b8ea6848752b64bc1ef4c3 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Sat, 15 Jun 2024 08:56:55 +0200 Subject: [PATCH 10/12] Move validation --- cli/packages/cmd/folder.go | 6 ------ cli/packages/util/folders.go | 3 +++ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/cli/packages/cmd/folder.go b/cli/packages/cmd/folder.go index cd50322d0..538f1e2dc 100644 --- a/cli/packages/cmd/folder.go +++ b/cli/packages/cmd/folder.go @@ -127,9 +127,6 @@ var createCmd = &cobra.Command{ if token != nil && (token.Type == util.SERVICE_TOKEN_IDENTIFIER || token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER) { params.InfisicalToken = token.Token - } else { - util.RequireLogin() - util.RequireLocalWorkspaceFile() } _, err = util.CreateFolder(params) @@ -198,9 +195,6 @@ var deleteCmd = &cobra.Command{ if token != nil && (token.Type == util.SERVICE_TOKEN_IDENTIFIER || token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER) { params.InfisicalToken = token.Token - } else { - util.RequireLogin() - util.RequireLocalWorkspaceFile() } _, err = util.DeleteFolder(params) diff --git a/cli/packages/util/folders.go b/cli/packages/util/folders.go index 80d31a891..c7f6de630 100644 --- a/cli/packages/util/folders.go +++ b/cli/packages/util/folders.go @@ -176,6 +176,7 @@ func CreateFolder(params models.CreateFolderParameters) (models.SingleFolder, er // If no token is provided, we will try to get the token from the current logged in user if params.InfisicalToken == "" { RequireLogin() + RequireLocalWorkspaceFile() loggedInUserDetails, err := GetCurrentLoggedInUserDetails() if err != nil { @@ -221,6 +222,8 @@ func DeleteFolder(params models.DeleteFolderParameters) ([]models.SingleFolder, // If no token is provided, we will try to get the token from the current logged in user if params.InfisicalToken == "" { RequireLogin() + RequireLocalWorkspaceFile() + loggedInUserDetails, err := GetCurrentLoggedInUserDetails() if err != nil { From 24935f4e074e30a3cf2c36b4582b1747fd73c83b Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Sat, 15 Jun 2024 08:59:00 +0200 Subject: [PATCH 11/12] Remove redundant auth schema set (defaults to Bearer) --- cli/packages/cmd/secrets.go | 2 +- cli/packages/util/secrets.go | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/cli/packages/cmd/secrets.go b/cli/packages/cmd/secrets.go index 731a023dc..7e10baa22 100644 --- a/cli/packages/cmd/secrets.go +++ b/cli/packages/cmd/secrets.go @@ -248,7 +248,7 @@ var secretsDeleteCmd = &cobra.Command{ } if token != nil && (token.Type == util.SERVICE_TOKEN_IDENTIFIER || token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER) { - httpClient.SetAuthScheme("Bearer").SetAuthToken(token.Token) + httpClient.SetAuthToken(token.Token) } else { util.RequireLogin() util.RequireLocalWorkspaceFile() diff --git a/cli/packages/util/secrets.go b/cli/packages/util/secrets.go index 9bcf66f31..08e6b563f 100644 --- a/cli/packages/util/secrets.go +++ b/cli/packages/util/secrets.go @@ -1017,7 +1017,6 @@ func SetRawSecrets(secretArgs []string, secretType string, environmentName strin } httpClient := resty.New(). - SetAuthScheme("Bearer"). SetAuthToken(tokenDetails.Token). SetHeader("Accept", "application/json") From 473f8137fdb076b957433fa218b708b14751e033 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Tue, 18 Jun 2024 13:33:41 +0200 Subject: [PATCH 12/12] Improved flag descriptions --- cli/packages/cmd/export.go | 4 ++-- cli/packages/cmd/run.go | 4 ++-- cli/packages/cmd/secrets.go | 32 ++++++++++++++++---------------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/cli/packages/cmd/export.go b/cli/packages/cmd/export.go index 012e21ba6..c0fea738e 100644 --- a/cli/packages/cmd/export.go +++ b/cli/packages/cmd/export.go @@ -169,9 +169,9 @@ 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().Bool("include-imports", true, "Imported linked secrets") - exportCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") + exportCmd.Flags().String("token", "", "Fetch secrets using service token or machine identity access token") 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("projectId", "", "manually set the projectId to export secrets from") exportCmd.Flags().String("path", "/", "get secrets within a folder path") exportCmd.Flags().String("template", "", "The path to the template file used to render secrets") } diff --git a/cli/packages/cmd/run.go b/cli/packages/cmd/run.go index 04fe2588b..22a4ca65b 100644 --- a/cli/packages/cmd/run.go +++ b/cli/packages/cmd/run.go @@ -237,8 +237,8 @@ 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("projectId", "", "manually set the projectId to fetch folders from for machine identity") + runCmd.Flags().String("token", "", "Fetch secrets using service token or machine identity access token") + runCmd.Flags().String("projectId", "", "manually set the project ID to fetch secrets from when using machine identity based auth") 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 ") diff --git a/cli/packages/cmd/secrets.go b/cli/packages/cmd/secrets.go index 7e10baa22..43c159c34 100644 --- a/cli/packages/cmd/secrets.go +++ b/cli/packages/cmd/secrets.go @@ -631,13 +631,13 @@ func getSecretsByKeys(secrets []models.SingleEnvironmentVariable) map[string]mod } func init() { - secretsGenerateExampleEnvCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") - secretsGenerateExampleEnvCmd.Flags().String("projectId", "", "manually set the projectId to fetch folders from for machine identity") + secretsGenerateExampleEnvCmd.Flags().String("token", "", "Fetch secrets using service token or machine identity access token") + secretsGenerateExampleEnvCmd.Flags().String("projectId", "", "manually set the projectId when using machine identity based auth") 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("projectId", "", "manually set the projectId to fetch folders from for machine identity") + secretsGetCmd.Flags().String("token", "", "Fetch secrets using service token or machine identity access token") + secretsGetCmd.Flags().String("projectId", "", "manually set the project ID to fetch secrets from when using machine identity based auth") 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") @@ -646,14 +646,14 @@ func init() { secretsCmd.Flags().Bool("secret-overriding", true, "Prioritizes personal secrets, if any, with the same name over shared secrets") secretsCmd.AddCommand(secretsSetCmd) - secretsSetCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") - secretsSetCmd.Flags().String("projectId", "", "manually set the projectId to fetch folders from for machine identity") + secretsSetCmd.Flags().String("token", "", "Fetch secrets using service token or machine identity access token") + secretsSetCmd.Flags().String("projectId", "", "manually set the project ID to for setting secrets when using machine identity based auth") secretsSetCmd.Flags().String("path", "/", "set secrets within a folder path") secretsSetCmd.Flags().String("type", util.SECRET_TYPE_SHARED, "the type of secret to create: personal or shared") secretsDeleteCmd.Flags().String("type", "personal", "the type of secret to delete: personal or shared (default: personal)") - secretsDeleteCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") - secretsDeleteCmd.Flags().String("projectId", "", "manually set the projectId to fetch folders from for machine identity") + secretsDeleteCmd.Flags().String("token", "", "Fetch secrets using service token or machine identity access token") + secretsDeleteCmd.Flags().String("projectId", "", "manually set the projectId to delete secrets from when using machine identity based auth") secretsDeleteCmd.Flags().String("path", "/", "get secrets within a folder path") secretsCmd.AddCommand(secretsDeleteCmd) @@ -662,21 +662,21 @@ 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("projectId", "", "manually set the projectId to fetch folders from for machine identity") + getCmd.Flags().String("token", "", "Fetch secrets using service token or machine identity access token") + getCmd.Flags().String("projectId", "", "manually set the projectId to fetch folders from when using machine identity based auth") folderCmd.AddCommand(getCmd) // Add createCmd flags here createCmd.Flags().StringP("path", "p", "/", "Path to where the folder should be created") createCmd.Flags().StringP("name", "n", "", "Name of the folder to be created in selected `--path`") - createCmd.Flags().String("token", "", "Fetch folders using the infisical token") - createCmd.Flags().String("projectId", "", "manually set the projectId to fetch folders from for machine identity") + createCmd.Flags().String("token", "", "Fetch secrets using service token or machine identity access token") + createCmd.Flags().String("projectId", "", "manually set the project ID for creating folders in when using machine identity based auth") folderCmd.AddCommand(createCmd) // Add deleteCmd flags here deleteCmd.Flags().StringP("path", "p", "/", "Path to the folder to be deleted") - deleteCmd.Flags().String("token", "", "Fetch folders using the infisical token") - deleteCmd.Flags().String("projectId", "", "manually set the projectId to fetch folders from for machine identity") + deleteCmd.Flags().String("token", "", "Fetch secrets using service token or machine identity access token") + deleteCmd.Flags().String("projectId", "", "manually set the projectId to delete folders when using machine identity based auth") deleteCmd.Flags().StringP("name", "n", "", "Name of the folder to be deleted within selected `--path`") folderCmd.AddCommand(deleteCmd) @@ -684,8 +684,8 @@ func init() { // ** End of folders sub command - secretsCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") - secretsCmd.Flags().String("projectId", "", "manually set the projectId to fetch folders from for machine identity") + secretsCmd.Flags().String("token", "", "Fetch secrets using service token or machine identity access token") + secretsCmd.Flags().String("projectId", "", "manually set the projectId to fetch secrets when using machine identity based auth") 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 ")