1
1
const process = require ( 'process' )
2
2
3
- const { SecretsManagerClient, ListSecretsCommand, GetSecretValueCommand } = require ( '@aws-sdk/client-secrets-manager' )
3
+ const {
4
+ SecretsManagerClient,
5
+ ListSecretsCommand,
6
+ GetSecretValueCommand,
7
+ DescribeSecretCommand,
8
+ } = require ( '@aws-sdk/client-secrets-manager' )
4
9
const chalk = require ( 'chalk' )
5
10
6
11
const listSecrets = async ( { client, nextToken, secrets = [ ] } ) => {
@@ -14,23 +19,39 @@ const listSecrets = async ({ client, nextToken, secrets = [] }) => {
14
19
return newSecrets
15
20
}
16
21
17
- const normalizeSecretValue = async ( { client, secret } ) => {
22
+ const getSecretContext = async ( { client, secret } ) => {
23
+ try {
24
+ const { Tags : tags = [ ] } = await client . send ( new DescribeSecretCommand ( { SecretId : secret . ARN } ) )
25
+ const context = tags . find ( ( { Key : key } ) => key === 'NETLIFY_CONTEXT' )
26
+ return context && context . Value
27
+ } catch ( error ) {
28
+ if ( error . name === 'AccessDeniedException' ) {
29
+ return console . log (
30
+ chalk . dim ( `Does not have permissions to retrieve context for secret ${ chalk . yellow ( secret . Name ) } ` ) ,
31
+ )
32
+ }
33
+ }
34
+ }
35
+
36
+ const getSecretsValue = async ( { client, secret } ) => {
18
37
try {
19
38
// SecretString is a JSON string representation of the secret, e.g. '{"SECRET_NAME":"SECRET_VALUE"}'
20
39
const { SecretString : secretString } = await client . send ( new GetSecretValueCommand ( { SecretId : secret . ARN } ) )
40
+ const context = await getSecretContext ( { client, secret } )
21
41
const parsedValue = JSON . parse ( secretString )
22
- return parsedValue
42
+ return Object . entries ( parsedValue ) . map ( ( [ key , value ] ) => ( { key , value , context } ) )
23
43
} catch ( error ) {
24
44
if ( error . name === 'AccessDeniedException' ) {
25
- return console . log ( chalk . dim ( `Skipping restricted AWS secret ${ chalk . yellow ( secret . Name ) } ` ) )
45
+ console . log ( chalk . dim ( `Skipping restricted secret ${ chalk . yellow ( secret . Name ) } ` ) )
46
+ return [ ]
26
47
}
27
48
throw error
28
49
}
29
50
}
30
51
31
- const normalizeSecrets = async ( { client, secrets } ) => {
32
- const values = await Promise . all ( secrets . map ( ( secret ) => normalizeSecretValue ( { client, secret } ) ) )
33
- return Object . assign ( { } , ... values )
52
+ const getSecretsValues = async ( { client, secrets } ) => {
53
+ const secretsWithValues = await Promise . all ( secrets . map ( ( secret ) => getSecretsValue ( { client, secret } ) ) )
54
+ return secretsWithValues . flat ( )
34
55
}
35
56
36
57
const SECRET_PREFIX = process . env . NETLIFY_AWS_SECRET_PREFIX || 'NETLIFY_AWS_SECRET_'
@@ -43,6 +64,7 @@ module.exports = {
43
64
NETLIFY_AWS_ACCESS_KEY_ID : accessKeyId ,
44
65
NETLIFY_AWS_SECRET_ACCESS_KEY : secretAccessKey ,
45
66
NETLIFY_AWS_DEFAULT_REGION : region = 'us-east-1' ,
67
+ CONTEXT ,
46
68
} = process . env
47
69
if ( ! accessKeyId ) {
48
70
return utils . build . failBuild ( `Missing environment variable NETLIFY_AWS_ACCESS_KEY_ID` )
@@ -57,14 +79,28 @@ module.exports = {
57
79
credentials : { accessKeyId, secretAccessKey } ,
58
80
} )
59
81
const secrets = await listSecrets ( { client } )
60
- const normalizedSecrets = await normalizeSecrets ( { client, secrets } )
61
-
62
- const entries = Object . entries ( normalizedSecrets )
63
- entries . forEach ( ( [ key , value ] ) => {
82
+ const secretsWithValues = await getSecretsValues ( { client, secrets } )
83
+ secretsWithValues . forEach ( ( { key, value, context } ) => {
64
84
const prefixedKey = getPrefixedKey ( key )
65
- console . log ( `${ chalk . bold ( 'Injecting AWS secret' ) } ${ chalk . magenta ( `${ key } ` ) } as ${ chalk . green ( prefixedKey ) } ` )
66
- // eslint-disable-next-line no-param-reassign
67
- netlifyConfig . build . environment [ prefixedKey ] = value
85
+
86
+ // no context, inject to all
87
+ if ( ! context ) {
88
+ console . log ( `${ chalk . bold ( 'Injecting AWS secret' ) } ${ chalk . magenta ( `${ key } ` ) } as ${ chalk . green ( prefixedKey ) } ` )
89
+ // eslint-disable-next-line no-param-reassign
90
+ netlifyConfig . build . environment [ prefixedKey ] = value
91
+ return
92
+ }
93
+
94
+ // inject only to matching context
95
+ if ( CONTEXT === context ) {
96
+ console . log (
97
+ `${ chalk . bold ( 'Injecting AWS secret' ) } ${ chalk . magenta ( `${ key } ` ) } as ${ chalk . green (
98
+ prefixedKey ,
99
+ ) } to context ${ chalk . yellow ( context ) } `,
100
+ )
101
+ /* eslint-disable-next-line no-param-reassign */
102
+ netlifyConfig . build . environment [ prefixedKey ] = value
103
+ }
68
104
} )
69
105
} ,
70
106
}
0 commit comments