diff --git a/.gitignore b/.gitignore index 3377d94390180530dfaa2f15939b6f2ede90f68d..387cc3095f6697c7175df47c85169052726ca547 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,4 @@ reports/ Ansible/*.crt Ansible/*.csr Ansible/*.key +Ansible/collections diff --git a/Ansible/ansible.cfg b/Ansible/ansible.cfg index 45588da8bc3c425823f710a6751b49a02b148aba..1c8279076de7298ff412fadb5dda6b5d0b8fd145 100644 --- a/Ansible/ansible.cfg +++ b/Ansible/ansible.cfg @@ -1,5 +1,6 @@ [defaults] callback_enabled = ansible.posix.profile_tasks, ansible.posix.timer +collections_path = {{CWD}}/collections deprecation_warnings = True fact_caching = jsonfile fact_caching_connection = ~/.ansible/facts diff --git a/Ansible/collections/.gitkeep b/Ansible/collections/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Ansible/project_ci_aws_creds.yaml b/Ansible/project_ci_aws_creds.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8c52376d5051806fd92f01105d7a112c302b9b84 --- /dev/null +++ b/Ansible/project_ci_aws_creds.yaml @@ -0,0 +1,208 @@ +--- +- name: Generate AWS credentials for a GitLab project CI + hosts: localhost + gather_facts: false + become: false + vars_prompt: + - name: project_full_name + # yamllint disable-line rule:line-length + prompt: Full name for the GitLab project (namespace included, eg. group/project) + private: false + - name: aws_region + prompt: List of AWS regions to limit the IAM user (comma separated) + default: us-east-1 + private: false + vars: + aws_username: "{{ project_name }}-ci" + aws_limit_policy: + Statement: + - Sid: LimitIP + Effect: Deny + Action: "*" + Resource: "*" + Condition: + ForAnyValue:NotIpAddress: + aws:SourceIp: '{{ shore_ip_addresses }}' + - Sid: LimitRegion + Effect: Deny + NotAction: + - cloudfront:* + - iam:* + - route53:* + - support:* + Resource: "*" + Condition: + ForAnyValue:StringNotEqualsIfExists: + aws:RequestedRegion: '{{ aws_region.split(",") }}' + aws_resourcegroup_policy: + Version: 2012-10-17 + Statement: + - Sid: ResourceGroupFullAccess + Effect: Allow + Action: "resource-groups:*" + Resource: "*" + gitlab_base_url: "{{ lookup('env', 'GITLAB_BASE_URL') }}" + gitlab_token: "{{ lookup('env', 'GITLAB_TOKEN') }}" + project_id: '{{ project_dict["id"] }}' + project_name: '{{ project_dict["path"] }}' + shore_ip_addresses: + - "{{ lookup('community.general.dig', 'ns1.shore.co.il') }}" + - "{{ lookup('community.general.dig', 'ns4.shore.co.il') }}" + tasks: + - name: Search for GitLab projects with the same name + ansible.builtin.uri: + headers: &gitlab_headers + Authorization: Bearer {{ gitlab_token }} + method: GET + # yamllint disable-line rule:line-length + url: "{{ gitlab_base_url }}/search?scope=projects&search={{ project_full_name.split('/')[1] }}" + register: search_projects + + - name: Find the right GitLab project + ansible.builtin.set_fact: + project_dict: >- + {{ + search_projects.json| + selectattr("path_with_namespace", "equalto", project_full_name)| + first + }} + + - name: Create a full access resource group IAM policy + community.aws.iam_managed_policy: + policy: '{{ aws_resourcegroup_policy|to_json }}' + policy_description: Provides full access to AWS Resource Groups + policy_name: &rg_policy_name AWSResourceGroupsFullAccess + state: present + + - name: Create the IAM user + community.aws.iam_user: + managed_policies: + - *rg_policy_name + name: "{{ aws_username }}" + purge_policies: false + state: present + tags: + Project: '{{ project_name }}' + + - name: Attach an inline policy to limit the IAM user + community.aws.iam_policy: + iam_name: '{{ aws_username }}' + iam_type: user + policy_json: '{{ aws_limit_policy|to_json }}' + policy_name: '{{ aws_username }}-limit' + skip_duplicates: true + state: present + + # yamllint disable-line rule:line-length + - name: Create access key for the IAM user (a new one every time, task will always change) + community.aws.iam_access_key: + active: true + rotate_keys: true + state: present + user_name: '{{ aws_username }}' + register: aws_access_key + + - name: Get the GitLab project CI variables + ansible.builtin.uri: + headers: *gitlab_headers + method: GET + url: "{{ gitlab_base_url }}/projects/{{ project_id }}/variables" + changed_when: false + register: project_vars + + - name: Create the access key ID GitLab CI variable + # yamllint disable-line rule:line-length + when: project_vars.json|selectattr("key", "equalto", "AWS_ACCESS_KEY_ID")|length == 0 + ansible.builtin.uri: + body: + environment_scope: "*" + key: AWS_ACCESS_KEY_ID + masked: false + protected: false + value: '{{ aws_access_key.access_key_id }}' + variable_key: env_var + body_format: form-urlencoded + headers: *gitlab_headers + method: POST + status_code: 201 + url: "{{ gitlab_base_url }}/projects/{{ project_id }}/variables" + + - name: Update the access key ID GitLab CI variable (will always change) + # yamllint disable-line rule:line-length + when: project_vars.json|selectattr("key", "equalto", "AWS_ACCESS_KEY_ID")|length == 1 + changed_when: true + ansible.builtin.uri: + body: + environment_scope: "*" + masked: false + protected: false + value: '{{ aws_access_key.access_key_id }}' + variable_key: env_var + body_format: form-urlencoded + headers: *gitlab_headers + method: PUT + status_code: 200 + # yamllint disable-line rule:line-length + url: "{{ gitlab_base_url }}/projects/{{ project_id }}/variables/AWS_ACCESS_KEY_ID" + + - name: Create the secret access key GitLab CI variable + # yamllint disable-line rule:line-length + when: project_vars.json|selectattr("key", "equalto", "AWS_SECRET_ACCESS_KEY")|length == 0 + ansible.builtin.uri: + body: + environment_scope: "*" + key: AWS_SECRET_ACCESS_KEY + masked: true + protected: false + value: '{{ aws_access_key.secret_access_key }}' + variable_key: env_var + body_format: form-urlencoded + headers: *gitlab_headers + method: POST + status_code: 201 + url: "{{ gitlab_base_url }}/projects/{{ project_id }}/variables" + + - name: Update the secret access key GitLab CI variable (will always change) + # yamllint disable-line rule:line-length + when: project_vars.json|selectattr("key", "equalto", "AWS_SECRET_ACCESS_KEY")|length == 1 + changed_when: true + ansible.builtin.uri: + body: + environment_scope: "*" + masked: true + protected: false + value: '{{ aws_access_key.secret_access_key }}' + variable_key: env_var + body_format: form-urlencoded + headers: *gitlab_headers + method: PUT + status_code: 200 + # yamllint disable-line rule:line-length + url: "{{ gitlab_base_url }}/projects/{{ project_id }}/variables/AWS_SECRET_ACCESS_KEY" + + - name: Find all of the IAM access keys for the user + community.aws.iam_access_key_info: + user_name: '{{ aws_username }}' + register: aws_access_keys + + - name: Remove the old IAM access keys + when: aws_access_keys.access_keys|length > 1 + community.aws.iam_access_key: + id: '{{ access_key.access_key_id }}' + state: absent + user_name: '{{ aws_username }}' + vars: + # yamllint disable rule:line-length + access_key: >- + {{ + aws_access_keys.access_keys| + rejectattr("access_key_id", "equalto", aws_access_key.access_key_id)| + first + }} + # yamllint enable rule:line-length + + - name: AWS console URL for modifying the IAM user + debug: + # yamllint disable-line rule:line-length + msg: https://us-east-1.console.aws.amazon.com/iam/home#/users/{{ aws_username }} + verbosity: 0 diff --git a/Ansible/requirements.yml b/Ansible/requirements.yml new file mode 100644 index 0000000000000000000000000000000000000000..f56a5b3739c34fc2778ec17cbcfc9ffe025f066e --- /dev/null +++ b/Ansible/requirements.yml @@ -0,0 +1,6 @@ +--- +collections: + - name: amazon.aws + version: '>=3.2.0' + - name: community.aws + version: '>=3.2.0'