Skip to content

Commit

Permalink
aws_secret (lookup) - Add support for handling secrets marked for del…
Browse files Browse the repository at this point in the history
…etion
  • Loading branch information
tremble committed Aug 11, 2021
1 parent 5876c14 commit 92f396d
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 15 deletions.
2 changes: 2 additions & 0 deletions changelogs/fragments/lookup_aws_secret.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- aws_secret - added support for gracefully handling deleted secrets.
21 changes: 20 additions & 1 deletion plugins/lookup/aws_secret.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@
- No effect when used with I(bypath).
type: boolean
default: false
on_deleted:
description:
- Action to take if the secret has been marked for deletion.
- C(error) will raise a fatal error when the secret has been marked for deletion.
- C(skip) will silently ignore the deleted secret.
- C(warn) will skip over the deleted secret but issue a warning.
default: error
type: string
choices: ['error', 'skip', 'warn']
on_missing:
description:
- Action to take if the secret is missing.
Expand Down Expand Up @@ -148,7 +157,7 @@ class LookupModule(LookupBase):
def run(self, terms, variables=None, boto_profile=None, aws_profile=None,
aws_secret_key=None, aws_access_key=None, aws_security_token=None, region=None,
bypath=False, nested=False, join=False, version_stage=None, version_id=None, on_missing='error',
on_denied='error'):
on_denied='error', on_deleted='error'):
'''
:arg terms: a list of lookups to run.
e.g. ['parameter_name', 'parameter_name_too' ]
Expand All @@ -164,12 +173,17 @@ def run(self, terms, variables=None, boto_profile=None, aws_profile=None,
:kwarg version_stage: Stage of the secret version
:kwarg version_id: Version of the secret(s)
:kwarg on_missing: Action to take if the secret is missing
:kwarg on_deleted: Action to take if the secret is marked for deletion
:kwarg on_denied: Action to take if access to the secret is denied
:returns: A list of parameter values or a list of dictionaries if bypath=True.
'''
if not HAS_BOTO3:
raise AnsibleError('botocore and boto3 are required for aws_ssm lookup.')

deleted = on_deleted.lower()
if not isinstance(deleted, string_types) or missing not in ['error', 'warn', 'skip']:
raise AnsibleError('"on_deleted" must be a string and one of "error", "warn" or "skip", not %s' % missing)

missing = on_missing.lower()
if not isinstance(missing, string_types) or missing not in ['error', 'warn', 'skip']:
raise AnsibleError('"on_missing" must be a string and one of "error", "warn" or "skip", not %s' % missing)
Expand Down Expand Up @@ -258,6 +272,11 @@ def get_secret_value(self, term, client, version_stage=None, version_id=None, on
return str(ret_val)
else:
return response['SecretString']
except is_boto3_error_message('marked for deletion'):
if on_deleted == 'error':
raise AnsibleError("Failed to find secret %s (marked for deletion)" % term)
elif on_deleted == 'warn':
self._display.warning('Skipping, did not find secret (marked for deletion) %s' % term)
except is_boto3_error_code('ResourceNotFoundException'):
if on_missing == 'error':
raise AnsibleError("Failed to find secret %s (ResourceNotFound)" % term)
Expand Down
67 changes: 53 additions & 14 deletions tests/integration/targets/lookup_aws_secret/tasks/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,41 +18,80 @@
block:
- name: define secret name
set_fact:
secret_name: "ansible-test-{{ resource_prefix | hash('md5') }}-secret"
secret_name: "ansible-test-{{ tiny_prefix }}-secret"
secret_value: "{{ lookup('password', '/dev/null chars=ascii_lowercase,digits,punctuation length=16') }}"
on_missing_secret: "skip"
on_deleted_secret: "skip"

- name: lookup missing secret
- name: lookup missing secret (skip)
set_fact:
missing_secret: "{{ lookup('amazon.aws.aws_secret', secret_name, on_missing=on_missing_secret, **connection_args) }}"
missing_secret: "{{ lookup('amazon.aws.aws_secret', secret_name, on_missing=on_missing_secret, on_deleted=on_deleted_secret, **connection_args) }}"

- name: assert that missing_secret is defined
assert:
that:
- missing_secret is defined
- missing_secret | list | length == 0


- name: lookup missing secret (error)
set_fact:
missing_secret: "{{ lookup('amazon.aws.aws_secret', secret_name, **connection_args) }}"
ignore_errors: True
register: get_missing_secret

- name: assert that setting the missing_secret failed
assert:
that:
- get_missing_secret is failed

- name: create secret "{{ secret_name }}"
aws_secret:
name: "{{ secret_name }}"
secret: "{{ secret_value }}"
tags:
ansible-test: "aws-tests-integration"
state: present

- name: read secret value
set_fact:
look_secret: "{{ lookup('amazon.aws.aws_secret', secret_name, **connection_args) }}"

- name: assert that secret was successfully retrieved
assert:
that:
- look_secret == secret_value


- name: delete secret
aws_secret:
name: "{{ secret_name }}"
state: absent

- name: lookup deleted secret (skip)
set_fact:
deleted_secret: "{{ lookup('amazon.aws.aws_secret', secret_name, on_missing=on_missing_secret, on_deleted=on_deleted_secret, **connection_args) }}"

- name: assert that deleted_secret is defined
assert:
that:
- deleted_secret is defined
- deleted_secret | list | length == 0

- name: lookup deleted secret (error)
set_fact:
missing_secret: "{{ lookup('amazon.aws.aws_secret', secret_name, **connection_args) }}"
ignore_errors: True
register: get_deleted_secret

- name: assert that setting the deleted_secret failed
assert:
that:
- get_deleted_secret is failed

always:
# delete secret created
- name: delete secret
aws_secret:
name: "{{ secret_name }}"
state: absent
ignore_errors: yes

# delete secret created
- name: delete secret
aws_secret:
name: "{{ secret_name }}"
state: absent
ignore_errors: yes

0 comments on commit 92f396d

Please sign in to comment.