Commit fb900e7f authored by Pierre Smeyers's avatar Pierre Smeyers
Browse files

feat: authenticate with OpenID Connect

parent 9675dd02
Loading
Loading
Loading
Loading
+21 −1
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ The AWS template uses some global configuration used throughout all jobs.
| `AWS_CLI_IMAGE`          | the Docker image used to run AWS CLI commands| `amazon/aws-cli:latest` |
| `AWS_BASE_APP_NAME`      | Base application name                  | `$CI_PROJECT_NAME` ([see GitLab doc](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html)) |
| `AWS_SCRIPTS_DIR`        | Directory where AWS scripts (deploy & cleanup) are located | `.` _(root project dir)_ |
| `AWS_OIDC_ROLE_ARN`    | Default IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/) | _none_ (disabled) |

### Secrets management

@@ -121,7 +122,14 @@ In order to be able to implement some **genericity** in your scripts and templat

#### AWS authentication

The AWS template **does not manage AWS authentication**.
The AWS template supports two kinds of authentication:

1. basic authentication with AWS access key ID & secret access key,
2. or [federated authentication using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/).

##### Basic authentication

When using basic authentication (AWS access key ID & secret access key), this template **does not manage AWS authentication**.

That means you'll have to manage AWS authentication by yourself, according to the `aws` CLI configuration options (configuration file, CLI options, environment variables).

@@ -141,6 +149,14 @@ scoped__AWS_ACCESS_KEY_ID__if__CI_ENVIRONMENT_NAME__equals__production: "<my-pro
scoped__AWS_SECRET_ACCESS_KEY__if__CI_ENVIRONMENT_NAME__equals__production: "<my-prod-secret-access-key>"
```

##### Federated authentication using OpenID Connect

If you wish to use this authentication mode, please follow carefully [the GitLab guide](https://docs.gitlab.com/ee/ci/cloud_services/aws/), 
then configure appropriately the related variables:

* `AWS_OIDC_ROLE_ARN` for any global/common access,
* `AWS_REVIEW_OIDC_ROLE_ARN` and/or `AWS_INTEG_OIDC_ROLE_ARN` and/or `AWS_STAGING_OIDC_ROLE_ARN` and/or `AWS_PROD_OIDC_ROLE_ARN` if you wish to use a separate role with any of your environments.

#### Static vs. Dynamic environment URLs

The AWS template supports two ways of defining your environments url:
@@ -185,6 +201,7 @@ Here are variables supported to configure review environments:
| Name                     | description                            | default value     |
| ------------------------ | -------------------------------------- | ----------------- |
| `AWS_REVIEW_ENABLED`     | AWS project ID for `review` env | _none_ (disabled) |
| `AWS_REVIEW_OIDC_ROLE_ARN`| IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/) on `review` env _(only define if different from global)_ | _none_ (disabled) |
| `AWS_REVIEW_APP_NAME`    | Application name for `review` env      | `"${AWS_BASE_APP_NAME}-${CI_ENVIRONMENT_SLUG}"` (ex: `myproject-review-fix-bug-12`) |
| `AWS_REVIEW_ENVIRONMENT_SCHEME`| The review environment protocol scheme.<br/>_For static environment URLs declaration_ | `https` |
| `AWS_REVIEW_ENVIRONMENT_DOMAIN`| The review environment domain.<br/>_For static environment URLs declaration_ | _none_ |
@@ -202,6 +219,7 @@ Here are variables supported to configure the integration environment:
| Name                     | description                            | default value     |
| ------------------------ | -------------------------------------- | ----------------- |
| `AWS_INTEG_ENABLED`      | AWS project ID for `integration` env | _none_ (disabled) |
| `AWS_INTEG_OIDC_ROLE_ARN`| IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/) on `integration` env _(only define if different from global)_ | _none_ (disabled) |
| `AWS_INTEG_APP_NAME`     | Application name for `integration` env | `${AWS_BASE_APP_NAME}-integration` |
| `AWS_INTEG_ENVIRONMENT_URL`| The integration environment url (ex: `https://my-application-integration.compute-1.amazonaws.com`).<br/>_For static environment URLs declaration_ | _none_ |

@@ -217,6 +235,7 @@ Here are variables supported to configure the staging environment:
| Name                     | description                            | default value     |
| ------------------------ | -------------------------------------- | ----------------- |
| `AWS_STAGING_ENABLED`    | AWS project ID for `staging` env | _none_ (disabled) |
| `AWS_STAGING_OIDC_ROLE_ARN`| IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/) on `staging` env _(only define if different from global)_ | _none_ (disabled) |
| `AWS_STAGING_APP_NAME`   | Application name for `staging` env     | `${AWS_BASE_APP_NAME}-staging` |
| `AWS_STAGING_ENVIRONMENT_URL` | The staging environment url (ex: `https://my-application-staging.compute-1.amazonaws.com`).<br/>_For static environment URLs declaration_ | _none_ |

