Skip to content

Commit

Permalink
Merge branch 'ansible-collections:main' into acm-request
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastien-rosset authored Jan 27, 2022
2 parents f0994bd + 99c64a6 commit feceacb
Show file tree
Hide file tree
Showing 15 changed files with 611 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- ec2_lc - add support for throughput parameter (https://github.com/ansible-collections/community.aws/pull/790).
2 changes: 2 additions & 0 deletions changelogs/fragments/825-fix-elb-wait.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- elb_instance - `wait` parameter is no longer ignored (https://github.com/ansible-collections/community.aws/pull/826)
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- aws_secret - Add ``resource_policy`` parameter (https://github.com/ansible-collections/community.aws/pull/843).
78 changes: 73 additions & 5 deletions plugins/modules/aws_secret.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from __future__ import absolute_import, division, print_function
__metaclass__ = type


DOCUMENTATION = r'''
---
module: aws_secret
Expand Down Expand Up @@ -54,6 +53,13 @@
- Specifies string or binary data that you want to encrypt and store in the new version of the secret.
default: ""
type: str
resource_policy:
description:
- Specifies JSON-formatted resource policy to attach to the secret. Useful when granting cross-account access
to secrets.
required: false
type: json
version_added: 3.1.0
tags:
description:
- Specifies a list of user-defined tags that are attached to the secret.
Expand All @@ -73,7 +79,6 @@
'''


EXAMPLES = r'''
- name: Add string to AWS Secrets Manager
community.aws.aws_secret:
Expand All @@ -82,6 +87,14 @@
secret_type: 'string'
secret: "{{ super_secret_string }}"
- name: Add a secret with resource policy attached
community.aws.aws_secret:
name: 'test_secret_string'
state: present
secret_type: 'string'
secret: "{{ super_secret_string }}"
resource_policy: "{{ lookup('template', 'templates/resource_policy.json.j2', convert_data=False) | string }}"
- name: remove string from AWS Secrets Manager
community.aws.aws_secret:
name: 'test_secret_string'
Expand All @@ -90,7 +103,6 @@
secret: "{{ super_secret_string }}"
'''


RETURN = r'''
secret:
description: The secret information
Expand Down Expand Up @@ -133,6 +145,9 @@
from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import snake_dict_to_camel_dict, camel_dict_to_snake_dict
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import boto3_tag_list_to_ansible_dict, compare_aws_tags, ansible_dict_to_boto3_tag_list
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import compare_policies
from traceback import format_exc
import json

try:
from botocore.exceptions import BotoCoreError, ClientError
Expand All @@ -142,7 +157,7 @@

class Secret(object):
"""An object representation of the Secret described by the self.module args"""
def __init__(self, name, secret_type, secret, description="", kms_key_id=None,
def __init__(self, name, secret_type, secret, resource_policy=None, description="", kms_key_id=None,
tags=None, lambda_arn=None, rotation_interval=None):
self.name = name
self.description = description
Expand All @@ -152,6 +167,7 @@ def __init__(self, name, secret_type, secret, description="", kms_key_id=None,
else:
self.secret_type = "SecretString"
self.secret = secret
self.resource_policy = resource_policy
self.tags = tags or {}
self.rotation_enabled = False
if lambda_arn:
Expand Down Expand Up @@ -185,6 +201,15 @@ def update_args(self):
args[self.secret_type] = self.secret
return args

@property
def secret_resource_policy_args(self):
args = {
"SecretId": self.name
}
if self.resource_policy:
args["ResourcePolicy"] = self.resource_policy
return args

@property
def boto3_tags(self):
return ansible_dict_to_boto3_tag_list(self.Tags)
Expand All @@ -211,6 +236,15 @@ def get_secret(self, name):
self.module.fail_json_aws(e, msg="Failed to describe secret")
return secret

def get_resource_policy(self, name):
try:
resource_policy = self.client.get_resource_policy(SecretId=name)
except self.client.exceptions.ResourceNotFoundException:
resource_policy = None
except (BotoCoreError, ClientError) as e:
self.module.fail_json_aws(e, msg="Failed to get secret resource policy")
return resource_policy

def create_secret(self, secret):
if self.module.check_mode:
self.module.exit_json(changed=True)
Expand All @@ -227,13 +261,26 @@ def create_secret(self, secret):
def update_secret(self, secret):
if self.module.check_mode:
self.module.exit_json(changed=True)

try:
response = self.client.update_secret(**secret.update_args)
except (BotoCoreError, ClientError) as e:
self.module.fail_json_aws(e, msg="Failed to update secret")
return response

def put_resource_policy(self, secret):
if self.module.check_mode:
self.module.exit_json(changed=True)
try:
json.loads(secret.secret_resource_policy_args.get("ResourcePolicy"))
except (TypeError, ValueError) as e:
self.module.fail_json(msg="Failed to parse resource policy as JSON: %s" % (str(e)), exception=format_exc())

try:
response = self.client.put_resource_policy(**secret.secret_resource_policy_args)
except (BotoCoreError, ClientError) as e:
self.module.fail_json_aws(e, msg="Failed to update secret resource policy")
return response

def restore_secret(self, name):
if self.module.check_mode:
self.module.exit_json(changed=True)
Expand All @@ -255,6 +302,15 @@ def delete_secret(self, name, recovery_window):
self.module.fail_json_aws(e, msg="Failed to delete secret")
return response

def delete_resource_policy(self, name):
if self.module.check_mode:
self.module.exit_json(changed=True)
try:
response = self.client.delete_resource_policy(SecretId=name)
except (BotoCoreError, ClientError) as e:
self.module.fail_json_aws(e, msg="Failed to delete secret resource policy")
return response

def update_rotation(self, secret):
if secret.rotation_enabled:
try:
Expand Down Expand Up @@ -334,6 +390,7 @@ def main():
'kms_key_id': dict(),
'secret_type': dict(choices=['binary', 'string'], default="string"),
'secret': dict(default="", no_log=True),
'resource_policy': dict(type='json', default=None),
'tags': dict(type='dict', default={}),
'rotation_lambda': dict(),
'rotation_interval': dict(type='int', default=30),
Expand All @@ -352,6 +409,7 @@ def main():
module.params.get('secret'),
description=module.params.get('description'),
kms_key_id=module.params.get('kms_key_id'),
resource_policy=module.params.get('resource_policy'),
tags=module.params.get('tags'),
lambda_arn=module.params.get('rotation_lambda'),
rotation_interval=module.params.get('rotation_interval')
Expand All @@ -374,6 +432,8 @@ def main():
if state == 'present':
if current_secret is None:
result = secrets_mgr.create_secret(secret)
if secret.resource_policy and result.get("ARN"):
result = secrets_mgr.put_resource_policy(secret)
changed = True
else:
if current_secret.get("DeletedDate"):
Expand All @@ -385,6 +445,14 @@ def main():
if not rotation_match(secret, current_secret):
result = secrets_mgr.update_rotation(secret)
changed = True
current_resource_policy_response = secrets_mgr.get_resource_policy(secret.name)
current_resource_policy = current_resource_policy_response.get("ResourcePolicy")
if compare_policies(secret.resource_policy, current_resource_policy):
if secret.resource_policy is None and current_resource_policy:
result = secrets_mgr.delete_resource_policy(secret.name)
else:
result = secrets_mgr.put_resource_policy(secret)
changed = True
current_tags = boto3_tag_list_to_ansible_dict(current_secret.get('Tags', []))
tags_to_add, tags_to_remove = compare_aws_tags(current_tags, secret.tags)
if tags_to_add:
Expand Down
13 changes: 12 additions & 1 deletion plugins/modules/ec2_lc.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@
description:
- The number of IOPS per second to provision for the volume.
- Required when I(volume_type=io1).
throughput:
type: int
description:
- The throughput to provision for a gp3 volume.
- Valid Range is a minimum value of 125 and a maximum value of 1000.
version_added: 3.1.0
encrypted:
type: bool
default: false
Expand Down Expand Up @@ -478,7 +484,7 @@ def create_block_device_meta(module, volume):
if 'no_device' in volume:
return_object['NoDevice'] = volume.get('no_device')

if any(key in volume for key in ['snapshot', 'volume_size', 'volume_type', 'delete_on_termination', 'ips', 'encrypted']):
if any(key in volume for key in ['snapshot', 'volume_size', 'volume_type', 'delete_on_termination', 'iops', 'throughput', 'encrypted']):
return_object['Ebs'] = {}

if 'snapshot' in volume:
Expand All @@ -496,6 +502,11 @@ def create_block_device_meta(module, volume):
if 'iops' in volume:
return_object['Ebs']['Iops'] = volume.get('iops')

if 'throughput' in volume:
if volume.get('volume_type') != 'gp3':
module.fail_json(msg='The throughput parameter is supported only for GP3 volumes.')
return_object['Ebs']['Throughput'] = volume.get('throughput')

if 'encrypted' in volume:
return_object['Ebs']['Encrypted'] = volume.get('encrypted')

Expand Down
10 changes: 6 additions & 4 deletions plugins/modules/elb_instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,9 @@ def deregister(self, wait, timeout):
# already OutOfService is being deregistered.
self.changed = True

for lb in self.lbs:
self._await_elb_instance_state(lb, 'Deregistered', timeout)
if wait:
for lb in self.lbs:
self._await_elb_instance_state(lb, 'Deregistered', timeout)

def register(self, wait, enable_availability_zone, timeout):
"""Register the instance for all ELBs and wait for the ELB
Expand Down Expand Up @@ -176,8 +177,9 @@ def register(self, wait, enable_availability_zone, timeout):

self.changed = True

for lb in self.lbs:
self._await_elb_instance_state(lb, 'InService', timeout)
if wait:
for lb in self.lbs:
self._await_elb_instance_state(lb, 'InService', timeout)

@AWSRetry.jittered_backoff()
def _describe_elbs(self, **params):
Expand Down
50 changes: 50 additions & 0 deletions tests/integration/targets/aws_secret/tasks/basic.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
---
- block:
# ============================================================
# Preparation
# ============================================================
- name: 'Retrieve caller facts'
aws_caller_info:
register: aws_caller_info

# ============================================================
# Module parameter testing
# ============================================================
Expand Down Expand Up @@ -101,6 +108,49 @@
that:
- result.changed

- name: add resource policy to secret
aws_secret:
name: "{{ secret_name }}"
description: 'this is a change to this secret'
state: present
secret_type: 'string'
secret: "{{ super_secret_string }}"
resource_policy: "{{ lookup('template', 'secret-policy.j2', convert_data=False) | string }}"
register: result

- name: assert correct keys are returned
assert:
that:
- result.changed

- name: remove existing resource policy from secret
aws_secret:
name: "{{ secret_name }}"
description: 'this is a change to this secret'
state: present
secret_type: 'string'
secret: "{{ super_secret_string }}"
register: result

- name: assert correct keys are returned
assert:
that:
- result.changed

- name: remove resource policy from secret (idempotency)
aws_secret:
name: "{{ secret_name }}"
description: 'this is a change to this secret'
state: present
secret_type: 'string'
secret: "{{ super_secret_string }}"
register: result

- name: assert no change happened
assert:
that:
- not result.changed

- name: remove secret
aws_secret:
name: "{{ secret_name }}"
Expand Down
11 changes: 11 additions & 0 deletions tests/integration/targets/aws_secret/templates/secret-policy.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"Version" : "2012-10-17",
"Statement" : [ {
"Effect" : "Allow",
"Principal" : {
"AWS" : "arn:aws:iam::{{ aws_caller_info.account }}:root"
},
"Action" : "secretsmanager:*",
"Resource" : "*"
} ]
}
4 changes: 4 additions & 0 deletions tests/integration/targets/ec2_lc/aliases
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
cloud/aws

ec2_lc_info
ec2_lc_find
7 changes: 7 additions & 0 deletions tests/integration/targets/ec2_lc/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
# defaults file for ec2_instance
ec2_instance_name: '{{ resource_prefix }}-node'
ec2_instance_owner: 'integration-run-{{ resource_prefix }}'
ec2_instance_type: t2.micro
ec2_ami_name: "amzn-ami-hvm*"
alarm_prefix: "ansible-test"
7 changes: 7 additions & 0 deletions tests/integration/targets/ec2_lc/meta/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
dependencies:
- prepare_tests
- setup_ec2
- setup_ec2_facts
- role: setup_botocore_pip
vars:
boto3_version: "1.17.86"
Loading

0 comments on commit feceacb

Please sign in to comment.