Skip to content

Commit

Permalink
ecs_ecr - Add encryption_configuration option (#1623)
Browse files Browse the repository at this point in the history
ecs_ecr - Add encryption_configuration option

SUMMARY
Adds an encryption_configuration option for new repositories to allow specifying a KMS key. Fixes #1203.
ISSUE TYPE

Feature Pull Request

COMPONENT NAME
ecs_ecr
ADDITIONAL INFORMATION

Reviewed-by: Markus Bergholz <[email protected]>
Reviewed-by: Mark Chappell <None>
Reviewed-by: Alina Buzachis <None>
(cherry picked from commit efbe850)
  • Loading branch information
rwha authored and patchback[bot] committed Jan 18, 2023
1 parent b642edf commit 2b410f0
Show file tree
Hide file tree
Showing 4 changed files with 192 additions and 4 deletions.
2 changes: 2 additions & 0 deletions changelogs/fragments/1623-ecs_ecr-add-kms-config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- ecs_ecr - add `encryption_configuration` option (https://github.com/ansible-collections/community.aws/pull/1623).
56 changes: 52 additions & 4 deletions plugins/modules/ecs_ecr.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,24 @@
default: false
type: bool
version_added: 1.3.0
encryption_configuration:
description:
- The encryption configuration for the repository.
required: false
suboptions:
encryption_type:
description:
- The encryption type to use.
choices: [AES256, KMS]
default: 'AES256'
type: str
kms_key:
description:
- If I(encryption_type=KMS), specify the KMS key to use for encryption.
- The alias, key ID, or full ARN of the KMS key can be specified.
type: str
type: dict
version_added: 5.2.0
author:
- David M. Lee (@leedm777)
extends_documentation_fragment:
Expand Down Expand Up @@ -161,6 +179,13 @@
community.aws.ecs_ecr:
name: needs-no-lifecycle-policy
purge_lifecycle_policy: true
- name: set-encryption-configuration
community.aws.ecs_ecr:
name: uses-custom-kms-key
encryption_configuration:
encryption_type: KMS
kms_key: custom-kms-key-alias
'''

RETURN = '''
Expand Down Expand Up @@ -201,6 +226,7 @@
except ImportError:
pass # Handled by AnsibleAWSModule

from ansible.module_utils.common.dict_transformations import snake_dict_to_camel_dict
from ansible.module_utils.six import string_types

from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule
Expand Down Expand Up @@ -249,17 +275,21 @@ def get_repository_policy(self, registry_id, name):
except is_boto3_error_code(['RepositoryNotFoundException', 'RepositoryPolicyNotFoundException']):
return None

def create_repository(self, registry_id, name, image_tag_mutability):
def create_repository(self, registry_id, name, image_tag_mutability, encryption_configuration):
if registry_id:
default_registry_id = self.sts.get_caller_identity().get('Account')
if registry_id != default_registry_id:
raise Exception('Cannot create repository in registry {0}.'
'Would be created in {1} instead.'.format(registry_id, default_registry_id))

if encryption_configuration is None:
encryption_configuration = dict(encryptionType='AES256')

if not self.check_mode:
repo = self.ecr.create_repository(
repositoryName=name,
imageTagMutability=image_tag_mutability).get('repository')
imageTagMutability=image_tag_mutability,
encryptionConfiguration=encryption_configuration).get('repository')
self.changed = True
return repo
else:
Expand Down Expand Up @@ -412,6 +442,7 @@ def run(ecr, params):
lifecycle_policy_text = params['lifecycle_policy']
purge_lifecycle_policy = params['purge_lifecycle_policy']
scan_on_push = params['scan_on_push']
encryption_configuration = snake_dict_to_camel_dict(params['encryption_configuration'])

# Parse policies, if they are given
try:
Expand All @@ -438,10 +469,16 @@ def run(ecr, params):
result['created'] = False

if not repo:
repo = ecr.create_repository(registry_id, name, image_tag_mutability)
repo = ecr.create_repository(
registry_id, name, image_tag_mutability, encryption_configuration)
result['changed'] = True
result['created'] = True
else:
if encryption_configuration is not None:
if repo.get('encryptionConfiguration') != encryption_configuration:
result['msg'] = 'Cannot modify repository encryption type'
return False, result

repo = ecr.put_image_tag_mutability(registry_id, name, image_tag_mutability)
result['repository'] = repo

Expand Down Expand Up @@ -557,7 +594,18 @@ def main():
purge_policy=dict(required=False, type='bool'),
lifecycle_policy=dict(required=False, type='json'),
purge_lifecycle_policy=dict(required=False, type='bool'),
scan_on_push=(dict(required=False, type='bool', default=False))
scan_on_push=(dict(required=False, type='bool', default=False)),
encryption_configuration=dict(
required=False,
type='dict',
options=dict(
encryption_type=dict(required=False, type='str', default='AES256', choices=['AES256', 'KMS']),
kms_key=dict(required=False, type='str', no_log=False),
),
required_if=[
['encryption_type', 'KMS', ['kms_key']],
],
),
)
mutually_exclusive = [
['policy', 'purge_policy'],
Expand Down
66 changes: 66 additions & 0 deletions tests/integration/targets/ecs_ecr/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,24 @@
- set_fact:
ecr_name: '{{ resource_prefix }}-ecr'

- name: get ARN of calling user
aws_caller_info:
register: aws_caller_info

- name: create KMS key for testing
aws_kms:
alias: "{{ resource_prefix }}-ecr"
description: a key used for testing ECR
state: present
enabled: yes
key_spec: SYMMETRIC_DEFAULT
key_usage: ENCRYPT_DECRYPT
policy: "{{ lookup('template', 'kms_policy.j2') }}"
tags:
Name: "{{ resource_prefix }}-ecr"
AnsibleTest: AnsibleTestVpc
register: kms_test_key

- name: When creating with check mode
ecs_ecr:
name: '{{ ecr_name }}'
Expand Down Expand Up @@ -54,6 +72,11 @@
that:
- result.repository.imageTagMutability == "MUTABLE"

- name: it should use AES256 encryption by default
assert:
that:
- result.repository.encryptionConfiguration.encryptionType == "AES256"

- name: When pulling an existing repository that has no existing policy
ecs_ecr:
name: '{{ ecr_name }}'
Expand Down Expand Up @@ -538,9 +561,52 @@
- result is changed
- not result.repository.imageScanningConfiguration.scanOnPush

- name: When modifying the encryption setting of an existing repository
ecs_ecr:
name: '{{ ecr_name }}'
encryption_configuration:
encryption_type: KMS
kms_key: '{{ kms_test_key.key_arn }}'
register: result
ignore_errors: true

- name: it should fail
assert:
that:
- result is failed

- name: delete repository
ecs_ecr:
name: '{{ ecr_name }}'
state: absent

- name: When creating a repo using KMS encryption
ecs_ecr:
name: '{{ ecr_name }}'
encryption_configuration:
encryption_type: KMS
kms_key: '{{ kms_test_key.key_arn }}'
register: result

- name: it should create the repo and use KMS encryption
assert:
that:
- result is changed
- result.repository.encryptionConfiguration.encryptionType == "KMS"

- name: it should use the provided KMS key
assert:
that:
- result.repository.encryptionConfiguration.kmsKey == '{{ kms_test_key.key_arn }}'

always:

- name: Delete lingering ECR repository
ecs_ecr:
name: '{{ ecr_name }}'
state: absent

- name: Delete KMS key
aws_kms:
key_id: '{{ kms_test_key.key_arn }}'
state: absent
72 changes: 72 additions & 0 deletions tests/integration/targets/ecs_ecr/templates/kms_policy.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
{
"Id": "key-ansible-test-policy-123",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Allow access for root user",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::{{ aws_caller_info.account }}:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow access for calling user",
"Effect": "Allow",
"Principal": {
"AWS": "{{ aws_caller_info.arn }}"
},
"Action": [
"kms:Create*",
"kms:Describe*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:TagResource",
"kms:UntagResource",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion"
],
"Resource": "*"
},
{
"Sid": "Allow use of the key",
"Effect": "Allow",
"Principal": {
"AWS": "{{ aws_caller_info.arn }}"
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*"
},
{
"Sid": "Allow attachment of persistent resources",
"Effect": "Allow",
"Principal": {
"AWS": "{{ aws_caller_info.arn }}"
},
"Action": [
"kms:CreateGrant",
"kms:ListGrants",
"kms:RevokeGrant"
],
"Resource": "*",
"Condition": {
"Bool": {
"kms:GrantIsForAWSResource": "true"
}
}
}
]
}

0 comments on commit 2b410f0

Please sign in to comment.