Skip to content
This repository was archived by the owner on Jul 26, 2022. It is now read-only.

Commit 8c17819

Browse files
moolenFlydiverny
authored andcommitted
feat: make role-scope annotation configurable & fix: allow missing roleArn even if annotations are set (#179)
* fix: missing roleArn should be allowed #174 * feat: make role-scope annotation configurable #174
1 parent 1bdfde2 commit 8c17819

File tree

7 files changed

+33
-12
lines changed

7 files changed

+33
-12
lines changed

README.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ The following table lists the configurable parameters of the `kubernetes-externa
5555
| `env.AWS_REGION` | Set AWS_REGION in Deployment Pod | `us-west-2` |
5656
| `env.LOG_LEVEL` | Set the application log level | `info` |
5757
| `env.METRICS_PORT` | Specify the port for the prometheus metrics server | `3001` |
58+
| `env.ROLE_PERMITTED_ANNOTATION` | Specify the annotation key where to lookup the role arn permission boundaries | `iam.amazonaws.com/permitted` |
5859
| `env.POLLER_INTERVAL_MILLISECONDS` | Set POLLER_INTERVAL_MILLISECONDS in Deployment Pod | `10000` |
5960
| `envVarsFromSecret.AWS_ACCESS_KEY_ID` | Set AWS_ACCESS_KEY_ID (from a secret) in Deployment Pod | |
6061
| `envVarsFromSecret.AWS_SECRET_ACCESS_KEY` | Set AWS_SECRET_ACCESS_KEY (from a secret) in Deployment Pod | |
@@ -87,14 +88,14 @@ Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY env vars in the session/pod.
8788
You can use envVarsFromSecret in the helm chart to create these env vars from existing k8s secrets
8889

8990
Additionally, you can specify a `roleArn` which will be assumed before retrieving the secret.
90-
You can limit the range of roles which can be assumed by this particular *namespace* by using annotations on the namespace resource.
91-
The annotation value is evaluated as a regular expression and tries to match the `roleArn`.
91+
You can limit the range of roles which can be assumed by this particular *namespace* by using annotations on the namespace resource. The annotation key is configurable (see above). The annotation value is evaluated as a regular expression and tries to match the `roleArn`.
9292

9393
```yaml
9494
kind: Namespace
9595
metadata:
9696
name: iam-example
9797
annotations:
98+
# annotation key is configurable
9899
iam.amazonaws.com/permitted: "arn:aws:iam::123456789012:role/.*"
99100
```
100101

bin/daemon.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ const {
2121
customResourceManifest,
2222
logger,
2323
metricsPort,
24-
pollerIntervalMilliseconds
24+
pollerIntervalMilliseconds,
25+
rolePermittedAnnotation
2526
} = require('../config')
2627

2728
async function main () {
@@ -46,6 +47,7 @@ async function main () {
4647
kubeClient,
4748
metrics,
4849
pollerIntervalMilliseconds,
50+
rolePermittedAnnotation,
4951
customResourceManifest,
5052
logger
5153
})

charts/kubernetes-external-secrets/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ The following table lists the configurable parameters of the `kubernetes-externa
3939
| `env.AWS_REGION` | Set AWS_REGION in Deployment Pod | `us-west-2` |
4040
| `env.LOG_LEVEL` | Set the application log level | `info` |
4141
| `env.METRICS_PORT` | Specify the port for the prometheus metrics server | `3001` |
42+
| `env.ROLE_PERMITTED_ANNOTATION` | Specify the annotation key where to lookup the role arn permission boundaries | `iam.amazonaws.com/permitted` |
4243
| `env.POLLER_INTERVAL_MILLISECONDS` | Set POLLER_INTERVAL_MILLISECONDS in Deployment Pod | `10000` |
4344
| `envVarsFromSecret.AWS_ACCESS_KEY_ID` | Set AWS_ACCESS_KEY_ID (from a secret) in Deployment Pod | |
4445
| `envVarsFromSecret.AWS_SECRET_ACCESS_KEY` | Set AWS_SECRET_ACCESS_KEY (from a secret) in Deployment Pod | |

config/environment.js

+3
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,14 @@ const pollerIntervalMilliseconds = process.env.POLLER_INTERVAL_MILLISECONDS
2121

2222
const logLevel = process.env.LOG_LEVEL || 'info'
2323

24+
const rolePermittedAnnotation = process.env.ROLE_PERMITTED_ANNOTATION || 'iam.amazonaws.com/permitted'
25+
2426
const metricsPort = process.env.METRICS_PORT || 3001
2527

2628
module.exports = {
2729
environment,
2830
pollerIntervalMilliseconds,
2931
metricsPort,
32+
rolePermittedAnnotation,
3033
logLevel
3134
}

lib/poller-factory.js

+4
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@ class PollerFactory {
1111
* @param {Object} customResourceManifest - CRD manifest
1212
* @param {Object} logger - Logger for logging stuff.
1313
* @param {number} pollerIntervalMilliseconds - Interval time in milliseconds for polling secret properties.
14+
* @param {String} rolePermittedAnnotation - namespace annotation that defines which roles can be assumed within this namespace
1415
*/
1516
constructor ({
1617
backends,
1718
kubeClient,
1819
metrics,
1920
pollerIntervalMilliseconds,
21+
rolePermittedAnnotation,
2022
customResourceManifest,
2123
logger
2224
}) {
@@ -26,6 +28,7 @@ class PollerFactory {
2628
this._kubeClient = kubeClient
2729
this._pollerIntervalMilliseconds = pollerIntervalMilliseconds
2830
this._customResourceManifest = customResourceManifest
31+
this._rolePermittedAnnotation = rolePermittedAnnotation
2932
}
3033

3134
/**
@@ -40,6 +43,7 @@ class PollerFactory {
4043
logger: this._logger,
4144
metrics: this._metrics,
4245
customResourceManifest: this._customResourceManifest,
46+
rolePermittedAnnotation: this._rolePermittedAnnotation,
4347
externalSecret
4448
})
4549

lib/poller.js

+5-4
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
* object, this is the property name of the value to use.
1313
*/
1414

15-
const annotationPermittedKey = 'iam.amazonaws.com/permitted'
16-
1715
/** Poller class. */
1816
class Poller {
1917
/**
@@ -25,6 +23,7 @@ class Poller {
2523
* @param {string} namespace - Kubernetes namespace.
2624
* @param {Object} customResourceManifest - CRD manifest
2725
* @param {Object} externalSecret - ExternalSecret manifest.
26+
* @param {string} rolePermittedAnnotation - namespace annotation that defines which roles can be assumed within this namespace
2827
* @param {Object} metrics - Metrics client.
2928
*/
3029
constructor ({
@@ -34,6 +33,7 @@ class Poller {
3433
logger,
3534
metrics,
3635
customResourceManifest,
36+
rolePermittedAnnotation,
3737
externalSecret
3838
}) {
3939
this._backends = backends
@@ -42,6 +42,7 @@ class Poller {
4242
this._logger = logger
4343
this._timeoutId = null
4444
this._metrics = metrics
45+
this._rolePermittedAnnotation = rolePermittedAnnotation
4546
this._customResourceManifest = customResourceManifest
4647

4748
this._externalSecret = externalSecret
@@ -169,13 +170,13 @@ class Poller {
169170
let allowed = true
170171
let reason = ''
171172

172-
if (!namespace.metadata.annotations) {
173+
if (!namespace.metadata.annotations || !role) {
173174
return {
174175
allowed, reason
175176
}
176177
}
177178
// an empty annotation value allows access to all roles
178-
const re = new RegExp(namespace.metadata.annotations[annotationPermittedKey])
179+
const re = new RegExp(namespace.metadata.annotations[this._rolePermittedAnnotation])
179180

180181
if (!re.test(role)) {
181182
allowed = false

lib/poller.test.js

+14-5
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ describe('Poller', () => {
2525
uid: fakeExternalSecret.metadata.uid
2626
})
2727

28+
const rolePermittedAnnotation = 'iam.amazonaws.com/permitted'
29+
2830
beforeEach(() => {
2931
backendMock = sinon.mock()
3032
kubeClientMock = sinon.mock()
@@ -90,6 +92,7 @@ describe('Poller', () => {
9092
kubeClient: kubeClientMock,
9193
logger: loggerMock,
9294
externalSecret: fakeExternalSecret,
95+
rolePermittedAnnotation,
9396
customResourceManifest: fakeCustomResourceManifest
9497
})
9598
}
@@ -440,7 +443,7 @@ describe('Poller', () => {
440443
})
441444

442445
it('does not permit update of secret', async () => {
443-
fakeNamespace.body.metadata.annotations['iam.amazonaws.com/permitted'] = '^$'
446+
fakeNamespace.body.metadata.annotations[rolePermittedAnnotation] = '^$'
444447
poller = pollerFactory({
445448
backendType: 'fakeBackendType',
446449
name: 'fakeSecretName',
@@ -536,27 +539,33 @@ describe('Poller', () => {
536539
},
537540
{
538541
// empty annotation
539-
ns: { metadata: { annotations: { 'iam.amazonaws.com/permitted': '' } } },
542+
ns: { metadata: { annotations: { [rolePermittedAnnotation]: '' } } },
540543
descriptor: {},
541544
permitted: true
542545
},
543546
{
544547
// test regex
545-
ns: { metadata: { annotations: { 'iam.amazonaws.com/permitted': '.*' } } },
548+
ns: { metadata: { annotations: { [rolePermittedAnnotation]: '.*' } } },
546549
descriptor: { roleArn: 'whatever' },
547550
permitted: true
548551
},
549552
{
550553
// test regex: deny access
551-
ns: { metadata: { annotations: { 'iam.amazonaws.com/permitted': '^$' } } },
554+
ns: { metadata: { annotations: { [rolePermittedAnnotation]: '^$' } } },
552555
descriptor: { roleArn: 'whatever' },
553556
permitted: false
554557
},
555558
{
556559
// real world example
557-
ns: { metadata: { annotations: { 'iam.amazonaws.com/permitted': 'arn:aws:iam::123456789012:role/.*' } } },
560+
ns: { metadata: { annotations: { [rolePermittedAnnotation]: 'arn:aws:iam::123456789012:role/.*' } } },
558561
descriptor: { roleArn: 'arn:aws:iam::123456789012:role/somerole' },
559562
permitted: true
563+
},
564+
{
565+
// test undefined
566+
ns: { metadata: { annotations: { [rolePermittedAnnotation]: 'my-kiam-role.*' } } },
567+
descriptor: {},
568+
permitted: true
560569
}
561570
]
562571

0 commit comments

Comments
 (0)