@@ -231,6 +250,7 @@ Here are variables supported to configure the production environment:
| Name                      | description                            | default value     |
| ------------------------- | -------------------------------------- | ----------------- |
| `AWS_PROD_ENABLED`        | AWS project ID for `production` env | _none_ (disabled) |
| `AWS_PROD_OIDC_ROLE_ARN`| IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/) on `production` env _(only define if different from global)_ | _none_ (disabled) |
| `AWS_PROD_APP_NAME`       | Application name for `production` env  | `$AWS_BASE_APP_NAME` |
| `AWS_PROD_ENVIRONMENT_URL`| The production environment url (ex: `https://my-application.compute-1.amazonaws.com`).<br/>_For static environment URLs declaration_ | _none_ |
| `AUTODEPLOY_TO_PROD`      | Set this variable to auto-deploy to production. If not set deployment to production will be `manual` (default behaviour). | _none_ (disabled) |
+25 −0
Original line number Diff line number Diff line
@@ -15,6 +15,11 @@
      "default": "$CI_PROJECT_NAME",
      "advanced": true
    },
    {
      "name": "AWS_OIDC_ROLE_ARN",
      "description": "Default IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/)",
      "advanced": true
    },
    {
      "name": "AWS_SCRIPTS_DIR",
      "description": "Directory where AWS scripts (deploy & cleanup) are located",
@@ -34,6 +39,11 @@
          "description": "The application name for review env (only define if different from global)",
          "advanced": true
        },
        {
          "name": "AWS_REVIEW_OIDC_ROLE_ARN",
          "description": "IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/) on `review` env _(only define if different from global)_",
          "advanced": true
        },
        {
          "name": "AWS_REVIEW_ENVIRONMENT_SCHEME",
          "description": "The review environment protocol scheme",
@@ -56,6 +66,11 @@
          "description": "The application name for integration env (only define if different from global)",
          "advanced": true
        },
        {
          "name": "AWS_INTEG_OIDC_ROLE_ARN",
          "description": "IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/) on `integration` env _(only define if different from global)_",
          "advanced": true
        },
        {
          "name": "AWS_INTEG_ENVIRONMENT_URL",
          "type": "url",
@@ -74,6 +89,11 @@
          "description": "The application name for staging env (only define if different from global)",
          "advanced": true
        },
        {
          "name": "AWS_STAGING_OIDC_ROLE_ARN",
          "description": "IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/) on `staging` env _(only define if different from global)_",
          "advanced": true
        },
        {
          "name": "AWS_STAGING_ENVIRONMENT_URL",
          "type": "url",
@@ -92,6 +112,11 @@
          "description": "The application name for production env (only define if different from global)",
          "advanced": true
        },
        {
          "name": "AWS_PROD_OIDC_ROLE_ARN",
          "description": "IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/) on `production` env _(only define if different from global)_",
          "advanced": true
        },
        {
          "name": "AWS_PROD_ENVIRONMENT_URL",
          "type": "url",
+20 −0
Original line number Diff line number Diff line
@@ -258,6 +258,20 @@ stages:
    fi
  }

  function auth() {
    oidc_role_arn="$1"
    if [[ "$oidc_role_arn" ]]
    then
      log_info "Obtaining temporary credentials with OpenID connect..."
      # see: https://docs.gitlab.com/ee/ci/cloud_services/aws/
      # shellcheck disable=SC2046,SC2183
      export $(printf "AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s AWS_SESSION_TOKEN=%s" $(aws sts assume-role-with-web-identity --role-arn "$oidc_role_arn" --role-session-name "GitLabRunner-${CI_PROJECT_ID}-${CI_PIPELINE_ID}" --web-identity-token "$CI_JOB_JWT_V2" --duration-seconds 3600 --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' --output text))
      aws sts get-caller-identity
    else
      log_info "Implicit authentication with AWS access key ID & secret access key..."
    fi
  }

  # application deployment function
  function deploy() {
    export env=$1
@@ -337,6 +351,7 @@ stages:
  before_script:
    - *aws-scripts
    - install_ca_certs "${CUSTOM_CA_CERTS:-$DEFAULT_CA_CERTS}"
    - auth "${ENV_OIDC_ROLE_ARN:-${AWS_OIDC_ROLE_ARN}}"

# Deploy job prototype
# Can be extended to define a concrete environment
@@ -387,6 +402,7 @@ aws-review:
    ENV_TYPE: review
    ENV_APP_NAME: "$AWS_REVIEW_APP_NAME"
    ENV_URL: "${AWS_REVIEW_ENVIRONMENT_SCHEME}://${CI_PROJECT_NAME}-${CI_ENVIRONMENT_SLUG}.${AWS_REVIEW_ENVIRONMENT_DOMAIN}"
    ENV_OIDC_ROLE_ARN: "$AWS_REVIEW_OIDC_ROLE_ARN"
  environment:
    name: review/$CI_COMMIT_REF_NAME
    on_stop: aws-cleanup-review
@@ -407,6 +423,7 @@ aws-cleanup-review:
  variables:
    ENV_TYPE: review
    ENV_APP_NAME: "$AWS_REVIEW_APP_NAME"
    ENV_OIDC_ROLE_ARN: "$AWS_REVIEW_OIDC_ROLE_ARN"
  environment:
    name: review/$CI_COMMIT_REF_NAME
    action: stop
@@ -427,6 +444,7 @@ aws-integration:
    ENV_TYPE: integration
    ENV_APP_NAME: "$AWS_INTEG_APP_NAME"
    ENV_URL: "${AWS_INTEG_ENVIRONMENT_URL}"
    ENV_OIDC_ROLE_ARN: "$AWS_INTEG_OIDC_ROLE_ARN"
  environment:
    name: integration
  resource_group: integration
@@ -441,6 +459,7 @@ aws-staging:
    ENV_TYPE: staging
    ENV_APP_NAME: "$AWS_STAGING_APP_NAME"
    ENV_URL: "${AWS_STAGING_ENVIRONMENT_URL}"
    ENV_OIDC_ROLE_ARN: "$AWS_STAGING_OIDC_ROLE_ARN"
  environment:
    name: staging
  resource_group: staging
@@ -457,6 +476,7 @@ aws-production:
    ENV_APP_SUFFIX: "" # no suffix for prod
    ENV_APP_NAME: "$AWS_PROD_APP_NAME"
    ENV_URL: "${AWS_PROD_ENVIRONMENT_URL}"
    ENV_OIDC_ROLE_ARN: "$AWS_PROD_OIDC_ROLE_ARN"
  environment:
    name: production
  resource_group: production