diff --git a/.gitignore b/.gitignore index f96f3079..b6b7bb4f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /tests/output/ +/tests/integration/integration_config.yml /tests/integration/inventory /changelogs/.plugin-cache.yaml tests/integration/cloud-config-* diff --git a/README.md b/README.md index 407a64be..4e34d6e7 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,8 @@ Name | Description [cloud.aws_ops.aws_setup_credentials](https://github.com/ansible-collections/cloud.aws_ops/blob/main/roles/aws_setup_credentials/README.md)|A role to define credentials for aws modules. [cloud.aws_ops.awsconfig_detach_and_delete_internet_gateway](https://github.com/ansible-collections/cloud.aws_ops/blob/main/roles/awsconfig_detach_and_delete_internet_gateway/README.md)|A role to detach and delete the internet gateway you specify from virtual private cloud. [cloud.aws_ops.awsconfig_multiregion_cloudtrail](https://github.com/ansible-collections/cloud.aws_ops/blob/main/roles/awsconfig_multiregion_cloudtrail/README.md)|A role to create/delete a Trail for multiple regions. +[cloud.backup_create_plan](https://github.com/ansible-collections/cloud.aws_ops/blob/main/roles/backup_create_plan/README.md)|A role to create an AWS backup plan. +[cloud.backup_select_resources](https://github.com/ansible-collections/cloud.aws_ops/blob/main/roles/backup_create_plan/README.md)|A role to select resources to back up with an existing backup plan. [cloud.aws_ops.customized_ami](https://github.com/ansible-collections/cloud.aws_ops/blob/main/roles/customized_ami/README.md)|A role to manage custom AMIs on AWS. [cloud.aws_ops.ec2_instance_terminate_by_tag](https://github.com/ansible-collections/cloud.aws_ops/blob/main/roles/ec2_instance_terminate_by_tag/README.md)|A role to terminate the EC2 instances based on a specific tag you specify. [cloud.aws_ops.enable_cloudtrail_encryption_with_kms](https://github.com/ansible-collections/cloud.aws_ops/blob/main/roles/enable_cloudtrail_encryption_with_kms/README.md)|A role to encrypt an AWS CloudTrail trail using the AWS Key Management Service (AWS KMS) customer managed key you specify. diff --git a/roles/backup_create_plan/README.md b/roles/backup_create_plan/README.md new file mode 100644 index 00000000..84e79404 --- /dev/null +++ b/roles/backup_create_plan/README.md @@ -0,0 +1,67 @@ +backup_create_plan +================== + +A role to create a backup plan and optionally a vault. A set of variables for plan rules is included for use as-is or as examples for modification. This role can be combined with the backup_select_resources role to back up a selection of resources. + +Requirements +------------ + +AWS User Account with the following permission: + +* backup:CreateBackupVault +* backup:CreateBackupPlan +* backup:DescribeBackupVault +* backup:ListBackupPlans +* backup:ListTags +* backup-storage:MountCapsule +* kms:CreateGrant +* kms:GenerateDataKey +* kms:Decrypt +* kms:RetireGrant +* kms:DescribeKey + +Role Variables +-------------- + +* **plan_name**: (Required) The name of the backup plan you want to create +* **plan_rules**: (Required) A set of rules for the backup, as a list of dicts +* **plan_windows_vss_settings**: Optional settings for Windows VSS backup, see [AdvancedBackupSetting object in the AWS Backup API documentation](https://docs.aws.amazon.com/aws-backup/latest/devguide/API_AdvancedBackupSetting.html) for details +* **plan_tags**: Optional tags to apply to all backups created with the plan +* **vault_name**: The name of the vault you want to use or create. If not provided, the role will use (and create if needed) the AWS default vault for the account, named Default. +* **vault_encryption_key_arn**: Optional ARN of key to use for vault encryption +* **vault_tags**: Optional tags to apply to the vault + +### Included sample plan rules variables +These are included in vars/main.yaml for use as-is or as examples for modification. + +* **hourly_backup**: Rules specifying hourly continous backup at :15 UTC with 7-day retention +* **daily_backup**: Rules specifying daily backup at 5am UTC with Amazon defaults for all other settings +* **weekly_backup**: Rules specifying weekly backup on Mondays at 5am UTC with 90 day retention after quick transition to cold storage +* **monthly_backup**: Rules specifying monthly backup at 5am UTC on 1st of month with copy to additional vault (requires an additional variable **copy_vault_name** be set with the name of the vault to copy to) + + +Dependencies +------------ + +* role: [aws_setup_credentials](../aws_setup_credentials/README.md) + +Example Playbook +---------------- + + - hosts: localhost + roles: + - role: cloud.aws_ops.backup_create_plan + plan_name: my-backup-plan + plan_rules: "{{ daily_backup }}" + +License +------- + +GNU General Public License v3.0 or later + +See [LICENCE](https://github.com/ansible-collections/cloud.aws_ops/blob/main/LICENSE) to see the full text. + +Author Information +------------------ + +* Ansible Cloud Content Team diff --git a/roles/backup_create_plan/defaults/main.yaml b/roles/backup_create_plan/defaults/main.yaml new file mode 100644 index 00000000..2d311b4c --- /dev/null +++ b/roles/backup_create_plan/defaults/main.yaml @@ -0,0 +1,2 @@ +--- +vault_name: Default diff --git a/roles/backup_create_plan/meta/main.yaml b/roles/backup_create_plan/meta/main.yaml new file mode 100644 index 00000000..e8b3ab42 --- /dev/null +++ b/roles/backup_create_plan/meta/main.yaml @@ -0,0 +1,3 @@ +--- +dependencies: + - role: cloud.aws_ops.aws_setup_credentials diff --git a/roles/backup_create_plan/tasks/main.yaml b/roles/backup_create_plan/tasks/main.yaml new file mode 100644 index 00000000..d2da44c2 --- /dev/null +++ b/roles/backup_create_plan/tasks/main.yaml @@ -0,0 +1,53 @@ +--- +- name: Verify required variables + block: + - name: Fail when plan variables are not defined + ansible.builtin.fail: + msg: "Required variable {{ item }} has not been defined" + when: vars[item] is undefined + loop: + - plan_name + - plan_rules + +- name: Run backup_create_plan_role + module_defaults: + group/aws: "{{ aws_setup_credentials__output }}" + block: + - name: Create or update backup vault + block: + - name: Create or update backup vault + amazon.aws.backup_vault: + state: present + backup_vault_name: "{{ vault_name }}" + encryption_key_arn: "{{ vault_encryption_key_arn | default(omit) }}" + tags: "{{ vault_tags | default(omit) }}" + register: backup_create_plan_backup_vault_result + + - name: Verify that vault has been created/updated + ansible.builtin.debug: + msg: Vault '{{ vault_name }}' successfully created/updated. + when: backup_create_plan_backup_vault_result is changed + + - name: Verify that vault already exists + ansible.builtin.debug: + msg: Vault '{{ vault_name }}' exists, no updates needed. + when: backup_create_plan_backup_vault_result is not changed + + - name: Create or update backup plan + amazon.aws.backup_plan: + state: present + backup_plan_name: "{{ plan_name }}" + rules: "{{ plan_rules }}" + advanced_backup_settings: "{{ plan_windows_vss_settings | default(omit) }}" + tags: "{{ plan_tags | default(omit) }}" + register: backup_create_plan_backup_plan_result + + - name: Verify that plan has been created/updated + ansible.builtin.debug: + msg: Plan '{{ plan_name }}' successfully created/updated. + when: backup_create_plan_backup_plan_result is changed + + - name: Verify that plan already exists + ansible.builtin.debug: + msg: Plan '{{ plan_name }}' exists, no updates needed. + when: backup_create_plan_backup_plan_result is not changed diff --git a/roles/backup_create_plan/vars/main.yaml b/roles/backup_create_plan/vars/main.yaml new file mode 100644 index 00000000..1731a2fb --- /dev/null +++ b/roles/backup_create_plan/vars/main.yaml @@ -0,0 +1,30 @@ +--- +hourly_backup: # Hourly continous backup at :15 with 7-day retention + rule_name: hourly + target_backup_vault_name: "{{ vault_name }}" + schedule_expression: "cron(15 * ? * * *)" + start_window_minutes: 60 + completion_window_minutes: 120 + enable_continuous_backup: true + lifecycle: + delete_after_days: 7 + +daily_backup: # Daily backup at 5am UTC with Amazon defaults for all other settings + rule_name: daily + target_backup_vault_name: "{{ vault_name }}" + schedule_expression: "cron(0 5 ? * * *)" + +weekly_backup: # Weekly backup on Mondays at 5am UTC with 90 day retention after quick transition to cold storage + rule_name: weekly + target_backup_vault_name: "{{ vault_name }}" + schedule_expression: "cron(0 5 ? * MON *)" + lifecycle: + delete_after_days: 91 + move_to_cold_storage_after_days: 1 + +monthly_backup: # Monthly backup at 5am UTC on 1st of month with copy to additional vault + rule_name: monthly + target_backup_vault_name: "{{ vault_name }}" + schedule_expression: "cron(0 5 1 * ? *)" + copy_actions: + - destination_backup_vault_name: "{{ copy_vault_name }}" diff --git a/roles/backup_select_resources/README.md b/roles/backup_select_resources/README.md new file mode 100644 index 00000000..0fe73045 --- /dev/null +++ b/roles/backup_select_resources/README.md @@ -0,0 +1,83 @@ +backup_select_resources +================== + +A role to configure backups for selected resources. The role requires an existing backup vault and plan, and adds selected resources to the provided plan. A set of variables for resource selections is included for use as-is or as examples for modification. This role can be combined with the `backup_create_plan` role to create or update a backup plan if one does not already exist. (see [example playbook](#create-backup-plan-and-select-resources)). + +Requirements +------------ + +AWS User Account with the following permission: + +* backup:CreateBackupSelection +* backup:DeleteBackupSelection +* backup:GetBackupPlan +* backup:GetBackupSelection +* backup:ListBackupSelections +* iam:GetRole + +Role Variables +-------------- + +* **plan_name**: (Required) The name of the backup plan you want to use for the selected resources. +* **selection_name**: (Required) The display name of the resource selection you want to back up. +* **selection_resources**: (Required) List of resources selected for backup. Can use wild cards and/or combine with selection options below to precisely restrict resources based on various conditions. See included vars for examples. +* **selection_excluded_resources**: List of resources to exclude from backup +* **selection_tags**: List of resource tags selected for backup +* **selection_conditions**: Conditions for resources to back up +* **backup_role_name**: (Required) The name of an IAM role with permissions to perform all needed backup actions for the selected resources. Alternatively, provide a new for a new IAM role which will be created with the same permissions as the AWSBackupDefaultServiceRole (note: these permissions allow backups and restores for all resources). + +### Included sample resource selection variables +These are included in vars/main.yaml for use as-is or as examples for modification. + +* **all_resources**: All AWS resources +* **all_s3_buckets** All S3 buckets +* **all_rds_db_instances**: All RDS database instances +* **tag_list_backup_or_prod**: Resources tagged {"backup": "true"} OR {"env": "prod"}, for use with the **selection_tags** role variable +* **conditions_tagged_backup_and_prod**: Resources tagged {"backup": "true"} AND {"env": "prod"}, for use with the **selection_conditions** role variable + +Dependencies +------------ + +* role: [aws_setup_credentials](../aws_setup_credentials/README.md) + +Example Playbooks +---------------- + +### Select resources + - hosts: localhost + roles: + - role: cloud.aws_ops.backup_select_resources + vars: + plan_name: my-backup-plan + selection_name: s3_buckets + selection_resources: + - "{{ all_s3_buckets }}" + +### Create backup plan and select resources + + - hosts: localhost + roles: + - role: cloud.aws_ops.backup_create_plan + plan_name: my-backup-plan + plan_rules: "{{ daily_backup }}" + + - hosts: localhost + roles: + - role: cloud.aws_ops.backup_select_resources + vars: + plan_name: my-backup-plan + selection_name: s3_buckets + selection_resources: + - "{{ all_s3_buckets }}" + +License +------- + +GNU General Public License v3.0 or later + +See [LICENCE](https://github.com/ansible-collections/cloud.aws_ops/blob/main/LICENSE) to see the full text. + +Author Information +------------------ + +* Ansible Cloud Content Team diff --git a/roles/backup_select_resources/files/backup-policy.json b/roles/backup_select_resources/files/backup-policy.json new file mode 100644 index 00000000..c8c34812 --- /dev/null +++ b/roles/backup_select_resources/files/backup-policy.json @@ -0,0 +1,12 @@ +{ + "Version": "2012-10-17", + "Statement":[ + { + "Effect": "Allow", + "Principal": { + "Service": "backup.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] +} diff --git a/roles/backup_select_resources/meta/main.yaml b/roles/backup_select_resources/meta/main.yaml new file mode 100644 index 00000000..e8b3ab42 --- /dev/null +++ b/roles/backup_select_resources/meta/main.yaml @@ -0,0 +1,3 @@ +--- +dependencies: + - role: cloud.aws_ops.aws_setup_credentials diff --git a/roles/backup_select_resources/tasks/main.yaml b/roles/backup_select_resources/tasks/main.yaml new file mode 100644 index 00000000..d263b4df --- /dev/null +++ b/roles/backup_select_resources/tasks/main.yaml @@ -0,0 +1,75 @@ +--- +- name: Fail when name, role, and resource variables are not defined + ansible.builtin.fail: + msg: "Required variable {{ item }} has not been defined" + when: vars[item] is undefined + loop: + - backup_role_name + - plan_name + - selection_name + - selection_resources + +- name: Run backup_select_resources role + module_defaults: + group/aws: "{{ aws_setup_credentials__output }}" + block: + - name: Get plan info + amazon.aws.backup_plan_info: + backup_plan_names: + - "{{ plan_name }}" + register: backup_select_resources_backup_plan_info + + - name: Fail when backup plan does not exist + ansible.builtin.fail: + msg: Backup plan {{ plan_name }} does not exist, please create or confirm plan name is correct. + when: backup_select_resources_backup_plan_info.backup_plans | length == 0 + + - name: Get provided IAM role info + community.aws.iam_role_info: + name: "{{ backup_role_name }}" + register: backup_select_resources_role_info + + - name: Create new role when IAM role does not exist + block: + - name: Create role + when: backup_select_resources_role_info.iam_roles | length == 0 + community.aws.iam_role: + name: "{{ backup_role_name }}" + state: present + assume_role_policy_document: '{{ lookup("file", "backup-policy.json") }}' + create_instance_profile: false + description: "AWS Backup Role" + managed_policy: + - arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup + wait: true + register: backup_select_resources_new_role_info + + - name: Wait for role to be created + ansible.builtin.pause: + seconds: 8 + + - name: Set backup role ARN + ansible.builtin.set_fact: + backup_select_resources_backup_role_arn: "{{ backup_select_resources_role_info.iam_roles[0].arn if backup_select_resources_new_role_info is skipped else backup_select_resources_new_role_info.arn }}" + + - name: Create or update backup selection + amazon.aws.backup_selection: + state: present + backup_plan_name: "{{ plan_name }}" + selection_name: "{{ selection_name }}" + iam_role_arn: "{{ backup_select_resources_backup_role_arn }}" + resources: "{{ selection_resources }}" + list_of_tags: "{{ selection_tags | default(omit) }}" + not_resources: "{{ selection_excluded_resources | default(omit) }}" + conditions: "{{ selection_conditions | default(omit) }}" + register: backup_select_resources_selection_result + + - name: Verify that selection has been created/updated + ansible.builtin.debug: + msg: Backup selection '{{ selection_name }}' successfully created/updated. + when: backup_select_resources_selection_result is changed + + - name: Verify that selection already exists + ansible.builtin.debug: + msg: Backup selection '{{ selection_name }}' exists, no updates needed. + when: backup_select_resources_selection_result is not changed diff --git a/roles/backup_select_resources/vars/main.yaml b/roles/backup_select_resources/vars/main.yaml new file mode 100644 index 00000000..837254ba --- /dev/null +++ b/roles/backup_select_resources/vars/main.yaml @@ -0,0 +1,19 @@ +--- +all_resources: "*" +all_s3_buckets: "arn:aws:s3:::*" +all_rds_db_instances: "arn:aws:rds:*:*:db:*" + +tag_list_backup_or_prod: # Resources tagged {"backup": "true"} OR {"env": "prod"} + - condition_type: "STRINGEQUALS" + condition_key: "backup" + condition_value: "true" + - condition_type: "StringEquals" + condition_key: "env" + condition_value: "prod" + +conditions_tagged_backup_and_prod: # Resources tagged {"backup": "true"} AND {"env": "prod"} + string_equals: + - condition_key: "aws:ResourceTag/backup" + condition_value: "true" + - condition_key: "aws:ResourceTag/env" + condition_value: "prod" diff --git a/tests/integration/constraints.txt b/tests/integration/constraints.txt new file mode 100644 index 00000000..927a6f07 --- /dev/null +++ b/tests/integration/constraints.txt @@ -0,0 +1,7 @@ +# Specifically run tests against the oldest versions that we support +boto3==1.22.0 +botocore==1.25.0 + +# AWS CLI has `botocore==` dependencies, provide the one that matches botocore +# to avoid needing to download over a years worth of awscli wheels. +awscli==1.23.0 diff --git a/tests/integration/requirements.txt b/tests/integration/requirements.txt new file mode 100644 index 00000000..1d40e8f9 --- /dev/null +++ b/tests/integration/requirements.txt @@ -0,0 +1,3 @@ +# Our code is based on the AWS SDKs +boto3 +botocore diff --git a/tests/integration/targets/test_backup_create_plan/aliases b/tests/integration/targets/test_backup_create_plan/aliases new file mode 100644 index 00000000..f73b35a4 --- /dev/null +++ b/tests/integration/targets/test_backup_create_plan/aliases @@ -0,0 +1,3 @@ +cloud/aws +role/backup_create_plan +time=3m diff --git a/tests/integration/targets/test_backup_create_plan/defaults/main.yml b/tests/integration/targets/test_backup_create_plan/defaults/main.yml new file mode 100644 index 00000000..ad1e2410 --- /dev/null +++ b/tests/integration/targets/test_backup_create_plan/defaults/main.yml @@ -0,0 +1,2 @@ +--- +aws_security_token: '{{ security_token | default(omit) }}' diff --git a/tests/integration/targets/test_backup_create_plan/tasks/main.yml b/tests/integration/targets/test_backup_create_plan/tasks/main.yml new file mode 100644 index 00000000..f226b95a --- /dev/null +++ b/tests/integration/targets/test_backup_create_plan/tasks/main.yml @@ -0,0 +1,121 @@ +--- +- name: Integration tests for 'backup_create_plan' role + module_defaults: + group/aws: + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + security_token: "{{ security_token | default(omit) }}" + region: "{{ aws_region }}" + + block: + - name: Set plan name variable + ansible.builtin.set_fact: + plan_name: "{{ resource_prefix }}-plan" + + - name: Include 'backup_create_plan' role to create plan with default vault + ansible.builtin.include_role: + name: cloud.aws_ops.backup_create_plan + vars: + plan_rules: + - "{{ daily_backup }}" + + - name: Get backup plan info + amazon.aws.backup_plan_info: + backup_plan_names: ["{{ plan_name }}"] + register: plan_create_result + + - name: Verify plan create result + ansible.builtin.assert: + that: + - plan_create_result.backup_plans | length == 1 + - plan_create_result.backup_plans[0].backup_plan_name == plan_name + - plan_create_result.backup_plans[0].backup_plan.rules | length == 1 + - plan_create_result.backup_plans[0].backup_plan.rules[0].rule_name == "daily" + - not plan_create_result.backup_plans[0].tags + + - name: Set vault name variable + ansible.builtin.set_fact: + vault_name: "{{ resource_prefix }}-vault" + + - name: Include 'backup_create_plan' role to create vault and plan + ansible.builtin.include_role: + name: cloud.aws_ops.backup_create_plan + vars: + plan_rules: + - "{{ weekly_backup }}" + + - name: Get backup vault info + amazon.aws.backup_vault_info: + backup_vault_names: ["{{ vault_name }}"] + register: vault_create_result + + - name: Verify vault create result + ansible.builtin.assert: + that: + - vault_create_result.backup_vaults | length == 1 + - vault_create_result.backup_vaults[0].backup_vault_name == vault_name + - not vault_create_result.backup_vaults[0].tags + + - name: Get backup plan info + amazon.aws.backup_plan_info: + backup_plan_names: ["{{ plan_name }}"] + register: plan_create_result + + - name: Verify plan create result + ansible.builtin.assert: + that: + - plan_create_result.backup_plans | length == 1 + - plan_create_result.backup_plans[0].backup_plan_name == plan_name + - plan_create_result.backup_plans[0].backup_plan.rules | length == 1 + - plan_create_result.backup_plans[0].backup_plan.rules[0].rule_name == "weekly" + - not plan_create_result.backup_plans[0].tags + + - name: Include 'backup_create_plan' role to update vault and plan + ansible.builtin.include_role: + name: cloud.aws_ops.backup_create_plan + vars: + vault_tags: + environment: test + plan_rules: + - "{{ hourly_backup }}" + plan_tags: + environment: test + + - name: Get backup vault info + amazon.aws.backup_vault_info: + backup_vault_names: ["{{ vault_name }}"] + register: vault_update_result + + - name: Verify vault update result + ansible.builtin.assert: + that: + - vault_update_result.backup_vaults | length == 1 + - vault_update_result.backup_vaults[0].backup_vault_name == vault_name + - vault_update_result.backup_vaults[0].tags.environment == "test" + + - name: Get backup plan info + amazon.aws.backup_plan_info: + backup_plan_names: ["{{ plan_name }}"] + register: plan_update_result + + - name: Verify plan update result + ansible.builtin.assert: + that: + - plan_update_result.backup_plans | length == 1 + - plan_update_result.backup_plans[0].backup_plan_name == plan_name + - plan_update_result.backup_plans[0].backup_plan.rules | length == 1 + - plan_update_result.backup_plans[0].backup_plan.rules[0].rule_name == "hourly" + - plan_update_result.backup_plans[0].tags.environment == "test" + + always: + - name: Delete backup plan created for test + amazon.aws.backup_plan: + backup_plan_name: "{{ plan_name }}" + state: absent + ignore_errors: true + + - name: Delete backup vault created for test + amazon.aws.backup_vault: + backup_vault_name: "{{ vault_name }}" + state: absent + ignore_errors: true diff --git a/tests/integration/targets/test_backup_select_resources/aliases b/tests/integration/targets/test_backup_select_resources/aliases new file mode 100644 index 00000000..7b05d295 --- /dev/null +++ b/tests/integration/targets/test_backup_select_resources/aliases @@ -0,0 +1,3 @@ +cloud/aws +role/backup_select_resources +time=3m diff --git a/tests/integration/targets/test_backup_select_resources/defaults/main.yml b/tests/integration/targets/test_backup_select_resources/defaults/main.yml new file mode 100644 index 00000000..bb61b33d --- /dev/null +++ b/tests/integration/targets/test_backup_select_resources/defaults/main.yml @@ -0,0 +1,8 @@ +--- +aws_security_token: '{{ security_token | default(omit) }}' +plan_name: "{{ resource_prefix }}-plan" +selection_name: "{{ resource_prefix }}-selection" +selection_two: "{{ resource_prefix }}-selection-2" +test_iam_role_name: "{{ resource_prefix }}-iam-role" +test_iam_role_name_new: "{{ resource_prefix }}-iam-role-new" +test_vault_name: "{{ resource_prefix }}-vault" diff --git a/tests/integration/targets/test_backup_select_resources/files/backup-policy.json b/tests/integration/targets/test_backup_select_resources/files/backup-policy.json new file mode 100644 index 00000000..c8c34812 --- /dev/null +++ b/tests/integration/targets/test_backup_select_resources/files/backup-policy.json @@ -0,0 +1,12 @@ +{ + "Version": "2012-10-17", + "Statement":[ + { + "Effect": "Allow", + "Principal": { + "Service": "backup.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] +} diff --git a/tests/integration/targets/test_backup_select_resources/tasks/main.yml b/tests/integration/targets/test_backup_select_resources/tasks/main.yml new file mode 100644 index 00000000..608de74e --- /dev/null +++ b/tests/integration/targets/test_backup_select_resources/tasks/main.yml @@ -0,0 +1,105 @@ +--- +- name: Integration tests for 'backup_create_vault' role + module_defaults: + group/aws: + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + security_token: "{{ security_token | default(omit) }}" + region: "{{ aws_region }}" + + block: + - name: Include 'setup.yml' file + ansible.builtin.include_tasks: setup.yml + + - name: Include 'backup_select_resources' role for all resources using new IAM role + ansible.builtin.include_role: + name: cloud.aws_ops.backup_select_resources + vars: + backup_role_name: "{{ test_iam_role_name_new }}" + selection_resources: + - "{{ all_resources }}" + + - name: Get backup selection info + amazon.aws.backup_selection_info: + backup_plan_name: "{{ plan_name }}" + register: result + + - name: Verify result + ansible.builtin.assert: + that: + - result.backup_selections | length == 1 + - result.backup_selections[0].selection_name == selection_name + - result.backup_selections[0].resources == ["*"] + + - name: Include 'backup_select_resources' role for all resources using existing IAM role + ansible.builtin.include_role: + name: cloud.aws_ops.backup_select_resources + vars: + backup_role_name: "{{ test_iam_role_name }}" + selection_resources: + - "{{ all_resources }}" + + - name: Get backup selection info + amazon.aws.backup_selection_info: + backup_plan_name: "{{ plan_name }}" + register: result + + - name: Verify result + ansible.builtin.assert: + that: + - result.backup_selections | length == 1 + - result.backup_selections[0].selection_name == selection_name + - result.backup_selections[0].resources == ["*"] + + - name: Include 'backup_select_resources' role updating selection to all s3 buckets with specified tags + ansible.builtin.include_role: + name: cloud.aws_ops.backup_select_resources + vars: + backup_role_name: "{{ test_iam_role_name }}" + selection_resources: + - "{{ all_s3_buckets }}" + selection_tags: "{{ tag_list_backup_or_prod }}" + + - name: Get updated backup selection info + amazon.aws.backup_selection_info: + backup_plan_name: "{{ plan_name }}" + register: result + + - name: Verify result + ansible.builtin.assert: + that: + - result.backup_selections | length == 1 + - result.backup_selections[0].selection_name == selection_name + - result.backup_selections[0].resources == ["arn:aws:s3:::*"] + - result.backup_selections[0].list_of_tags | length == 2 + + - name: Include 'backup_select_resources' role adding selection of all resources except rds instances with specified conditions + ansible.builtin.include_role: + name: cloud.aws_ops.backup_select_resources + vars: + backup_role_name: "{{ test_iam_role_name }}" + selection_name: "{{ selection_two }}" + selection_resources: + - "{{ all_resources }}" + selection_excluded_resources: + - "{{ all_rds_db_instances }}" + selection_conditions: "{{ conditions_tagged_backup_and_prod }}" + + - name: Get updated backup selection info + amazon.aws.backup_selection_info: + backup_plan_name: "{{ plan_name }}" + register: result + + - name: Verify result + ansible.builtin.assert: + that: + - result.backup_selections | length == 2 + - result.backup_selections[1].selection_name == "{{ selection_two }}" + - result.backup_selections[1].resources == ["*"] + - result.backup_selections[1].not_resources == ["arn:aws:rds:*:*:db:*"] + - result.backup_selections[1].list_of_tags | length == 0 + - result.backup_selections[1].conditions.string_equals | length == 2 + + always: + - name: Include 'teardown.yml' file + ansible.builtin.include_tasks: teardown.yml diff --git a/tests/integration/targets/test_backup_select_resources/tasks/setup.yml b/tests/integration/targets/test_backup_select_resources/tasks/setup.yml new file mode 100644 index 00000000..b5db7b63 --- /dev/null +++ b/tests/integration/targets/test_backup_select_resources/tasks/setup.yml @@ -0,0 +1,24 @@ +--- +- name: Create an IAM Role for backup + community.aws.iam_role: + name: "{{ test_iam_role_name }}" + state: present + assume_role_policy_document: '{{ lookup("file", "backup-policy.json") }}' + create_instance_profile: false + description: "Test Ansible AWS Backup Role" + managed_policy: + - "arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup" + wait: true + register: iam_role + +- name: Wait for role to be created + ansible.builtin.pause: + seconds: 8 + +- name: Create a backup vault and plan for test + ansible.builtin.include_role: + name: cloud.aws_ops.backup_create_plan + vars: + vault_name: "{{ test_vault_name }}" + plan_rules: + - "{{ daily_backup }}" diff --git a/tests/integration/targets/test_backup_select_resources/tasks/teardown.yml b/tests/integration/targets/test_backup_select_resources/tasks/teardown.yml new file mode 100644 index 00000000..335386a9 --- /dev/null +++ b/tests/integration/targets/test_backup_select_resources/tasks/teardown.yml @@ -0,0 +1,42 @@ +--- +- name: Delete backup selection created for test + amazon.aws.backup_selection: + state: absent + backup_plan_name: "{{ plan_name }}" + selection_name: "{{ selection_name }}" + ignore_errors: true + +- name: Delete backup selection two created for test + amazon.aws.backup_selection: + state: absent + backup_plan_name: "{{ plan_name }}" + selection_name: "{{ selection_two }}" + ignore_errors: true + +- name: Delete backup plan created for test + amazon.aws.backup_plan: + backup_plan_name: "{{ plan_name }}" + state: absent + ignore_errors: true + +- name: Delete backup vault created for test + amazon.aws.backup_vault: + backup_vault_name: "{{ test_vault_name }}" + state: absent + ignore_errors: true + +- name: Delete IAM role created for test + community.aws.iam_role: + name: "{{ test_iam_role_name }}" + state: absent + wait: true + wait_timeout: 30 + ignore_errors: true + +- name: Delete IAM role created during test + community.aws.iam_role: + name: "{{ test_iam_role_name_new }}" + state: absent + wait: true + wait_timeout: 30 + ignore_errors: true