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

Commit

Permalink
feat: make role-scope annotation configurable #174
Browse files Browse the repository at this point in the history
  • Loading branch information
moolen committed Nov 5, 2019
1 parent 7ed6720 commit 1c35682
Show file tree
Hide file tree
Showing 7 changed files with 27 additions and 12 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ The following table lists the configurable parameters of the `kubernetes-externa
| `env.AWS_REGION` | Set AWS_REGION in Deployment Pod | `us-west-2` |
| `env.LOG_LEVEL` | Set the application log level | `info` |
| `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` |
| `envVarsFromSecret.AWS_ACCESS_KEY_ID` | Set AWS_ACCESS_KEY_ID (from a secret) in Deployment Pod | |
| `envVarsFromSecret.AWS_SECRET_ACCESS_KEY` | Set AWS_SECRET_ACCESS_KEY (from a secret) in Deployment Pod | |
Expand Down Expand Up @@ -87,14 +88,14 @@ Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY env vars in the session/pod.
You can use envVarsFromSecret in the helm chart to create these env vars from existing k8s secrets

Additionally, you can specify a `roleArn` which will be assumed before retrieving the secret.
You can limit the range of roles which can be assumed by this particular *namespace* by using annotations on the namespace resource.
The annotation value is evaluated as a regular expression and tries to match the `roleArn`.
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`.

```yaml
kind: Namespace
metadata:
name: iam-example
annotations:
# annotation key is configurable
iam.amazonaws.com/permitted: "arn:aws:iam::123456789012:role/.*"
```
Expand Down
4 changes: 3 additions & 1 deletion bin/daemon.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ const {
customResourceManifest,
logger,
metricsPort,
pollerIntervalMilliseconds
pollerIntervalMilliseconds,
rolePermittedAnnotation
} = require('../config')

