Skip to content
Snippets Groups Projects
Commit 2638eac3 authored by nimrod's avatar nimrod
Browse files

Ansible playbook: project_ci_aws_creds.yaml

An Ansible playbook to create an IAM user for GitLab projects' CI. Also,
rotates the IAM access keys, sets the CI variables for the access key,
attaches an inline policy to limit the user by IP and requested region.
Lastly, create a policy with full access to Resource Groups because I
usually create one for each deployment but there isn't such an AWS
managed policy.
parent b52cae78
No related branches found
No related tags found
No related merge requests found
Pipeline #2790 failed
......@@ -61,3 +61,4 @@ reports/
Ansible/*.crt
Ansible/*.csr
Ansible/*.key
Ansible/collections
[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
......
---
- 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
---
collections:
- name: amazon.aws
version: '>=3.2.0'
- name: community.aws
version: '>=3.2.0'
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment