Skip to content

Commit

Permalink
Merge pull request validatedpatterns#579 from mbaldessari/push-secrets
Browse files Browse the repository at this point in the history
Add a pushsecrets policy and vault path for ESO syncing
  • Loading branch information
mhjacks authored Aug 30, 2024
2 parents 0a20ea6 + 9aef778 commit 5acb722
Show file tree
Hide file tree
Showing 14 changed files with 117 additions and 43 deletions.
1 change: 1 addition & 0 deletions ansible/plugins/filter/parse_acm_secrets.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,6 @@ def parse_acm_secrets(secrets):


class FilterModule:

def filters(self):
return {"parse_acm_secrets": parse_acm_secrets}
1 change: 1 addition & 0 deletions ansible/plugins/module_utils/load_secrets_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@


class LoadSecretsV1:

def __init__(
self,
module,
Expand Down
1 change: 1 addition & 0 deletions ansible/plugins/module_utils/load_secrets_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@


class LoadSecretsV2:

def __init__(self, module, syaml, namespace, pod):
self.module = module
self.namespace = namespace
Expand Down
1 change: 1 addition & 0 deletions ansible/plugins/module_utils/parse_secrets_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@


class ParseSecretsV2:

def __init__(self, module, syaml, secrets_backing_store):
self.module = module
self.syaml = syaml
Expand Down
1 change: 1 addition & 0 deletions ansible/plugins/modules/vault_load_parsed_secrets.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@


class VaultSecretLoader:

def __init__(
self,
module,
Expand Down
91 changes: 51 additions & 40 deletions ansible/roles/vault_utils/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ unseal_namespace: "imperative"
This relies on [kubernetes.core](https://docs.ansible.com/ansible/latest/collections/kubernetes/core/k8s_module.html)
## Vault out of the box configuration
This role configures four secret paths in vault:
1. `secret/global` - Any secret under this path is accessible in read-only only to all clusters known to ACM (hub and spokes)
2. `secret/hub` - Any secret under this path is accessible in read-only only to the ACM hub cluster
3. `secret/<fqdn.of.spoke.cluster>` - Any secret under this path is accessible in read-only only to the spoke cluster
4. `secret/pushsecrets` - Any secret here can be accessed in read and write mode to all clusters known to ACM. This area can
be used with ESO's `PushSecrets` so you can push an existing secret from one namespace, to the vault under this path and
then it can be retrieved by an `ExternalSecret` either in a different namespace *or* from an entirely different cluster.

## Values secret file format

Currently this role supports two formats: version 1.0 (which is the assumed
Expand All @@ -58,46 +69,6 @@ secret file.
The values secret YAML files can be encrypted with `ansible-vault`. If the role detects they are encrypted, the password to
decrypt them will be prompted when needed.

### Version 1.0

Here is a well-commented example of a version 1.0 file:

```yaml
---
# By default when a top-level 'version: 1.0' is missing it is assumed to be '1.0'
# NEVER COMMIT THESE VALUES TO GIT
secrets:
# These secrets will be pushed in the vault at secret/hub/test The vault will
# have secret/hub/test with secret1 and secret2 as keys with their associated
# values (secrets)
test:
secret1: foo
secret2: bar
# This ends up as the s3Secret attribute to the path secret/hub/aws
aws:
s3Secret: test-secret
# This will create the vault key secret/hub/testfoo which will have two
# properties 'b64content' and 'content' which will be the base64-encoded
# content and the normal content respectively
files:
testfoo: ~/ca.crt
# These secrets will be pushed in the vault at secret/region1/test The vault will
# have secret/region1/test with secret1 and secret2 as keys with their associated
# values (secrets)
secrets.region1:
test:
secret1: foo1
secret2: bar1
# This will create the vault key secret/region2/testbar which will have two
# properties 'b64content' and 'content' which will be the base64-encoded
# content and the normal content respectively
files.region2:
testbar: ~/ca.crt
```

### Version 2.0

Here is a version 2.0 example file (specifying `version: 2.0` is mandatory in this case):
Expand Down Expand Up @@ -210,6 +181,46 @@ secrets:
ini_key: aws_secret_access_key
```

### Version 1.0

Here is a well-commented example of a version 1.0 file:

```yaml
---
# By default when a top-level 'version: 1.0' is missing it is assumed to be '1.0'
# NEVER COMMIT THESE VALUES TO GIT
secrets:
# These secrets will be pushed in the vault at secret/hub/test The vault will
# have secret/hub/test with secret1 and secret2 as keys with their associated
# values (secrets)
test:
secret1: foo
secret2: bar
# This ends up as the s3Secret attribute to the path secret/hub/aws
aws:
s3Secret: test-secret
# This will create the vault key secret/hub/testfoo which will have two
# properties 'b64content' and 'content' which will be the base64-encoded
# content and the normal content respectively
files:
testfoo: ~/ca.crt
# These secrets will be pushed in the vault at secret/region1/test The vault will
# have secret/region1/test with secret1 and secret2 as keys with their associated
# values (secrets)
secrets.region1:
test:
secret1: foo1
secret2: bar1
# This will create the vault key secret/region2/testbar which will have two
# properties 'b64content' and 'content' which will be the base64-encoded
# content and the normal content respectively
files.region2:
testbar: ~/ca.crt
```

Internals
---------

Expand Down
2 changes: 2 additions & 0 deletions ansible/roles/vault_utils/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ vault_spoke_capabilities: '[\\\"read\\\"]'
vault_spoke_ttl: "15m"
vault_global_policy: global
vault_global_capabilities: '[\\\"read\\\"]'
vault_pushsecrets_policy: pushsecrets
vault_pushsecrets_capabilities: '[\\\"create\\\",\\\"read\\\",\\\"update\\\",\\\"delete\\\"]'
external_secrets_ns: golang-external-secrets
external_secrets_sa: golang-external-secrets
external_secrets_secret: golang-external-secrets
Expand Down
24 changes: 23 additions & 1 deletion ansible/roles/vault_utils/tasks/vault_secrets_init.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,28 @@
pod: "{{ vault_pod }}"
command: "vault policy write {{ vault_global_policy }}-secret /tmp/policy-{{ vault_global_policy }}.hcl"

- name: Configure VP pushsecrets policy template
kubernetes.core.k8s_exec:
namespace: "{{ vault_ns }}"
pod: "{{ vault_pod }}"
command: >
bash -e -c "echo \"path \\\"secret/data/{{ vault_pushsecrets_policy }}/*\\\" {
capabilities = {{ vault_pushsecrets_capabilities }} }\" > /tmp/policy-{{ vault_pushsecrets_policy }}.hcl"
- name: Add metadata path to the pushsecrets policy
kubernetes.core.k8s_exec:
namespace: "{{ vault_ns }}"
pod: "{{ vault_pod }}"
command: >
bash -e -c "echo \"path \\\"secret/metadata/{{ vault_pushsecrets_policy }}/*\\\" {
capabilities = {{ vault_pushsecrets_capabilities }} }\" >> /tmp/policy-{{ vault_pushsecrets_policy }}.hcl"
- name: Configure VP pushsecrets policy
kubernetes.core.k8s_exec:
namespace: "{{ vault_ns }}"
pod: "{{ vault_pod }}"
command: "vault policy write {{ vault_pushsecrets_policy }}-secret /tmp/policy-{{ vault_pushsecrets_policy }}.hcl"

- name: Configure policy template for hub
kubernetes.core.k8s_exec:
namespace: "{{ vault_ns }}"
Expand All @@ -93,4 +115,4 @@
vault write auth/"{{ vault_hub }}"/role/"{{ vault_hub }}"-role
bound_service_account_names="{{ external_secrets_sa }}"
bound_service_account_namespaces="{{ external_secrets_ns }}"
policies="default,{{ vault_global_policy }}-secret,{{ vault_hub }}-secret" ttl="{{ vault_hub_ttl }}"
policies="default,{{ vault_global_policy }}-secret,{{ vault_pushsecrets_policy }}-secret,{{ vault_hub }}-secret" ttl="{{ vault_hub_ttl }}"
32 changes: 30 additions & 2 deletions ansible/roles/vault_utils/tasks/vault_spokes_init.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@
loop_control:
label: "{{ item.key }}"

- name: Configure policy template
- name: Configure spoke policy template
kubernetes.core.k8s_exec:
namespace: "{{ vault_ns }}"
pod: "{{ vault_pod }}"
Expand All @@ -171,6 +171,34 @@
loop_control:
label: "{{ item.key }}"

- name: Configure spoke pushsecrets policy template
kubernetes.core.k8s_exec:
namespace: "{{ vault_ns }}"
pod: "{{ vault_pod }}"
command: >
bash -e -c "echo \"path \\\"secret/data/{{ vault_pushsecrets_policy }}/*\\\" {
capabilities = {{ vault_pushsecrets_capabilities }} }\" >> /tmp/policy-{{ item.value['vault_path'] }}.hcl"
loop: "{{ clusters_info | dict2items }}"
when:
- item.value['esoToken'] is defined
- item.key != "local-cluster"
loop_control:
label: "{{ item.key }}"

- name: Configure spoke pushsecrets metadata policy template
kubernetes.core.k8s_exec:
namespace: "{{ vault_ns }}"
pod: "{{ vault_pod }}"
command: >
bash -e -c "echo \"path \\\"secret/metadata/{{ vault_pushsecrets_policy }}/*\\\" {
capabilities = {{ vault_pushsecrets_capabilities }} }\" >> /tmp/policy-{{ item.value['vault_path'] }}.hcl"
loop: "{{ clusters_info | dict2items }}"
when:
- item.value['esoToken'] is defined
- item.key != "local-cluster"
loop_control:
label: "{{ item.key }}"

- name: Configure policy for spokes
kubernetes.core.k8s_exec:
namespace: "{{ vault_ns }}"
Expand All @@ -191,7 +219,7 @@
vault write auth/"{{ item.value['vault_path'] }}"/role/"{{ item.value['vault_path'] }}"-role
bound_service_account_names="{{ external_secrets_sa }}"
bound_service_account_namespaces="{{ external_secrets_ns }}"
policies="default,{{ vault_global_policy }}-secret,{{ item.value['vault_path'] }}-secret" ttl="{{ vault_spoke_ttl }}"
policies="default,{{ vault_global_policy }}-secret,{{ vault_pushsecrets_policy }}-secret,{{ item.value['vault_path'] }}-secret" ttl="{{ vault_spoke_ttl }}"
loop: "{{ clusters_info | dict2items }}"
when:
- item.value['esoToken'] is defined
Expand Down
1 change: 1 addition & 0 deletions ansible/tests/unit/test_ini_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@


class TestMyModule(unittest.TestCase):

def setUp(self):
self.testdir_v2 = os.path.join(os.path.dirname(os.path.abspath(__file__)), "v2")

Expand Down
2 changes: 2 additions & 0 deletions ansible/tests/unit/test_parse_secrets.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ def set_module_args(args):


class BytesEncoder(json.JSONEncoder):

def default(self, o):
if isinstance(o, bytes):
return base64.b64encode(o).decode("ascii")
Expand Down Expand Up @@ -113,6 +114,7 @@ def fail_json(*args, **kwargs):

@mock.patch("getpass.getpass")
class TestMyModule(unittest.TestCase):

def create_inifile(self):
self.inifile = open("/tmp/awscredentials", "w")
config = configparser.ConfigParser()
Expand Down
1 change: 1 addition & 0 deletions ansible/tests/unit/test_vault_load_parsed_secrets.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ def fail_json(*args, **kwargs):


class TestMyModule(unittest.TestCase):

def setUp(self):
self.mock_module_helper = patch.multiple(
basic.AnsibleModule, exit_json=exit_json, fail_json=fail_json
Expand Down
1 change: 1 addition & 0 deletions ansible/tests/unit/test_vault_load_secrets.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ def fail_json(*args, **kwargs):


class TestMyModule(unittest.TestCase):

def setUp(self):
self.mock_module_helper = patch.multiple(
basic.AnsibleModule, exit_json=exit_json, fail_json=fail_json
Expand Down
1 change: 1 addition & 0 deletions ansible/tests/unit/test_vault_load_secrets_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ def fail_json(*args, **kwargs):

@mock.patch("getpass.getpass")
class TestMyModule(unittest.TestCase):

def create_inifile(self):
self.inifile = open("/tmp/awscredentials", "w")
config = configparser.ConfigParser()
Expand Down

0 comments on commit 5acb722

Please sign in to comment.