async function main () {
Expand All @@ -46,6 +47,7 @@ async function main () {
kubeClient,
metrics,
pollerIntervalMilliseconds,
rolePermittedAnnotation,
customResourceManifest,
logger
})
Expand Down
1 change: 1 addition & 0 deletions charts/kubernetes-external-secrets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ The following table lists the configurable parameters of the `kubernetes-externa
| `env.AWS_REGION` | Set AWS_REGION in Deployment Pod | `us-west-2` |
| `env.LOG_LEVEL` | Set the application log level | `info` |
| `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` |
| `envVarsFromSecret.AWS_ACCESS_KEY_ID` | Set AWS_ACCESS_KEY_ID (from a secret) in Deployment Pod | |
| `envVarsFromSecret.AWS_SECRET_ACCESS_KEY` | Set AWS_SECRET_ACCESS_KEY (from a secret) in Deployment Pod | |
Expand Down
3 changes: 3 additions & 0 deletions config/environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@ const pollerIntervalMilliseconds = process.env.POLLER_INTERVAL_MILLISECONDS

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

const rolePermittedAnnotation = process.env.ROLE_PERMITTED_ANNOTATION || 'iam.amazonaws.com/permitted'

const metricsPort = process.env.METRICS_PORT || 3001

module.exports = {
environment,
pollerIntervalMilliseconds,
metricsPort,
rolePermittedAnnotation,
logLevel
}
4 changes: 4 additions & 0 deletions lib/poller-factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ class PollerFactory {
* @param {Object} customResourceManifest - CRD manifest
* @param {Object} logger - Logger for logging stuff.
* @param {number} pollerIntervalMilliseconds - Interval time in milliseconds for polling secret properties.
* @param {String} rolePermittedAnnotation - namespace annotation that defines which roles can be assumed within this namespace
*/
constructor ({
backends,
kubeClient,
metrics,
pollerIntervalMilliseconds,
rolePermittedAnnotation,
customResourceManifest,
logger
}) {
Expand All @@ -26,6 +28,7 @@ class PollerFactory {
this._kubeClient = kubeClient
this._pollerIntervalMilliseconds = pollerIntervalMilliseconds
this._customResourceManifest = customResourceManifest
this._rolePermittedAnnotation = rolePermittedAnnotation
}

/**
Expand All @@ -40,6 +43,7 @@ class PollerFactory {
logger: this._logger,
metrics: this._metrics,
customResourceManifest: this._customResourceManifest,
rolePermittedAnnotation: this._rolePermittedAnnotation,
externalSecret
})

Expand Down
7 changes: 4 additions & 3 deletions lib/poller.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
* object, this is the property name of the value to use.
*/

const annotationPermittedKey = 'iam.amazonaws.com/permitted'

/** Poller class. */
class Poller {
/**
Expand All @@ -25,6 +23,7 @@ class Poller {
* @param {string} namespace - Kubernetes namespace.
* @param {Object} customResourceManifest - CRD manifest
* @param {Object} externalSecret - ExternalSecret manifest.
* @param {string} rolePermittedAnnotation - namespace annotation that defines which roles can be assumed within this namespace
* @param {Object} metrics - Metrics client.
*/
constructor ({
Expand All @@ -34,6 +33,7 @@ class Poller {
logger,
metrics,
customResourceManifest,
rolePermittedAnnotation,
externalSecret
}) {
this._backends = backends
Expand All @@ -42,6 +42,7 @@ class Poller {
this._logger = logger
this._timeoutId = null
this._metrics = metrics
this._rolePermittedAnnotation = rolePermittedAnnotation
this._customResourceManifest = customResourceManifest

this._externalSecret = externalSecret
Expand Down Expand Up @@ -175,7 +176,7 @@ class Poller {
}
}
// an empty annotation value allows access to all roles
const re = new RegExp(namespace.metadata.annotations[annotationPermittedKey])
const re = new RegExp(namespace.metadata.annotations[this._rolePermittedAnnotation])

if (!re.test(role)) {
allowed = false
Expand Down
15 changes: 9 additions & 6 deletions lib/poller.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ describe('Poller', () => {
uid: fakeExternalSecret.metadata.uid
})

const rolePermittedAnnotation = 'iam.amazonaws.com/permitted'

beforeEach(() => {
backendMock = sinon.mock()
kubeClientMock = sinon.mock()
Expand Down Expand Up @@ -90,6 +92,7 @@ describe('Poller', () => {
kubeClient: kubeClientMock,
logger: loggerMock,
externalSecret: fakeExternalSecret,
rolePermittedAnnotation,
customResourceManifest: fakeCustomResourceManifest
})
}
Expand Down Expand Up @@ -440,7 +443,7 @@ describe('Poller', () => {
})

it('does not permit update of secret', async () => {
fakeNamespace.body.metadata.annotations['iam.amazonaws.com/permitted'] = '^$'
fakeNamespace.body.metadata.annotations[rolePermittedAnnotation] = '^$'
poller = pollerFactory({
backendType: 'fakeBackendType',
name: 'fakeSecretName',
Expand Down Expand Up @@ -536,31 +539,31 @@ describe('Poller', () => {
},
{
// empty annotation
ns: { metadata: { annotations: { 'iam.amazonaws.com/permitted': '' } } },
ns: { metadata: { annotations: { [rolePermittedAnnotation]: '' } } },
descriptor: {},
permitted: true
},
{
// test regex
ns: { metadata: { annotations: { 'iam.amazonaws.com/permitted': '.*' } } },
ns: { metadata: { annotations: { [rolePermittedAnnotation]: '.*' } } },
descriptor: { roleArn: 'whatever' },
permitted: true
},
{
// test regex: deny access
ns: { metadata: { annotations: { 'iam.amazonaws.com/permitted': '^$' } } },
ns: { metadata: { annotations: { [rolePermittedAnnotation]: '^$' } } },
descriptor: { roleArn: 'whatever' },
permitted: false
},
{
// real world example
ns: { metadata: { annotations: { 'iam.amazonaws.com/permitted': 'arn:aws:iam::123456789012:role/.*' } } },
ns: { metadata: { annotations: { [rolePermittedAnnotation]: 'arn:aws:iam::123456789012:role/.*' } } },
descriptor: { roleArn: 'arn:aws:iam::123456789012:role/somerole' },
permitted: true
},
{
// test undefined
ns: { metadata: { annotations: { 'iam.amazonaws.com/permitted': 'my-kiam-role.*' } } },
ns: { metadata: { annotations: { [rolePermittedAnnotation]: 'my-kiam-role.*' } } },
descriptor: {},
permitted: true
}
Expand Down

0 comments on commit 1c35682

Please sign in to comment.