Skip to content

Commit a71f9bb

Browse files
authored
Merge pull request #13 from adobe/read_ssm
Retrieve secrets from AWS SSM
2 parents eed6fc9 + bf9b231 commit a71f9bb

File tree

5 files changed

+86
-21
lines changed

5 files changed

+86
-21
lines changed

README.md

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -138,18 +138,11 @@ $ aws configure --profile aws_account_name
138138
## Azure
139139
TBD
140140

141-
## SKMS
142-
Create a file in `~/.skms/credentials.yaml` which looks like the following:
143-
```yaml
144-
endpoint: "api.skms.mycompany.com"
145-
username: <username>
146-
password: <password>
147-
```
141+
## Examples
148142

149-
## Example
150-
151-
See `examples/` folder:
143+
See [examples/](https://github.com/adobe/ops-cli/tree/master/examples) folder:
152144
- cassandra-stress - n-node cassandra cluster used for stress-testing; a basic stress profile is included
145+
- spin up a Kubernetes clsuter
153146
- distinct `ops` features
154147

155148
## Usage help
@@ -526,14 +519,11 @@ optional arguments:
526519
ops clusters/centos7.yaml packer build
527520
```
528521
529-
## Development
530-
531-
### Running tests
522+
## Secrets Management
532523
533-
- docker: `buildrunner -f buildrunner.yaml`
534-
- on your machine: `py.test tests`
524+
There are cases where you need to reference sensitive data in your `cluster.yaml` file (credentials, passwords, tokens etc). Given that the cluster configuration file can be stored in a version control system (such as Git), the best practice is to not put sensitive data in the file itself. Instead, we can use `ops-cli` to fetch the desired credentials from a secrets manager such as Vault or Amazon SSM, at runtime.
535525
536-
## Secrets Management
526+
### Vault
537527
538528
Ops can manage the automatic generation of secrets and their push in Vault, without actually persisting the secrets in the cluster file.
539529
A cluster file will only need to use a construct like the following:
@@ -548,6 +538,20 @@ Which will translate behind the scenes in :
548538
This allows us to just refer in cluster files a secret that actually exists in vault and make sure we only generate it once - if it was already created by os or any other system, we will just use what is already there.
549539
The reference is by means of fixed form jinja call added to the cluster file, which ends up interpretted later during the templating phase.
550540
541+
### Amazon Secrets Manager (SSM)
542+
543+
Amazon offers the possibility to use their [Secrets Manager](https://docs.aws.amazon.com/systems-manager/latest/userguide/what-is-systems-manager.html) in order to manage configuration data such as credentials, passwords and license keys.
544+
545+
We can use `ops-cli` to fetch the sensitive data from SSM, at runtime. Just define this in your cluster configuration file (eg. `mycluster.yaml`).
546+
547+
```
548+
db_password: "{{ '/my/ssm/path' | read_ssm(aws_profile='myprofile') }}"
549+
```
550+
551+
`ops-cli` will read the SSM value by running a command similar to: `AWS_PROFILE=aam-npe aws ssm get-parameter --name "/my/ssm/path" --region us-east-1 --with-decryption`.
552+
Note that you can specify the AWS region via `read_ssm(aws_profile='myprofile', region_name='us-west-2')`.
553+
554+
551555
## Using jinja2 filters in playbooks and terraform templates
552556
553557
You can register your own jinja2 filters that you can use in the cluster config file, terraform templates and ansible playbooks
@@ -575,6 +579,20 @@ class FilterModule(object):
575579
# test_custom_filters: "{{ 'value' | my_filter }}"
576580
```
577581
582+
## SKMS
583+
Create a file in `~/.skms/credentials.yaml` which looks like the following:
584+
```yaml
585+
endpoint: "api.skms.mycompany.com"
586+
username: <username>
587+
password: <password>
588+
```
589+
590+
## Development
591+
592+
### Running tests
593+
594+
- on your machine: `py.test tests`
595+
578596
## Troubleshooting
579597
580598
- Permission issues when installing: you should install the tool in a python virtualenv

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
simpledi>=0.2
22
awscli==1.16.97
33
ansible==2.3.1.0
4-
boto3==1.9.87
4+
boto3==1.9.91
55
boto==2.49.0
66
azure-common==1.1.4
77
azure==2.0.0rc5

src/ops/ansible/filter_plugins/commonfilters.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,12 @@ def flatten_tree(d, parent_key='', sep='/'):
6565
return dict(items)
6666

6767
def read_vault(secret_path, key='value', fetch_all=False, vault_user=None,vault_url=None, token=None, auto_prompt=True):
68-
from ops.simplesecrets import SimpleVault
68+
from ops.simplevault import SimpleVault
6969
sv = SimpleVault(vault_user=vault_user, vault_addr=vault_url, vault_token=token,auto_prompt=auto_prompt)
7070
return sv.get(path=secret_path, key=key, fetch_all=fetch_all)
7171

7272
def write_vault(secret_path, key='value', data="", vault_user=None, vault_url=None, token=None, auto_prompt=True):
73-
from ops.simplesecrets import SimpleVault
73+
from ops.simplevault import SimpleVault
7474
sv = SimpleVault(vault_user=vault_user, vault_addr=vault_url, vault_token=token, auto_prompt=auto_prompt)
7575
new_data = {}
7676
if isinstance(data, dict):
@@ -82,13 +82,18 @@ def write_vault(secret_path, key='value', data="", vault_user=None, vault_url=No
8282
return False
8383
return sv.put(path=secret_path, value=new_data )
8484

85+
def read_ssm(key, aws_profile, region_name='us-east-1'):
86+
from ops.simplessm import SimpleSSM
87+
ssm = SimpleSSM(aws_profile, region_name)
88+
return ssm.get(key)
89+
8590
def managed_vault_secret(secret_path,key='value',
8691
policy={},
8792
vault_user=None,
8893
vault_addr=None,
8994
vault_token=None,
9095
auto_prompt=True):
91-
from ops.simplesecrets import ManagedVaultSecret
96+
from ops.simplevault import ManagedVaultSecret
9297
ms = ManagedVaultSecret(path=secret_path,
9398
key=key,
9499
policy=policy,
@@ -111,5 +116,6 @@ def filters(self):
111116
'read_yaml': read_yaml,
112117
'read_vault': read_vault,
113118
'write_vault': write_vault,
114-
'managed_vault_secret': managed_vault_secret
119+
'managed_vault_secret': managed_vault_secret,
120+
'read_ssm': read_ssm
115121
}

src/ops/simplessm.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#Copyright 2019 Adobe. All rights reserved.
2+
#This file is licensed to you under the Apache License, Version 2.0 (the "License");
3+
#you may not use this file except in compliance with the License. You may obtain a copy
4+
#of the License at http://www.apache.org/licenses/LICENSE-2.0
5+
6+
#Unless required by applicable law or agreed to in writing, software distributed under
7+
#the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
8+
#OF ANY KIND, either express or implied. See the License for the specific language
9+
#governing permissions and limitations under the License.
10+
11+
#!/usr/bin/env python
12+
13+
from ops.cli import display
14+
from botocore.exceptions import ClientError
15+
import boto3
16+
import os
17+
18+
class SimpleSSM(object):
19+
def __init__(self, aws_profile, region_name):
20+
self.initial_aws_profile = os.getenv('AWS_PROFILE', None)
21+
self.aws_profile = aws_profile
22+
self.region_name = region_name
23+
24+
def get(self, key):
25+
client = self.get_ssm_client()
26+
try:
27+
return client.get_parameter(Name=key, WithDecryption=True).get("Parameter").get("Value")
28+
except ClientError as e:
29+
raise Exception('Error while trying to read SSM value for key: %s - %s' % (key, e.response['Error']['Code']))
30+
finally:
31+
self.release_ssm_client()
32+
33+
def get_ssm_client(self):
34+
os.environ['AWS_PROFILE'] = self.aws_profile
35+
return boto3.client('ssm', region_name=self.region_name)
36+
37+
def release_ssm_client(self):
38+
if self.initial_aws_profile is None:
39+
del os.environ['AWS_PROFILE']
40+
else:
41+
os.environ['AWS_PROFILE'] = self.initial_aws_profile
File renamed without changes.

0 commit comments

Comments
 (0)