diff --git a/changelogs/fragments/876-aws_ssm_connection_ssm_document.yml b/changelogs/fragments/876-aws_ssm_connection_ssm_document.yml new file mode 100644 index 00000000000..7345273eeaf --- /dev/null +++ b/changelogs/fragments/876-aws_ssm_connection_ssm_document.yml @@ -0,0 +1,2 @@ +minor_changes: +- aws_ssm_connection - add support for custom SSM document (https://github.com/ansible-collections/community.aws/pull/876) diff --git a/plugins/connection/aws_ssm.py b/plugins/connection/aws_ssm.py index 565544671ba..b02331d7707 100644 --- a/plugins/connection/aws_ssm.py +++ b/plugins/connection/aws_ssm.py @@ -82,6 +82,11 @@ version_added: 2.2.0 vars: - name: ansible_aws_ssm_bucket_sse_kms_key_id + ssm_document: + description: SSM document to use when connecting. + vars: + - name: ansible_aws_ssm_document + version_added: 5.2.0 ''' EXAMPLES = r''' @@ -188,6 +193,19 @@ yum: name: nginx state: present + +# Install a Nginx Package on Linux Instance; with dedicated SSM document +- 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_document: nameofthecustomdocument + tasks: + - name: Install a Nginx Package + yum: + name: nginx + state: present ''' import os @@ -342,7 +360,11 @@ def start_session(self): ssm_parameters = dict() client = self._get_boto_client('ssm', region_name=region_name, profile_name=profile_name) self._client = client - response = client.start_session(Target=self.instance_id, Parameters=ssm_parameters) + start_session_args = dict(Target=self.instance_id, Parameters=ssm_parameters) + document_name = self.get_option('ssm_document') + if document_name is not None: + start_session_args['DocumentName'] = document_name + response = client.start_session(**start_session_args) self._session_id = response['SessionId'] cmd = [ diff --git a/tests/integration/targets/connection_aws_ssm_ssm_document/aliases b/tests/integration/targets/connection_aws_ssm_ssm_document/aliases new file mode 100644 index 00000000000..2f6a2beab2a --- /dev/null +++ b/tests/integration/targets/connection_aws_ssm_ssm_document/aliases @@ -0,0 +1,4 @@ +time=20m + +cloud/aws +connection_aws_ssm diff --git a/tests/integration/targets/connection_aws_ssm_ssm_document/aws_ssm_integration_test_setup.yml b/tests/integration/targets/connection_aws_ssm_ssm_document/aws_ssm_integration_test_setup.yml new file mode 100644 index 00000000000..018af40eb77 --- /dev/null +++ b/tests/integration/targets/connection_aws_ssm_ssm_document/aws_ssm_integration_test_setup.yml @@ -0,0 +1,6 @@ +- hosts: localhost + roles: + - role: ../setup_connection_aws_ssm + vars: + target_os: fedora + use_ssm_document: True diff --git a/tests/integration/targets/connection_aws_ssm_ssm_document/aws_ssm_integration_test_teardown.yml b/tests/integration/targets/connection_aws_ssm_ssm_document/aws_ssm_integration_test_teardown.yml new file mode 100644 index 00000000000..3ab6f74cf64 --- /dev/null +++ b/tests/integration/targets/connection_aws_ssm_ssm_document/aws_ssm_integration_test_teardown.yml @@ -0,0 +1,5 @@ +- hosts: localhost + tasks: + - include_role: + name: ../setup_connection_aws_ssm + tasks_from: cleanup.yml diff --git a/tests/integration/targets/connection_aws_ssm_ssm_document/meta/main.yml b/tests/integration/targets/connection_aws_ssm_ssm_document/meta/main.yml new file mode 100644 index 00000000000..d055eb86e84 --- /dev/null +++ b/tests/integration/targets/connection_aws_ssm_ssm_document/meta/main.yml @@ -0,0 +1,3 @@ +dependencies: + - connection + - setup_connection_aws_ssm diff --git a/tests/integration/targets/connection_aws_ssm_ssm_document/runme.sh b/tests/integration/targets/connection_aws_ssm_ssm_document/runme.sh new file mode 100755 index 00000000000..c99b3b0663b --- /dev/null +++ b/tests/integration/targets/connection_aws_ssm_ssm_document/runme.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +PLAYBOOK_DIR=$(pwd) +set -eux + +CMD_ARGS=("$@") + +# Destroy Environment +cleanup() { + + cd "${PLAYBOOK_DIR}" + ansible-playbook -c local aws_ssm_integration_test_teardown.yml "${CMD_ARGS[@]}" + +} + +trap "cleanup" EXIT + +# Setup Environment +ansible-playbook -c local aws_ssm_integration_test_setup.yml "$@" + +# Export the AWS Keys +set +x +. ./aws-env-vars.sh +set -x + +cd ../connection + +# Execute Integration tests +INVENTORY="${PLAYBOOK_DIR}/ssm_inventory" ./test.sh \ + -e target_hosts=aws_ssm \ + "$@" diff --git a/tests/integration/targets/setup_connection_aws_ssm/defaults/main.yml b/tests/integration/targets/setup_connection_aws_ssm/defaults/main.yml index fb54b2cbbc2..7eb6f04b84e 100644 --- a/tests/integration/targets/setup_connection_aws_ssm/defaults/main.yml +++ b/tests/integration/targets/setup_connection_aws_ssm/defaults/main.yml @@ -47,3 +47,4 @@ encrypted_s3_bucket_name: ssm-encrypted-test-bucket s3_bucket_name: "{{ resource_prefix }}-connection-ssm" kms_key_name: "{{ resource_prefix }}-connection-ssm" +ssm_document_name: "{{ resource_prefix }}-connection-ssm" diff --git a/tests/integration/targets/setup_connection_aws_ssm/files/ssm-document.json b/tests/integration/targets/setup_connection_aws_ssm/files/ssm-document.json new file mode 100644 index 00000000000..b3e5d91146f --- /dev/null +++ b/tests/integration/targets/setup_connection_aws_ssm/files/ssm-document.json @@ -0,0 +1,15 @@ +{ + "schemaVersion": "1.0", + "description": "Custom SSM document", + "sessionType": "Standard_Stream", + "inputs": { + "s3EncryptionEnabled": false, + "cloudWatchLogGroupName": "", + "cloudWatchEncryptionEnabled": false, + "idleSessionTimeout": "20", + "cloudWatchStreamingEnabled": false, + "kmsKeyId": "", + "runAsEnabled": false, + "runAsDefaultUser": "" + } +} diff --git a/tests/integration/targets/setup_connection_aws_ssm/tasks/cleanup.yml b/tests/integration/targets/setup_connection_aws_ssm/tasks/cleanup.yml index c45ac7dd457..68b491cc6d8 100644 --- a/tests/integration/targets/setup_connection_aws_ssm/tasks/cleanup.yml +++ b/tests/integration/targets/setup_connection_aws_ssm/tasks/cleanup.yml @@ -10,6 +10,9 @@ region: '{{ aws_region }}' block: + - name: setup connection argments fact + include_tasks: 'connection_args.yml' + - name: Check if instance_vars_to_delete.yml is present stat: path: "{{ playbook_dir }}/instance_vars_to_delete.yml" @@ -37,6 +40,15 @@ include_vars: "{{ playbook_dir }}/iam_role_vars_to_delete.yml" when: iam_role_vars_file.stat.exists == true + - name: Check if ssm_vars_to_delete.yml is present + stat: + path: "{{ playbook_dir }}/ssm_vars_to_delete.yml" + register: ssm_vars_file + + - name: Include variable file to delete SSM infra + include_vars: "{{ playbook_dir }}/ssm_vars_to_delete.yml" + when: ssm_vars_file.stat.exists == true + - name: Terminate EC2 instances that were previously launched ec2_instance: instance_ids: "{{ created_instance_ids }}" @@ -64,6 +76,11 @@ state: absent alias: '{{ kms_key_name }}' + - name: Delete SSM document + command: "aws ssm delete-document --name {{ ssm_document_name }}" + environment: "{{ connection_env }}" + ignore_errors: yes + - name: Delete AWS keys environement file: path: "{{ playbook_dir }}/aws-env-vars.sh" diff --git a/tests/integration/targets/setup_connection_aws_ssm/tasks/connection_args.yml b/tests/integration/targets/setup_connection_aws_ssm/tasks/connection_args.yml new file mode 100644 index 00000000000..727220e4958 --- /dev/null +++ b/tests/integration/targets/setup_connection_aws_ssm/tasks/connection_args.yml @@ -0,0 +1,14 @@ +--- +- set_fact: + # As a lookup plugin we don't have access to module_defaults + connection_args: + region: "{{ aws_region }}" + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + aws_security_token: "{{ security_token | default(omit) }}" + connection_env: + AWS_DEFAULT_REGION: "{{ aws_region }}" + AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" + AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" + AWS_SESSION_TOKEN: "{{ security_token | default(omit) }}" + no_log: True diff --git a/tests/integration/targets/setup_connection_aws_ssm/tasks/main.yml b/tests/integration/targets/setup_connection_aws_ssm/tasks/main.yml index 509e8eec5e2..e312a301d87 100644 --- a/tests/integration/targets/setup_connection_aws_ssm/tasks/main.yml +++ b/tests/integration/targets/setup_connection_aws_ssm/tasks/main.yml @@ -15,6 +15,9 @@ aws_caller_info: register: aws_caller_info + - name: setup connection argments fact + include_tasks: 'connection_args.yml' + - name: Ensure IAM instance role exists iam_role: name: "ansible-test-{{tiny_prefix}}-aws-ssm-role" @@ -43,14 +46,6 @@ when: - ami_configuration.ssm_parameter | default(False) block: - - set_fact: - # As a lookup plugin we don't have access to module_defaults - connection_args: - region: "{{ aws_region }}" - aws_access_key: "{{ aws_access_key }}" - aws_secret_key: "{{ aws_secret_key }}" - aws_security_token: "{{ security_token | default(omit) }}" - no_log: True - set_fact: ssm_amis: "{{ lookup('aws_ssm', ami_configuration.ssm_parameter, **connection_args) }}" @@ -101,6 +96,11 @@ when: - encrypted_bucket | default(False) + - name: setup SSM document + include_tasks: 'ssm_document.yml' + when: + - use_ssm_document | default(False) + - name: Create S3 bucket s3_bucket: name: "{{ s3_bucket_name }}" @@ -141,3 +141,9 @@ when: - s3_output is successful ignore_errors: yes + + - name: Create SSM vars_to_delete.yml + template: + dest: "{{ playbook_dir }}/ssm_vars_to_delete.yml" + src: ssm_vars_to_delete.yml.j2 + ignore_errors: yes diff --git a/tests/integration/targets/setup_connection_aws_ssm/tasks/ssm_document.yml b/tests/integration/targets/setup_connection_aws_ssm/tasks/ssm_document.yml new file mode 100644 index 00000000000..2e0781dd993 --- /dev/null +++ b/tests/integration/targets/setup_connection_aws_ssm/tasks/ssm_document.yml @@ -0,0 +1,11 @@ +--- +- block: + - name: Create custom SSM document + command: "aws ssm create-document --content file://{{ role_path }}/files/ssm-document.json --name {{ ssm_document_name }} --document-type Session" + environment: "{{ connection_env }}" + always: + - name: Create SSM vars_to_delete.yml + template: + dest: "{{ playbook_dir }}/ssm_vars_to_delete.yml" + src: ssm_vars_to_delete.yml.j2 + ignore_errors: yes diff --git a/tests/integration/targets/setup_connection_aws_ssm/templates/inventory-combined.aws_ssm.j2 b/tests/integration/targets/setup_connection_aws_ssm/templates/inventory-combined.aws_ssm.j2 index ea73a93752f..24fa19a272b 100644 --- a/tests/integration/targets/setup_connection_aws_ssm/templates/inventory-combined.aws_ssm.j2 +++ b/tests/integration/targets/setup_connection_aws_ssm/templates/inventory-combined.aws_ssm.j2 @@ -38,6 +38,9 @@ ansible_aws_ssm_bucket_name={{ encrypted_s3_bucket_name }} {% else %} ansible_aws_ssm_bucket_name={{ s3_bucket_name }} {% endif %} +{% if use_ssm_document | default(False) %} +ansible_aws_ssm_document={{ ssm_document_name }} +{% endif %} # support tests that target testhost [testhost:children] diff --git a/tests/integration/targets/setup_connection_aws_ssm/templates/ssm_vars_to_delete.yml.j2 b/tests/integration/targets/setup_connection_aws_ssm/templates/ssm_vars_to_delete.yml.j2 new file mode 100644 index 00000000000..af017f5ba41 --- /dev/null +++ b/tests/integration/targets/setup_connection_aws_ssm/templates/ssm_vars_to_delete.yml.j2 @@ -0,0 +1,2 @@ +--- +ssm_document_name: {{ ssm_document_name }}