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

fix: iam role #179

Merged
merged 2 commits into from
Nov 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
9 changes: 5 additions & 4 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 @@ -169,13 +170,13 @@ class Poller {
let allowed = true
let reason = ''

if (!namespace.metadata.annotations) {
if (!namespace.metadata.annotations || !role) {
return {
allowed, reason
}
}
// 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
19 changes: 14 additions & 5 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,27 +539,33 @@ 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: { [rolePermittedAnnotation]: 'my-kiam-role.*' } } },
descriptor: {},
permitted: true
}
]

Expand Down