diff --git a/charts/kubernetes-external-secrets/README.md b/charts/kubernetes-external-secrets/README.md index c790c45e..372b0c8c 100644 --- a/charts/kubernetes-external-secrets/README.md +++ b/charts/kubernetes-external-secrets/README.md @@ -74,7 +74,10 @@ The following table lists the configurable parameters of the `kubernetes-externa | `crds.create` | For Helm V2 installations of the chart to install the CRD, for V3 installations use `--skip-crds` appropriately | `false` | | `customResourceManagerDisabled` | Disables the custom resource manager, requiring the CRD be installed via the chart or other means | `false` | | `env.AWS_REGION` | Set AWS_REGION in Deployment Pod | `us-west-2` | +| `env.AWS_INTERMEDIATE_ROLE_ARN` | Specifies a role to be assumed before assuming role arn specified in external secrets | | | `env.LOG_LEVEL` | Set the application log level | `info` | +| `env.LOG_MESSAGE_KEY` | Set the key for log messages log text, for example when running on GCP it might be nice to set to `message` | `msg` | +| `env.USE_HUMAN_READABLE_LOG_LEVELS` | Sets log levels as string instead of ints eg `info` instead of `30`, setting this to any value will switch | `nil` | | `env.METRICS_PORT` | Specify the port for the prometheus metrics server | `3001` | | `env.ROLE_PERMITTED_ANNOTATION` | Specify the annotation key where to lookup the role arn permission boundaries | `iam.amazonaws.com/permitted` | | `env.POLLER_INTERVAL_MILLISECONDS` | Set POLLER_INTERVAL_MILLISECONDS in Deployment Pod | `10000` | diff --git a/charts/kubernetes-external-secrets/values.yaml b/charts/kubernetes-external-secrets/values.yaml index aa30728f..8f8e981e 100644 --- a/charts/kubernetes-external-secrets/values.yaml +++ b/charts/kubernetes-external-secrets/values.yaml @@ -21,7 +21,9 @@ env: # USE_HUMAN_READABLE_LOG_LEVELS: true METRICS_PORT: 3001 VAULT_ADDR: http://127.0.0.1:8200 -# GOOGLE_APPLICATION_CREDENTIALS: /app/gcp-creds/gcp-creds.json + # Set a role to be used when assuming roles specified in external secret (AWS only) + # AWS_INTERMEDIATE_ROLE_ARN: + # GOOGLE_APPLICATION_CREDENTIALS: /app/gcp-creds/gcp-creds.json # Create environment variables from existing k8s secrets # envVarsFromSecret: diff --git a/config/aws-config.js b/config/aws-config.js index df2a1b6b..a3a75a30 100644 --- a/config/aws-config.js +++ b/config/aws-config.js @@ -7,6 +7,8 @@ const merge = require('lodash.merge') const localstack = process.env.LOCALSTACK || 0 +const intermediateRole = process.env.AWS_INTERMEDIATE_ROLE_ARN || 0 + let secretsManagerConfig = {} let systemManagerConfig = {} let stsConfig = { @@ -29,6 +31,13 @@ if (localstack) { } } +const intermediateCredentials = intermediateRole ? new AWS.ChainableTemporaryCredentials({ + params: { + RoleArn: intermediateRole + }, + stsConfig +}) : null + module.exports = { secretsManagerFactory: (opts = {}) => { if (localstack) { @@ -43,15 +52,10 @@ module.exports = { return new AWS.SSM(opts) }, assumeRole: (assumeRoleOpts) => { - const sts = new AWS.STS(stsConfig) - - return new Promise((resolve, reject) => { - sts.assumeRole(assumeRoleOpts, (err, res) => { - if (err) { - return reject(err) - } - resolve(res) - }) + return new AWS.ChainableTemporaryCredentials({ + params: assumeRoleOpts, + masterCredentials: intermediateCredentials, + stsConfig }) } } diff --git a/lib/backends/secrets-manager-backend.js b/lib/backends/secrets-manager-backend.js index f7df15af..61f75a3d 100644 --- a/lib/backends/secrets-manager-backend.js +++ b/lib/backends/secrets-manager-backend.js @@ -31,14 +31,12 @@ class SecretsManagerBackend extends KVBackend { let client = this._client if (roleArn) { - const res = await this._assumeRole({ + const credentials = this._assumeRole({ RoleArn: roleArn, RoleSessionName: 'k8s-external-secrets' }) client = this._clientFactory({ - accessKeyId: res.Credentials.AccessKeyId, - secretAccessKey: res.Credentials.SecretAccessKey, - sessionToken: res.Credentials.SessionToken + credentials }) } diff --git a/lib/backends/secrets-manager-backend.test.js b/lib/backends/secrets-manager-backend.test.js index feae9f52..2bd02790 100644 --- a/lib/backends/secrets-manager-backend.test.js +++ b/lib/backends/secrets-manager-backend.test.js @@ -16,11 +16,7 @@ describe('SecretsManagerBackend', () => { const keyOptions = {} const assumeRoleCredentials = { - Credentials: { - AccessKeyId: '1234', - SecretAccessKey: '3123123', - SessionToken: 'asdasdasdad' - } + fakeObject: 'Fake mock object' } beforeEach(() => { @@ -28,7 +24,7 @@ describe('SecretsManagerBackend', () => { loggerMock = sinon.mock() loggerMock.info = sinon.stub() clientFactoryMock = sinon.fake.returns(clientMock) - assumeRoleMock = sinon.fake.returns(Promise.resolve(assumeRoleCredentials)) + assumeRoleMock = sinon.fake.returns(assumeRoleCredentials) secretsManagerBackend = new SecretsManagerBackend({ clientFactory: clientFactoryMock, assumeRole: assumeRoleMock, @@ -97,9 +93,7 @@ describe('SecretsManagerBackend', () => { }) expect(clientFactoryMock.lastArg).deep.equals({ - accessKeyId: assumeRoleCredentials.Credentials.AccessKeyId, - secretAccessKey: assumeRoleCredentials.Credentials.SecretAccessKey, - sessionToken: assumeRoleCredentials.Credentials.SessionToken + credentials: assumeRoleCredentials }) expect(clientMock.getSecretValue.calledWith({ SecretId: 'fakeSecretKey', @@ -107,9 +101,7 @@ describe('SecretsManagerBackend', () => { })).to.equal(true) expect(clientFactoryMock.getCall(0).args).deep.equals([]) expect(clientFactoryMock.getCall(1).args).deep.equals([{ - accessKeyId: assumeRoleCredentials.Credentials.AccessKeyId, - secretAccessKey: assumeRoleCredentials.Credentials.SecretAccessKey, - sessionToken: assumeRoleCredentials.Credentials.SessionToken + credentials: assumeRoleCredentials }]) expect(assumeRoleMock.callCount).equals(1) expect(secretPropertyValue).equals('fakeAssumeRoleSecretValue') diff --git a/lib/backends/system-manager-backend.js b/lib/backends/system-manager-backend.js index 79300b49..778cb58a 100644 --- a/lib/backends/system-manager-backend.js +++ b/lib/backends/system-manager-backend.js @@ -29,14 +29,12 @@ class SystemManagerBackend extends KVBackend { let client = this._client if (roleArn) { - const res = await this._assumeRole({ + const credentials = this._assumeRole({ RoleArn: roleArn, RoleSessionName: 'k8s-external-secrets' }) client = this._clientFactory({ - accessKeyId: res.Credentials.AccessKeyId, - secretAccessKey: res.Credentials.SecretAccessKey, - sessionToken: res.Credentials.SessionToken + credentials }) } try { diff --git a/lib/backends/system-manager-backend.test.js b/lib/backends/system-manager-backend.test.js index 15f9da35..aa86b84f 100644 --- a/lib/backends/system-manager-backend.test.js +++ b/lib/backends/system-manager-backend.test.js @@ -15,11 +15,7 @@ describe('SystemManagerBackend', () => { const specOptions = {} const assumeRoleCredentials = { - Credentials: { - AccessKeyId: '1234', - SecretAccessKey: '3123123', - SessionToken: 'asdasdasdad' - } + fakeObject: 'Fake mock object' } beforeEach(() => { @@ -27,7 +23,7 @@ describe('SystemManagerBackend', () => { loggerMock = sinon.mock() loggerMock.info = sinon.stub() clientFactoryMock = sinon.fake.returns(clientMock) - assumeRoleMock = sinon.fake.returns(Promise.resolve(assumeRoleCredentials)) + assumeRoleMock = sinon.fake.returns(assumeRoleCredentials) systemManagerBackend = new SystemManagerBackend({ client: clientMock, @@ -79,9 +75,7 @@ describe('SystemManagerBackend', () => { specOptions: { roleArn: 'my-role' } }) expect(clientFactoryMock.lastArg).deep.equals({ - accessKeyId: assumeRoleCredentials.Credentials.AccessKeyId, - secretAccessKey: assumeRoleCredentials.Credentials.SecretAccessKey, - sessionToken: assumeRoleCredentials.Credentials.SessionToken + credentials: assumeRoleCredentials }) expect(clientMock.getParameter.calledWith({ Name: 'fakeSecretKey', @@ -89,9 +83,7 @@ describe('SystemManagerBackend', () => { })).to.equal(true) expect(clientFactoryMock.getCall(0).args).deep.equals([]) expect(clientFactoryMock.getCall(1).args).deep.equals([{ - accessKeyId: assumeRoleCredentials.Credentials.AccessKeyId, - secretAccessKey: assumeRoleCredentials.Credentials.SecretAccessKey, - sessionToken: assumeRoleCredentials.Credentials.SessionToken + credentials: assumeRoleCredentials }]) expect(secretPropertyValue).equals('fakeAssumeRoleSecretValue') })