mirror of
https://github.com/farcasclaudiu/Flowise.git
synced 2026-06-29 07:01:04 +03:00
Update how credential data is saved in db when using aws secrets manager (#4271)
* Update how credential data is saved in db when using aws secrets manager * Run lint-fix and update env example
This commit is contained in:
@@ -543,6 +543,15 @@ const getEncryptionKey = async (): Promise<string> => {
|
|||||||
return process.env.FLOWISE_SECRETKEY_OVERWRITE
|
return process.env.FLOWISE_SECRETKEY_OVERWRITE
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
if (USE_AWS_SECRETS_MANAGER && secretsManagerClient) {
|
||||||
|
const secretId = process.env.SECRETKEY_AWS_NAME || 'FlowiseEncryptionKey'
|
||||||
|
const command = new GetSecretValueCommand({ SecretId: secretId })
|
||||||
|
const response = await secretsManagerClient.send(command)
|
||||||
|
|
||||||
|
if (response.SecretString) {
|
||||||
|
return response.SecretString
|
||||||
|
}
|
||||||
|
}
|
||||||
return await fs.promises.readFile(getEncryptionKeyPath(), 'utf8')
|
return await fs.promises.readFile(getEncryptionKeyPath(), 'utf8')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error)
|
throw new Error(error)
|
||||||
@@ -561,18 +570,24 @@ const decryptCredentialData = async (encryptedData: string): Promise<ICommonObje
|
|||||||
|
|
||||||
if (USE_AWS_SECRETS_MANAGER && secretsManagerClient) {
|
if (USE_AWS_SECRETS_MANAGER && secretsManagerClient) {
|
||||||
try {
|
try {
|
||||||
const command = new GetSecretValueCommand({ SecretId: encryptedData })
|
if (encryptedData.startsWith('FlowiseCredential_')) {
|
||||||
const response = await secretsManagerClient.send(command)
|
const command = new GetSecretValueCommand({ SecretId: encryptedData })
|
||||||
|
const response = await secretsManagerClient.send(command)
|
||||||
|
|
||||||
if (response.SecretString) {
|
if (response.SecretString) {
|
||||||
const secretObj = JSON.parse(response.SecretString)
|
const secretObj = JSON.parse(response.SecretString)
|
||||||
decryptedDataStr = JSON.stringify(secretObj)
|
decryptedDataStr = JSON.stringify(secretObj)
|
||||||
|
} else {
|
||||||
|
throw new Error('Failed to retrieve secret value.')
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Failed to retrieve secret value.')
|
const encryptKey = await getEncryptionKey()
|
||||||
|
const decryptedData = AES.decrypt(encryptedData, encryptKey)
|
||||||
|
decryptedDataStr = decryptedData.toString(enc.Utf8)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
throw new Error('Credentials could not be decrypted.')
|
throw new Error('Failed to decrypt credential data.')
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Fallback to existing code
|
// Fallback to existing code
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ PORT=3000
|
|||||||
# SECRETKEY_AWS_ACCESS_KEY=<your-access-key>
|
# SECRETKEY_AWS_ACCESS_KEY=<your-access-key>
|
||||||
# SECRETKEY_AWS_SECRET_KEY=<your-secret-key>
|
# SECRETKEY_AWS_SECRET_KEY=<your-secret-key>
|
||||||
# SECRETKEY_AWS_REGION=us-west-2
|
# SECRETKEY_AWS_REGION=us-west-2
|
||||||
|
# SECRETKEY_AWS_NAME=FlowiseEncryptionKey
|
||||||
|
|
||||||
# NUMBER_OF_PROXIES= 1
|
# NUMBER_OF_PROXIES= 1
|
||||||
# CORS_ORIGINS=*
|
# CORS_ORIGINS=*
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ import { StatusCodes } from 'http-status-codes'
|
|||||||
import {
|
import {
|
||||||
CreateSecretCommand,
|
CreateSecretCommand,
|
||||||
GetSecretValueCommand,
|
GetSecretValueCommand,
|
||||||
PutSecretValueCommand,
|
|
||||||
SecretsManagerClient,
|
SecretsManagerClient,
|
||||||
SecretsManagerClientConfig
|
SecretsManagerClientConfig
|
||||||
} from '@aws-sdk/client-secrets-manager'
|
} from '@aws-sdk/client-secrets-manager'
|
||||||
@@ -1394,6 +1393,29 @@ export const getEncryptionKey = async (): Promise<string> => {
|
|||||||
if (process.env.FLOWISE_SECRETKEY_OVERWRITE !== undefined && process.env.FLOWISE_SECRETKEY_OVERWRITE !== '') {
|
if (process.env.FLOWISE_SECRETKEY_OVERWRITE !== undefined && process.env.FLOWISE_SECRETKEY_OVERWRITE !== '') {
|
||||||
return process.env.FLOWISE_SECRETKEY_OVERWRITE
|
return process.env.FLOWISE_SECRETKEY_OVERWRITE
|
||||||
}
|
}
|
||||||
|
if (USE_AWS_SECRETS_MANAGER && secretsManagerClient) {
|
||||||
|
const secretId = process.env.SECRETKEY_AWS_NAME || 'FlowiseEncryptionKey'
|
||||||
|
try {
|
||||||
|
const command = new GetSecretValueCommand({ SecretId: secretId })
|
||||||
|
const response = await secretsManagerClient.send(command)
|
||||||
|
|
||||||
|
if (response.SecretString) {
|
||||||
|
return response.SecretString
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
if (error.name === 'ResourceNotFoundException') {
|
||||||
|
// Secret doesn't exist, create it
|
||||||
|
const newKey = generateEncryptKey()
|
||||||
|
const createCommand = new CreateSecretCommand({
|
||||||
|
Name: secretId,
|
||||||
|
SecretString: newKey
|
||||||
|
})
|
||||||
|
await secretsManagerClient.send(createCommand)
|
||||||
|
return newKey
|
||||||
|
}
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
return await fs.promises.readFile(getEncryptionKeyPath(), 'utf8')
|
return await fs.promises.readFile(getEncryptionKeyPath(), 'utf8')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -1412,39 +1434,7 @@ export const getEncryptionKey = async (): Promise<string> => {
|
|||||||
* @returns {Promise<string>}
|
* @returns {Promise<string>}
|
||||||
*/
|
*/
|
||||||
export const encryptCredentialData = async (plainDataObj: ICredentialDataDecrypted): Promise<string> => {
|
export const encryptCredentialData = async (plainDataObj: ICredentialDataDecrypted): Promise<string> => {
|
||||||
if (USE_AWS_SECRETS_MANAGER && secretsManagerClient) {
|
|
||||||
const secretName = `FlowiseCredential_${randomBytes(12).toString('hex')}`
|
|
||||||
|
|
||||||
logger.info(`[server]: Upserting AWS Secret: ${secretName}`)
|
|
||||||
|
|
||||||
const secretString = JSON.stringify({ ...plainDataObj })
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Try to update the secret if it exists
|
|
||||||
const putCommand = new PutSecretValueCommand({
|
|
||||||
SecretId: secretName,
|
|
||||||
SecretString: secretString
|
|
||||||
})
|
|
||||||
await secretsManagerClient.send(putCommand)
|
|
||||||
} catch (error: any) {
|
|
||||||
if (error.name === 'ResourceNotFoundException') {
|
|
||||||
// Secret doesn't exist, so create it
|
|
||||||
const createCommand = new CreateSecretCommand({
|
|
||||||
Name: secretName,
|
|
||||||
SecretString: secretString
|
|
||||||
})
|
|
||||||
await secretsManagerClient.send(createCommand)
|
|
||||||
} else {
|
|
||||||
// Rethrow any other errors
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return secretName
|
|
||||||
}
|
|
||||||
|
|
||||||
const encryptKey = await getEncryptionKey()
|
const encryptKey = await getEncryptionKey()
|
||||||
|
|
||||||
// Fallback to existing code
|
|
||||||
return AES.encrypt(JSON.stringify(plainDataObj), encryptKey).toString()
|
return AES.encrypt(JSON.stringify(plainDataObj), encryptKey).toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1465,14 +1455,20 @@ export const decryptCredentialData = async (
|
|||||||
if (USE_AWS_SECRETS_MANAGER && secretsManagerClient) {
|
if (USE_AWS_SECRETS_MANAGER && secretsManagerClient) {
|
||||||
try {
|
try {
|
||||||
logger.info(`[server]: Reading AWS Secret: ${encryptedData}`)
|
logger.info(`[server]: Reading AWS Secret: ${encryptedData}`)
|
||||||
const command = new GetSecretValueCommand({ SecretId: encryptedData })
|
if (encryptedData.startsWith('FlowiseCredential_')) {
|
||||||
const response = await secretsManagerClient.send(command)
|
const command = new GetSecretValueCommand({ SecretId: encryptedData })
|
||||||
|
const response = await secretsManagerClient.send(command)
|
||||||
|
|
||||||
if (response.SecretString) {
|
if (response.SecretString) {
|
||||||
const secretObj = JSON.parse(response.SecretString)
|
const secretObj = JSON.parse(response.SecretString)
|
||||||
decryptedDataStr = JSON.stringify(secretObj)
|
decryptedDataStr = JSON.stringify(secretObj)
|
||||||
|
} else {
|
||||||
|
throw new Error('Failed to retrieve secret value.')
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Failed to retrieve secret value.')
|
const encryptKey = await getEncryptionKey()
|
||||||
|
const decryptedData = AES.decrypt(encryptedData, encryptKey)
|
||||||
|
decryptedDataStr = decryptedData.toString(enc.Utf8)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
|
|||||||
Reference in New Issue
Block a user