mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-03 05:25:56 +00:00
delete, get and create via cli
This commit is contained in:
@@ -24,7 +24,7 @@ router.post(
|
|||||||
}),
|
}),
|
||||||
param('workspaceId').exists().isMongoId().trim(),
|
param('workspaceId').exists().isMongoId().trim(),
|
||||||
param('environmentName').exists().trim(),
|
param('environmentName').exists().trim(),
|
||||||
body('secrets').exists().isArray().custom((value) => value.every((item: ISecret) => typeof item === 'object')),
|
body('secrets').exists().isArray().custom((value) => value.every((item: CreateSecretRequestBody) => typeof item === 'object')),
|
||||||
validateRequest,
|
validateRequest,
|
||||||
async (req: Request, res: Response) => {
|
async (req: Request, res: Response) => {
|
||||||
const secretsToCreate: CreateSecretRequestBody[] = req.body.secrets;
|
const secretsToCreate: CreateSecretRequestBody[] = req.body.secrets;
|
||||||
@@ -94,7 +94,7 @@ router.delete(
|
|||||||
requireAuth,
|
requireAuth,
|
||||||
param('workspaceId').exists().isMongoId().trim(),
|
param('workspaceId').exists().isMongoId().trim(),
|
||||||
param('environmentName').exists().trim(),
|
param('environmentName').exists().trim(),
|
||||||
body('secretIds').exists().isArray(),
|
body('secretIds').exists().isArray().custom(array => array.length > 0),
|
||||||
requireWorkspaceAuth({
|
requireWorkspaceAuth({
|
||||||
acceptedRoles: [ADMIN, MEMBER],
|
acceptedRoles: [ADMIN, MEMBER],
|
||||||
acceptedStatuses: [COMPLETED, GRANTED]
|
acceptedStatuses: [COMPLETED, GRANTED]
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ func Execute() {
|
|||||||
func init() {
|
func init() {
|
||||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||||
rootCmd.PersistentFlags().BoolVarP(&debugLogging, "debug", "d", false, "Enable verbose logging")
|
rootCmd.PersistentFlags().BoolVarP(&debugLogging, "debug", "d", false, "Enable verbose logging")
|
||||||
rootCmd.PersistentFlags().StringVar(&util.INFISICAL_URL, "domain", "https://app.infisical.com/api", "Point the CLI to your own backend")
|
rootCmd.PersistentFlags().StringVar(&util.INFISICAL_URL, "domain", "http://localhost:8080/api", "Point the CLI to your own backend")
|
||||||
// rootCmd.PersistentPreRun = func(cmd *cobra.Command, args []string) {
|
// rootCmd.PersistentPreRun = func(cmd *cobra.Command, args []string) {
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
+166
-7
@@ -4,11 +4,17 @@ Copyright © 2022 NAME HERE <EMAIL ADDRESS>
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"crypto/sha256"
|
||||||
|
|
||||||
|
"github.com/Infisical/infisical-merge/packages/http"
|
||||||
"github.com/Infisical/infisical-merge/packages/models"
|
"github.com/Infisical/infisical-merge/packages/models"
|
||||||
"github.com/Infisical/infisical-merge/packages/util"
|
"github.com/Infisical/infisical-merge/packages/util"
|
||||||
"github.com/Infisical/infisical-merge/packages/visualize"
|
"github.com/Infisical/infisical-merge/packages/visualize"
|
||||||
|
"github.com/go-resty/resty/v2"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
@@ -21,14 +27,15 @@ var secretsCmd = &cobra.Command{
|
|||||||
PreRun: toggleDebug,
|
PreRun: toggleDebug,
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
secrets, err := util.GetAllEnvironmentVariables("", "dev")
|
secrets, err := util.GetAllEnvironmentVariables("", "dev")
|
||||||
secrets = util.SubstituteSecrets(secrets)
|
secrets = util.SubstituteSecrets(secrets)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugln(err)
|
log.Debugln(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
visualize.PrintAllSecretDetails(secrets)
|
visualize.PrintAllSecretDetails(secrets)
|
||||||
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,9 +55,95 @@ var secretsSetCmd = &cobra.Command{
|
|||||||
Use: "set [secrets]",
|
Use: "set [secrets]",
|
||||||
DisableFlagsInUseLine: true,
|
DisableFlagsInUseLine: true,
|
||||||
PreRun: toggleDebug,
|
PreRun: toggleDebug,
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.MinimumNArgs(1),
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
fmt.Println("set secret")
|
loggedInUserDetails, err := util.GetCurrentLoggedInUserDetails()
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !loggedInUserDetails.IsUserLoggedIn {
|
||||||
|
log.Error("You are not logged in yet. Please run [infisical login] then try again")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if loggedInUserDetails.IsUserLoggedIn && loggedInUserDetails.LoginExpired {
|
||||||
|
log.Error("Your login has expired. Please run [infisical login] then try again")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
httpClient := resty.New().
|
||||||
|
SetAuthToken(loggedInUserDetails.UserCredentials.JTWToken).
|
||||||
|
SetHeader("Accept", "application/json")
|
||||||
|
|
||||||
|
request := models.GetEncryptedWorkspaceKeyRequest{
|
||||||
|
WorkspaceId: "63b0c1dbf2a30bdfddcfe1ac",
|
||||||
|
}
|
||||||
|
|
||||||
|
workspaceKeyResponse, err := http.CallGetEncryptedWorkspaceKey(httpClient, request)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("unable to get your encrypted workspace key. [err=%v]", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
encryptedWorkspaceKey, _ := base64.StdEncoding.DecodeString(workspaceKeyResponse.LatestKey.EncryptedKey)
|
||||||
|
encryptedWorkspaceKeySenderPublicKey, _ := base64.StdEncoding.DecodeString(workspaceKeyResponse.LatestKey.Sender.PublicKey)
|
||||||
|
encryptedWorkspaceKeyNonce, _ := base64.StdEncoding.DecodeString(workspaceKeyResponse.LatestKey.Nonce)
|
||||||
|
currentUsersPrivateKey, _ := base64.StdEncoding.DecodeString(loggedInUserDetails.UserCredentials.PrivateKey)
|
||||||
|
|
||||||
|
// decrypt workspace key
|
||||||
|
plainTextEncryptionKey := util.DecryptAsymmetric(encryptedWorkspaceKey, encryptedWorkspaceKeyNonce, encryptedWorkspaceKeySenderPublicKey, currentUsersPrivateKey)
|
||||||
|
secretsToUpload := []models.Secret{}
|
||||||
|
for _, arg := range args {
|
||||||
|
splitKeyValueFromArg := strings.SplitN(arg, "=", 2)
|
||||||
|
if len(splitKeyValueFromArg) < 2 {
|
||||||
|
splitKeyValueFromArg[1] = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
key := splitKeyValueFromArg[0]
|
||||||
|
value := splitKeyValueFromArg[1]
|
||||||
|
|
||||||
|
encryptedKey, err := util.EncryptSymmetric([]byte(key), []byte(plainTextEncryptionKey))
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("unable to encrypt your secrets [err=%v]", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
hashedKey := fmt.Sprintf("%x", sha256.Sum256([]byte(key)))
|
||||||
|
|
||||||
|
encryptedValue, err := util.EncryptSymmetric([]byte(value), []byte(plainTextEncryptionKey))
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("unable to encrypt your secrets [err=%v]", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
hashedValue := fmt.Sprintf("%x", sha256.Sum256([]byte(value)))
|
||||||
|
|
||||||
|
fullEncryptedSecret := models.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: "shared",
|
||||||
|
}
|
||||||
|
secretsToUpload = append(secretsToUpload, fullEncryptedSecret)
|
||||||
|
}
|
||||||
|
|
||||||
|
batchCreateRequest := models.BatchCreateSecretsByWorkspaceAndEnvRequest{
|
||||||
|
WorkspaceId: "63b0c1dbf2a30bdfddcfe1ac",
|
||||||
|
EnvironmentName: "dev",
|
||||||
|
Secrets: secretsToUpload,
|
||||||
|
}
|
||||||
|
err = http.CallBatchCreateSecretsByWorkspaceAndEnv(httpClient, batchCreateRequest)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Unable to complete your request because %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("secret name(s) [%v] have been created", strings.Join(args, ", "))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,9 +153,65 @@ var secretsDeleteCmd = &cobra.Command{
|
|||||||
Use: "delete [secrets]",
|
Use: "delete [secrets]",
|
||||||
DisableFlagsInUseLine: true,
|
DisableFlagsInUseLine: true,
|
||||||
PreRun: toggleDebug,
|
PreRun: toggleDebug,
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.MinimumNArgs(1),
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
fmt.Println("Delete secret")
|
loggedInUserDetails, err := util.GetCurrentLoggedInUserDetails()
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !loggedInUserDetails.IsUserLoggedIn {
|
||||||
|
log.Error("You are not logged in yet. Please run [infisical login] then try again")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if loggedInUserDetails.IsUserLoggedIn && loggedInUserDetails.LoginExpired {
|
||||||
|
log.Error("Your login has expired. Please run [infisical login] then try again")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
secrets, err := util.GetAllEnvironmentVariables("", "dev")
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Unable to retrieve secrets. Run with -d to see full logs")
|
||||||
|
log.Debug(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
secretByKey := getSecretsByKeys(secrets)
|
||||||
|
validSecretIdsToDelete := []string{}
|
||||||
|
invalidSecretNamesThatDoNotExist := []string{}
|
||||||
|
|
||||||
|
for _, secretKeyFromArg := range args {
|
||||||
|
if value, ok := secretByKey[secretKeyFromArg]; ok {
|
||||||
|
validSecretIdsToDelete = append(validSecretIdsToDelete, value.ID)
|
||||||
|
} else {
|
||||||
|
invalidSecretNamesThatDoNotExist = append(invalidSecretNamesThatDoNotExist, secretKeyFromArg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(invalidSecretNamesThatDoNotExist) != 0 {
|
||||||
|
log.Errorf("secret name(s) [%v] does not exist in your project. Please remove and re-run the command", strings.Join(invalidSecretNamesThatDoNotExist, ", "))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
request := models.BatchDeleteSecretsBySecretIdsRequest{
|
||||||
|
WorkspaceId: "63b0c1dbf2a30bdfddcfe1ac",
|
||||||
|
EnvironmentName: "dev",
|
||||||
|
SecretIds: validSecretIdsToDelete,
|
||||||
|
}
|
||||||
|
|
||||||
|
httpClient := resty.New().
|
||||||
|
SetAuthToken(loggedInUserDetails.UserCredentials.JTWToken).
|
||||||
|
SetHeader("Accept", "application/json")
|
||||||
|
|
||||||
|
err = http.CallBatchDeleteSecretsByWorkspaceAndEnv(httpClient, request)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Unable to complete your request because %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("secret name(s) [%v] have been deleted from your project", strings.Join(args, ", "))
|
||||||
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,11 +242,21 @@ func getSecretsByNames(cmd *cobra.Command, args []string) {
|
|||||||
} else {
|
} else {
|
||||||
requestedSecrets = append(requestedSecrets, models.SingleEnvironmentVariable{
|
requestedSecrets = append(requestedSecrets, models.SingleEnvironmentVariable{
|
||||||
Key: secretKeyFromArg,
|
Key: secretKeyFromArg,
|
||||||
Type: "NOT FOUND",
|
Type: "*not found*",
|
||||||
Value: "NOT FOUND",
|
Value: "*not found*",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
visualize.PrintAllSecretDetails(requestedSecrets)
|
visualize.PrintAllSecretDetails(requestedSecrets)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getSecretsByKeys(secrets []models.SingleEnvironmentVariable) map[string]models.SingleEnvironmentVariable {
|
||||||
|
secretMapByName := make(map[string]models.SingleEnvironmentVariable)
|
||||||
|
|
||||||
|
for _, secret := range secrets {
|
||||||
|
secretMapByName[secret.Key] = secret
|
||||||
|
}
|
||||||
|
|
||||||
|
return secretMapByName
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/Infisical/infisical-merge/packages/models"
|
||||||
|
"github.com/Infisical/infisical-merge/packages/util"
|
||||||
|
"github.com/go-resty/resty/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CallBatchModifySecretsByWorkspaceAndEnv(httpClient *resty.Client, request models.BatchModifySecretsByWorkspaceAndEnvRequest) error {
|
||||||
|
endpoint := fmt.Sprintf("%v/v2/secret/batch-modify/workspace/%v/environment/%v", util.INFISICAL_URL, request.WorkspaceId, request.EnvironmentName)
|
||||||
|
response, err := httpClient.
|
||||||
|
R().
|
||||||
|
SetBody(request).
|
||||||
|
Patch(endpoint)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("CallBatchModifySecretsByWorkspaceAndEnv: Unable to complete api request [err=%s]", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.StatusCode() > 299 {
|
||||||
|
return fmt.Errorf("CallBatchModifySecretsByWorkspaceAndEnv: Unsuccessful response: [response=%s]", response)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CallBatchCreateSecretsByWorkspaceAndEnv(httpClient *resty.Client, request models.BatchCreateSecretsByWorkspaceAndEnvRequest) error {
|
||||||
|
endpoint := fmt.Sprintf("%v/v2/secret/batch-create/workspace/%v/environment/%v", util.INFISICAL_URL, request.WorkspaceId, request.EnvironmentName)
|
||||||
|
response, err := httpClient.
|
||||||
|
R().
|
||||||
|
SetBody(request).
|
||||||
|
Post(endpoint)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("CallBatchCreateSecretsByWorkspaceAndEnv: Unable to complete api request [err=%s]", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.StatusCode() > 299 {
|
||||||
|
return fmt.Errorf("CallBatchCreateSecretsByWorkspaceAndEnv: Unsuccessful response: [response=%s]", response)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CallBatchDeleteSecretsByWorkspaceAndEnv(httpClient *resty.Client, request models.BatchDeleteSecretsBySecretIdsRequest) error {
|
||||||
|
endpoint := fmt.Sprintf("%v/v2/secret/batch/workspace/%v/environment/%v", util.INFISICAL_URL, request.WorkspaceId, request.EnvironmentName)
|
||||||
|
response, err := httpClient.
|
||||||
|
R().
|
||||||
|
SetBody(request).
|
||||||
|
Delete(endpoint)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("CallBatchDeleteSecretsByWorkspaceAndEnv: Unable to complete api request [err=%s]", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.StatusCode() > 299 {
|
||||||
|
return fmt.Errorf("CallBatchDeleteSecretsByWorkspaceAndEnv: Unsuccessful response: [response=%s]", response)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CallGetEncryptedWorkspaceKey(httpClient *resty.Client, request models.GetEncryptedWorkspaceKeyRequest) (models.GetEncryptedWorkspaceKeyResponse, error) {
|
||||||
|
endpoint := fmt.Sprintf("%v/v1/key/%v/latest", util.INFISICAL_URL, request.WorkspaceId)
|
||||||
|
var result models.GetEncryptedWorkspaceKeyResponse
|
||||||
|
response, err := httpClient.
|
||||||
|
R().
|
||||||
|
SetResult(&result).
|
||||||
|
Get(endpoint)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return models.GetEncryptedWorkspaceKeyResponse{}, fmt.Errorf("CallGetEncryptedWorkspaceKey: Unable to complete api request [err=%s]", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.StatusCode() > 299 {
|
||||||
|
return models.GetEncryptedWorkspaceKeyResponse{}, fmt.Errorf("CallGetEncryptedWorkspaceKey: Unsuccessful response: [response=%s]", response)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
@@ -128,3 +128,66 @@ type Workspace struct {
|
|||||||
V int `json:"__v"`
|
V int `json:"__v"`
|
||||||
Organization string `json:"organization,omitempty"`
|
Organization string `json:"organization,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Secret struct {
|
||||||
|
SecretKeyCiphertext string `json:"secretKeyCiphertext,omitempty"`
|
||||||
|
SecretKeyIV string `json:"secretKeyIV,omitempty"`
|
||||||
|
SecretKeyTag string `json:"secretKeyTag,omitempty"`
|
||||||
|
SecretKeyHash string `json:"secretKeyHash,omitempty"`
|
||||||
|
SecretValueCiphertext string `json:"secretValueCiphertext,omitempty"`
|
||||||
|
SecretValueIV string `json:"secretValueIV,omitempty"`
|
||||||
|
SecretValueTag string `json:"secretValueTag,omitempty"`
|
||||||
|
SecretValueHash string `json:"secretValueHash,omitempty"`
|
||||||
|
SecretCommentCiphertext string `json:"secretCommentCiphertext,omitempty"`
|
||||||
|
SecretCommentIV string `json:"secretCommentIV,omitempty"`
|
||||||
|
SecretCommentTag string `json:"secretCommentTag,omitempty"`
|
||||||
|
SecretCommentHash string `json:"secretCommentHash,omitempty"`
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
ID string `json:"_id,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BatchCreateSecretsByWorkspaceAndEnvRequest struct {
|
||||||
|
EnvironmentName string `json:"environmentName"`
|
||||||
|
WorkspaceId string `json:"workspaceId"`
|
||||||
|
Secrets []Secret `json:"secrets"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BatchModifySecretsByWorkspaceAndEnvRequest struct {
|
||||||
|
EnvironmentName string `json:"environmentName"`
|
||||||
|
WorkspaceId string `json:"workspaceId"`
|
||||||
|
Secrets []Secret `json:"secrets"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BatchDeleteSecretsBySecretIdsRequest struct {
|
||||||
|
EnvironmentName string `json:"environmentName"`
|
||||||
|
WorkspaceId string `json:"workspaceId"`
|
||||||
|
SecretIds []string `json:"secretIds"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetEncryptedWorkspaceKeyRequest struct {
|
||||||
|
WorkspaceId string `json:"workspaceId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetEncryptedWorkspaceKeyResponse struct {
|
||||||
|
LatestKey struct {
|
||||||
|
ID string `json:"_id"`
|
||||||
|
EncryptedKey string `json:"encryptedKey"`
|
||||||
|
Nonce string `json:"nonce"`
|
||||||
|
Sender struct {
|
||||||
|
ID string `json:"_id"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
RefreshVersion int `json:"refreshVersion"`
|
||||||
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
|
UpdatedAt time.Time `json:"updatedAt"`
|
||||||
|
V int `json:"__v"`
|
||||||
|
FirstName string `json:"firstName"`
|
||||||
|
LastName string `json:"lastName"`
|
||||||
|
PublicKey string `json:"publicKey"`
|
||||||
|
} `json:"sender"`
|
||||||
|
Receiver string `json:"receiver"`
|
||||||
|
Workspace string `json:"workspace"`
|
||||||
|
V int `json:"__v"`
|
||||||
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
|
UpdatedAt time.Time `json:"updatedAt"`
|
||||||
|
} `json:"latestKey"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,8 +18,15 @@ type SingleEnvironmentVariable struct {
|
|||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
Value string `json:"value"`
|
Value string `json:"value"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
|
ID string `json:"_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type WorkspaceConfigFile struct {
|
type WorkspaceConfigFile struct {
|
||||||
WorkspaceId string `json:"workspaceId"`
|
WorkspaceId string `json:"workspaceId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SymmetricEncryptionResult struct {
|
||||||
|
CipherText []byte
|
||||||
|
Nonce []byte
|
||||||
|
AuthTag []byte
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,12 @@ import (
|
|||||||
|
|
||||||
const SERVICE_NAME = "infisical"
|
const SERVICE_NAME = "infisical"
|
||||||
|
|
||||||
|
type LoggedInUserDetails struct {
|
||||||
|
IsUserLoggedIn bool
|
||||||
|
LoginExpired bool
|
||||||
|
UserCredentials models.UserCredentials
|
||||||
|
}
|
||||||
|
|
||||||
// To do: what happens if the user doesn't have a keyring in their system?
|
// To do: what happens if the user doesn't have a keyring in their system?
|
||||||
func StoreUserCredsInKeyRing(userCred *models.UserCredentials) error {
|
func StoreUserCredsInKeyRing(userCred *models.UserCredentials) error {
|
||||||
userCredMarshalled, err := json.Marshal(userCred)
|
userCredMarshalled, err := json.Marshal(userCred)
|
||||||
@@ -102,3 +108,50 @@ func IsUserLoggedIn() (hasUserLoggedIn bool, theUsersEmail string, err error) {
|
|||||||
return false, "", nil
|
return false, "", nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetCurrentLoggedInUserDetails() (LoggedInUserDetails, error) {
|
||||||
|
if ConfigFileExists() {
|
||||||
|
configFile, err := GetConfigFile()
|
||||||
|
if err != nil {
|
||||||
|
return LoggedInUserDetails{}, fmt.Errorf("getCurrentLoggedInUserDetails: unable to get logged in user from config file [err=%s]", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if configFile.LoggedInUserEmail == "" {
|
||||||
|
return LoggedInUserDetails{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
userCreds, err := GetUserCredsFromKeyRing(configFile.LoggedInUserEmail)
|
||||||
|
if err != nil {
|
||||||
|
return LoggedInUserDetails{}, fmt.Errorf("getCurrentLoggedInUserDetails: unable to your credentials from Keyring [err=%s]", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// check to to see if the JWT is still valid
|
||||||
|
httpClient := resty.New().
|
||||||
|
SetAuthToken(userCreds.JTWToken).
|
||||||
|
SetHeader("Accept", "application/json")
|
||||||
|
|
||||||
|
response, err := httpClient.
|
||||||
|
R().
|
||||||
|
Post(fmt.Sprintf("%v/v1/auth/checkAuth", INFISICAL_URL))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return LoggedInUserDetails{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.StatusCode() > 299 {
|
||||||
|
return LoggedInUserDetails{
|
||||||
|
IsUserLoggedIn: true,
|
||||||
|
LoginExpired: true,
|
||||||
|
UserCredentials: userCreds,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return LoggedInUserDetails{
|
||||||
|
IsUserLoggedIn: true,
|
||||||
|
LoginExpired: false,
|
||||||
|
UserCredentials: userCreds,
|
||||||
|
}, nil
|
||||||
|
} else {
|
||||||
|
return LoggedInUserDetails{}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/Infisical/infisical-merge/packages/models"
|
||||||
"golang.org/x/crypto/nacl/box"
|
"golang.org/x/crypto/nacl/box"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -39,15 +40,15 @@ func GenerateNewKey() (newKey []byte, keyErr error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Will encrypt a plain text with the provided key
|
// Will encrypt a plain text with the provided key
|
||||||
func EncryptSymmetric(plaintext []byte, key []byte) (cipherText []byte, iv []byte, tag []byte, err error) {
|
func EncryptSymmetric(plaintext []byte, key []byte) (result models.SymmetricEncryptionResult, err error) {
|
||||||
block, err := aes.NewCipher(key)
|
block, err := aes.NewCipher(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return models.SymmetricEncryptionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
aesgcm, err := cipher.NewGCMWithNonceSize(block, 16) // default is 12, 16 because https://github.com/Infisical/infisical/blob/bea0ff6e05a4de73a5db625d4ae181a015b50855/backend/src/utils/aes-gcm.ts#L4
|
aesgcm, err := cipher.NewGCMWithNonceSize(block, 16) // default is 12, 16 because https://github.com/Infisical/infisical/blob/bea0ff6e05a4de73a5db625d4ae181a015b50855/backend/src/utils/aes-gcm.ts#L4
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return models.SymmetricEncryptionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a nonce
|
// create a nonce
|
||||||
@@ -62,7 +63,11 @@ func EncryptSymmetric(plaintext []byte, key []byte) (cipherText []byte, iv []byt
|
|||||||
|
|
||||||
authTag := ciphertext[len(ciphertext)-16:]
|
authTag := ciphertext[len(ciphertext)-16:]
|
||||||
|
|
||||||
return ciphertextOnly, nonce, authTag, nil
|
return models.SymmetricEncryptionResult{
|
||||||
|
CipherText: ciphertextOnly,
|
||||||
|
AuthTag: authTag,
|
||||||
|
Nonce: nonce,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func DecryptAsymmetric(ciphertext []byte, nonce []byte, publicKey []byte, privateKey []byte) (plainText []byte) {
|
func DecryptAsymmetric(ciphertext []byte, nonce []byte, publicKey []byte, privateKey []byte) (plainText []byte) {
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ func getSecretsByWorkspaceIdAndEnvName(httpClient resty.Client, envName string,
|
|||||||
Key: string(plainTextKey),
|
Key: string(plainTextKey),
|
||||||
Value: string(plainTextValue),
|
Value: string(plainTextValue),
|
||||||
Type: string(secret.Type),
|
Type: string(secret.Type),
|
||||||
|
ID: secret.ID,
|
||||||
}
|
}
|
||||||
|
|
||||||
listOfEnv = append(listOfEnv, env)
|
listOfEnv = append(listOfEnv, env)
|
||||||
@@ -192,6 +193,7 @@ func GetSecretsFromAPIUsingInfisicalToken(infisicalToken string, envName string,
|
|||||||
Key: string(plainTextKey),
|
Key: string(plainTextKey),
|
||||||
Value: string(plainTextValue),
|
Value: string(plainTextValue),
|
||||||
Type: string(secret.Type),
|
Type: string(secret.Type),
|
||||||
|
ID: secret.ID,
|
||||||
}
|
}
|
||||||
|
|
||||||
listOfEnv = append(listOfEnv, env)
|
listOfEnv = append(listOfEnv, env)
|
||||||
|
|||||||
Reference in New Issue
Block a user