Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aws_ssm connection: add SSE encryption parameters. #763

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- aws_ssm connection plugin - add parameters to explicitly specify SSE mode and KMS key id for uploads on the file transfer bucket. (https://github.com/ansible-collections/community.aws/pull/763)
58 changes: 51 additions & 7 deletions plugins/connection/aws_ssm.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,18 @@
type: integer
vars:
- name: ansible_aws_ssm_timeout
bucket_sse_mode:
description: Server-side encryption mode to use for uploads on the S3 bucket used for file transfer.
choices: [ 'AES256', 'aws:kms' ]
required: false
version_added: 2.2.0
vars:
fh-maxime-froment marked this conversation as resolved.
Show resolved Hide resolved
- name: ansible_aws_ssm_bucket_sse_mode
bucket_sse_kms_key_id:
description: KMS key id to use when encrypting objects using C(bucket_sse_mode=aws:kms). Ignored otherwise.
version_added: 2.2.0
vars:
fh-maxime-froment marked this conversation as resolved.
Show resolved Hide resolved
- name: ansible_aws_ssm_bucket_sse_kms_key_id
'''

EXAMPLES = r'''
Expand Down Expand Up @@ -162,6 +174,20 @@
state: directory
# Execution: ansible-playbook win_file.yaml -i aws_ec2.yml
# The playbook tasks will get executed on the instance ids returned from the dynamic inventory plugin using ssm connection.

# Install a Nginx Package on Linux Instance; with specific SSE for file transfer
- name: Install a Nginx Package
vars:
ansible_connection: aws_ssm
ansible_aws_ssm_bucket_name: nameofthebucket
ansible_aws_ssm_region: us-west-2
ansible_aws_ssm_bucket_sse_mode: 'aws:kms'
ansible_aws_ssm_bucket_sse_kms_key_id: alias/kms-key-alias
tasks:
- name: Install a Nginx Package
yum:
name: nginx
state: present
'''

import os
Expand Down Expand Up @@ -506,11 +532,14 @@ def _flush_stderr(self, subprocess):

return stderr

def _get_url(self, client_method, bucket_name, out_path, http_method, profile_name):
def _get_url(self, client_method, bucket_name, out_path, http_method, profile_name, extra_args=None):
''' Generate URL for get_object / put_object '''
region_name = self.get_option('region') or 'us-east-1'
client = self._get_boto_client('s3', region_name=region_name, profile_name=profile_name)
return client.generate_presigned_url(client_method, Params={'Bucket': bucket_name, 'Key': out_path}, ExpiresIn=3600, HttpMethod=http_method)
params = {'Bucket': bucket_name, 'Key': out_path}
if extra_args is not None:
params.update(extra_args)
return client.generate_presigned_url(client_method, Params=params, ExpiresIn=3600, HttpMethod=http_method)

def _get_boto_client(self, service, region_name=None, profile_name=None):
''' Gets a boto3 client based on the STS token '''
Expand Down Expand Up @@ -554,14 +583,29 @@ def _file_transport_command(self, in_path, out_path, ssm_action):

profile_name = self.get_option('profile')

put_args = dict()
put_headers = dict()
if self.get_option('bucket_sse_mode'):
put_args['ServerSideEncryption'] = self.get_option('bucket_sse_mode')
put_headers['x-amz-server-side-encryption'] = self.get_option('bucket_sse_mode')
if self.get_option('bucket_sse_mode') == 'aws:kms' and self.get_option('bucket_sse_kms_key_id'):
put_args['SSEKMSKeyId'] = self.get_option('bucket_sse_kms_key_id')
put_headers['x-amz-server-side-encryption-aws-kms-key-id'] = self.get_option('bucket_sse_kms_key_id')

if self.is_windows:
put_command = "Invoke-WebRequest -Method PUT -InFile '%s' -Uri '%s' -UseBasicParsing" % (
in_path, self._get_url('put_object', self.get_option('bucket_name'), s3_path, 'PUT', profile_name))
put_command_headers = "; ".join(["'%s' = '%s'" % (h, v) for h, v in put_headers.items()])
put_command = "Invoke-WebRequest -Method PUT -Headers @{%s} -InFile '%s' -Uri '%s' -UseBasicParsing" % (
put_command_headers, in_path,
self._get_url('put_object', self.get_option('bucket_name'), s3_path, 'PUT', profile_name,
extra_args=put_args))
get_command = "Invoke-WebRequest '%s' -OutFile '%s'" % (
self._get_url('get_object', self.get_option('bucket_name'), s3_path, 'GET', profile_name), out_path)
else:
put_command = "curl --request PUT --upload-file '%s' '%s'" % (
in_path, self._get_url('put_object', self.get_option('bucket_name'), s3_path, 'PUT', profile_name))
put_command_headers = "".join(["-H '%s: %s' " % (h, v) for h, v in put_headers.items()])
put_command = "curl --request PUT %s--upload-file '%s' '%s'" % (
put_command_headers, in_path,
self._get_url('put_object', self.get_option('bucket_name'), s3_path, 'PUT', profile_name,
extra_args=put_args))
get_command = "curl '%s' -o '%s'" % (
self._get_url('get_object', self.get_option('bucket_name'), s3_path, 'GET', profile_name), out_path)

Expand All @@ -572,7 +616,7 @@ def _file_transport_command(self, in_path, out_path, ssm_action):
client.download_fileobj(self.get_option('bucket_name'), s3_path, data)
else:
with open(to_bytes(in_path, errors='surrogate_or_strict'), 'rb') as data:
client.upload_fileobj(data, self.get_option('bucket_name'), s3_path)
client.upload_fileobj(data, self.get_option('bucket_name'), s3_path, ExtraArgs=put_args)
(returncode, stdout, stderr) = self.exec_command(get_command, in_data=None, sudoable=False)

# Remove the files from the bucket after they've been transferred
Expand Down
6 changes: 0 additions & 6 deletions tests/integration/targets/connection_aws_ssm/aliases
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,4 @@
# This test suite can take almost 25 minutes (on a good day)
disabled # Test is currently broken on Deb-based systems, and dependant ../connection dir access in ansible/default-test-container
unstable

cloud/aws

destructive
non_local
needs/root
needs/target/connection
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,8 @@ instance_type: t3.micro
linux_ami_name: amzn-ami-hvm-2018.03*x86_64-ebs
# Windows AMIs get replaced every few months, don't be too specific
windows_ami_name: Windows_Server-2019-English-Full-Base-*

# see:
# - https://github.com/mattclay/aws-terminator/pull/181
# - https://github.com/ansible-collections/community.aws/pull/763
s3_bucket_name: ssm-encrypted-test-bucket
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,30 @@
linux_ami_id: '{{ latest_linux_ami.image_id }}'
windows_ami_id: '{{ latest_windows_ami.image_id }}'

- name: Install Session Manager Plugin for Debian/Ubuntu
- name: Install Session Manager Plugin for Fedora/Debian/Ubuntu
include_tasks: debian.yml
when: ansible_distribution == "Ubuntu" or ansible_distribution == "Debian"
register: install_plugin_debian

- name: Install Session Manager Plugin for RedHat/Amazon
include_tasks: redhat.yml
when: ansible_distribution == "CentOS" or ansible_distribution == "RedHat" or ansible_distribution == "Amazon"
when: ansible_distribution in ["CentOS", "RedHat", "Amazon", "Fedora"]
register: install_plugin_redhat

- name: Fail if the plugin was not installed
fail:
msg: The distribution does not contain the required Session Manager Plugin
when:
- install_plugin_debian is skipped
- install_plugin_redhat is skipped
- block:
- name: Fail if the plugin was not installed
fail:
msg: The distribution does not contain the required Session Manager Plugin
when:
- install_plugin_debian is skipped
- install_plugin_redhat is skipped
always:
- debug:
var: ansible_distribution

- name: Ensure IAM instance role exists
iam_role:
name: "ansible-test-{{resource_prefix}}-aws-ssm-role"
name: "ansible-test-{{tiny_prefix}}-aws-ssm-role"
assume_role_policy_document: "{{ lookup('file','ec2-trust-policy.json') }}"
state: present
create_instance_profile: yes
Expand Down Expand Up @@ -99,10 +103,16 @@
wait_for_connection:
delay: 360

- name: Create S3 bucket
s3_bucket:
name: "{{resource_prefix}}-aws-ssm-s3"
register: s3_output
- name: create a key
aws_kms:
alias: '{{ resource_prefix }}-kms'
tags:
ansible-test: '{{ resource_prefix }}'

# - name: Create S3 bucket
# s3_bucket:
# name: "{{resource_prefix}}-aws-ssm-s3"
# register: s3_output

- name: Create Inventory file
template:
Expand All @@ -128,11 +138,11 @@
src: ec2_windows_vars_to_delete.yml.j2
ignore_errors: yes

- name: Create S3 vars_to_delete.yml
template:
dest: "{{playbook_dir}}/s3_vars_to_delete.yml"
src: s3_vars_to_delete.yml.j2
ignore_errors: yes
# - name: Create S3 vars_to_delete.yml
# template:
# dest: "{{playbook_dir}}/s3_vars_to_delete.yml"
# src: s3_vars_to_delete.yml.j2
# ignore_errors: yes

- name: Create IAM Role vars_to_delete.yml
template:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
mode: '0440'
tags: setup_infra
- name: Install SSM Plugin
become: true
yum:
name: /tmp/session-manager-plugin.rpm
state: present
disable_gpg_check: true
tags: setup_infra
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ aws_ssm_linux

[aws_ssm:vars]
ansible_connection=community.aws.aws_ssm
ansible_aws_ssm_bucket_name={{s3_output.name}}
ansible_aws_ssm_bucket_name={{s3_bucket_name}}
ansible_aws_ssm_plugin=/usr/local/sessionmanagerplugin/bin/session-manager-plugin
ansible_python_interpreter=/usr/bin/env python
local_tmp=/tmp/ansible-local-
ansible_aws_ssm_bucket_sse_mode='aws:kms'
ansible_aws_ssm_bucket_sse_kms_key_id=alias/{{ resource_prefix }}-kms

# support tests that target testhost
[testhost:children]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
bucket_name: {{s3_output.name}}
#bucket_name: {{s3_output.name}}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@
ignore_errors: yes
when: iam_role_vars_file.stat.exists == true

- name: Delete the KMS key
aws_kms:
state: absent
alias: '{{ resource_prefix }}-kms'

- name: Delete AWS keys environement
file:
path: "{{playbook_dir}}/aws-env-vars.sh"
Expand Down