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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 14 additions & 27 deletions packages/cmd/tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ Copyright (c) 2023 Infisical Inc.
package cmd

import (
"crypto/rand"
"encoding/base64"
"encoding/hex"
"fmt"
"strings"
Expand Down Expand Up @@ -115,24 +113,11 @@ var tokensCreateCmd = &cobra.Command{
}
}

workspaceKey, err := util.GetPlainTextWorkspaceKey(loggedInUserDetails.UserCredentials.JTWToken, loggedInUserDetails.UserCredentials.PrivateKey, workspaceId)
if err != nil {
util.HandleError(err, "Unable to get workspace key needed to create service token")
}

newWorkspaceEncryptionKey := make([]byte, 16)
_, err = rand.Read(newWorkspaceEncryptionKey)
if err != nil {
util.HandleError(err)
}

newWorkspaceEncryptionKeyHexFormat := hex.EncodeToString(newWorkspaceEncryptionKey)

// encrypt the workspace key symmetrically
encryptedDetails, err := crypto.EncryptSymmetric(workspaceKey, []byte(newWorkspaceEncryptionKeyHexFormat))
randomBytes, err := crypto.GenerateRandomBytes(16)
if err != nil {
util.HandleError(err)
}
hexEncodedRandomBytes := hex.EncodeToString(randomBytes)

// make a call to the api to save the encrypted symmetric key details
httpClient, err := util.GetRestyClientWithCustomHeaders()
Expand All @@ -144,22 +129,24 @@ var tokensCreateCmd = &cobra.Command{
SetHeader("Accept", "application/json")

createServiceTokenResponse, err := api.CallCreateServiceToken(httpClient, api.CreateServiceTokenRequest{
Name: serviceTokenName,
WorkspaceId: workspaceId,
Scopes: permissions,
ExpiresIn: expireSeconds,
EncryptedKey: base64.StdEncoding.EncodeToString(encryptedDetails.CipherText),
Iv: base64.StdEncoding.EncodeToString(encryptedDetails.Nonce),
Tag: base64.StdEncoding.EncodeToString(encryptedDetails.AuthTag),
RandomBytes: newWorkspaceEncryptionKeyHexFormat,
Permissions: accessLevels,
Name: serviceTokenName,
WorkspaceId: workspaceId,
Scopes: permissions,
ExpiresIn: expireSeconds,
Permissions: accessLevels,
RandomBytes: hexEncodedRandomBytes,

// No longer required for creating service tokens:
EncryptedKey: "",
Iv: "",
Tag: "",
})

if err != nil {
util.HandleError(err, "Unable to create service token")
}

serviceToken := createServiceTokenResponse.ServiceToken + "." + newWorkspaceEncryptionKeyHexFormat
serviceToken := createServiceTokenResponse.ServiceToken + "." + hexEncodedRandomBytes

if tokenOnly {
fmt.Println(serviceToken)
Expand Down
9 changes: 9 additions & 0 deletions packages/crypto/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ import (
"golang.org/x/crypto/nacl/box"
)

func GenerateRandomBytes(length int) ([]byte, error) {
bytes := make([]byte, length)
_, err := rand.Read(bytes)
if err != nil {
return nil, err
}
return bytes, nil
}

// will decrypt cipher text to plain text using iv and tag
func DecryptSymmetric(key []byte, cipherText []byte, tag []byte, iv []byte) ([]byte, error) {
// Case: empty string
Expand Down
46 changes: 0 additions & 46 deletions packages/util/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package util

import (
"crypto/rand"
"encoding/base64"
"encoding/hex"
"encoding/json"
"errors"
Expand Down Expand Up @@ -543,51 +542,6 @@ func GetEnvelopmentBasedOnGitBranch(workspaceFile models.WorkspaceConfigFile) st
}
}

func GetPlainTextWorkspaceKey(authenticationToken string, receiverPrivateKey string, workspaceId string) ([]byte, error) {
httpClient, err := GetRestyClientWithCustomHeaders()
if err != nil {
return nil, fmt.Errorf("GetPlainTextWorkspaceKey: unable to get client with custom headers [err=%v]", err)
}

httpClient.SetAuthToken(authenticationToken).
SetHeader("Accept", "application/json")

request := api.GetEncryptedWorkspaceKeyRequest{
WorkspaceId: workspaceId,
}

workspaceKeyResponse, err := api.CallGetEncryptedWorkspaceKey(httpClient, request)
if err != nil {
return nil, fmt.Errorf("GetPlainTextWorkspaceKey: unable to retrieve your encrypted workspace key. [err=%v]", err)
}

encryptedWorkspaceKey, err := base64.StdEncoding.DecodeString(workspaceKeyResponse.EncryptedKey)
if err != nil {
return nil, fmt.Errorf("GetPlainTextWorkspaceKey: Unable to get bytes represented by the base64 for encryptedWorkspaceKey [err=%v]", err)
}

encryptedWorkspaceKeySenderPublicKey, err := base64.StdEncoding.DecodeString(workspaceKeyResponse.Sender.PublicKey)
if err != nil {
return nil, fmt.Errorf("GetPlainTextWorkspaceKey: Unable to get bytes represented by the base64 for encryptedWorkspaceKeySenderPublicKey [err=%v]", err)
}

encryptedWorkspaceKeyNonce, err := base64.StdEncoding.DecodeString(workspaceKeyResponse.Nonce)
if err != nil {
return nil, fmt.Errorf("GetPlainTextWorkspaceKey: Unable to get bytes represented by the base64 for encryptedWorkspaceKeyNonce [err=%v]", err)
}

currentUsersPrivateKey, err := base64.StdEncoding.DecodeString(receiverPrivateKey)
if err != nil {
return nil, fmt.Errorf("GetPlainTextWorkspaceKey: Unable to get bytes represented by the base64 for currentUsersPrivateKey [err=%v]", err)
}

if len(currentUsersPrivateKey) == 0 || len(encryptedWorkspaceKeySenderPublicKey) == 0 {
return nil, fmt.Errorf("GetPlainTextWorkspaceKey: Missing credentials for generating plainTextEncryptionKey")
}

return crypto.DecryptAsymmetric(encryptedWorkspaceKey, encryptedWorkspaceKeyNonce, encryptedWorkspaceKeySenderPublicKey, currentUsersPrivateKey), nil
}

func parseSecrets(fileName string, content string) (map[string]string, error) {
secrets := make(map[string]string)

Expand Down
Loading