diff --git a/docs/2.0/docs/pipelines/concepts/cloud-auth.md b/docs/2.0/docs/pipelines/concepts/cloud-auth.md index dfa7a8fff..c25202772 100644 --- a/docs/2.0/docs/pipelines/concepts/cloud-auth.md +++ b/docs/2.0/docs/pipelines/concepts/cloud-auth.md @@ -71,3 +71,60 @@ The AWS IAM Role in the Management Account must have permissions to provision ne Each child account (e.g., `dev`, `stage`, `prod`, etc.) contains an AWS IAM role that Pipelines can assume from GitHub Actions or GitLab CI using OIDC. This role is automatically provisioned during the [account baseline process](/2.0/docs/accountfactory/guides/vend-aws-account). Once the role is established in the child account, users can submit pull requests/merge requests to add, modify, or delete resources in that account. When a pull request/merge request is created or synchronized, or when changes are pushed to the `main` branch, Pipelines detects the changes, maps them to the appropriate account, assumes the role in the child account, and executes a `terragrunt plan` (for pull requests/merge requests) or `terragrunt apply` (for pushes to `main`). + +### Fundamentals of OIDC for Publicly Available and Private CI/CD platforms + +### JWT Token Issuers +A JWT token is a base64-encoded JSON object that contains three parts: a header, a payload, and a signature. The header typically contains metadata about the token, such as the algorithm used to sign it. The payload contains the claims or assertions made by the issuer, such as the subject (user), audience (intended recipient), and expiration time. The signature is used to verify that the token was issued by a trusted authority and has not been tampered with. + +Critically, the issuer is a URL that is both specified inside the token, and is used by consumers of the token to fetch the public key used to validate the signature of that same token. Assuming the public key is fetched via HTTPS, there is a valid trust chain that the token was in fact issued by the expected issuer and you have typical cryptographic guarantees it wasn't substituted or tampered with. + +Typically the issuer is the hostname of the CI/CD platform, such as `https://gitlab.com`, and thus oidc configuration (and public keys) can be fetched from the publicly available route, `https://gitlab.com/.well-known/openid-configuration` etc. + +If, however, your CI/CD platform is hosted privately, you will need to host the public key and OIDC configuration in a publicly accessible location, such as an S3 bucket, and update the issuer in your CI/CD configuration to point to that location. The diagrams below illustrate both approaches - fetching the keys directly from your CI/CD platform via a public route, or fetching the keys from a public S3 bucket. + + +#### Publicly Available CI/CD Platforms +```mermaid +sequenceDiagram + participant SCM as SCM (GitLab/GitHub etc.) + participant SCMPublicRoute as SCM Hostname e.g. gitlab.com + participant AWSIdP as AWS IdP & STS + + SCM->>SCM: Generate a public/private key pair + SCM->>SCM: Generate a JWT and sign with the private key + SCM->AWSIdP: Send JWT to AWS requesting a role + AWSIdP->>SCMPublicRoute: Fetch public key via HTTPS
(which validates that the SCM is who it says it is) + SCMPublicRoute->>AWSIdP: Return the public key + AWSIdP->>AWSIdP: Validate signature on JWT using public key to validate that it was generated by the Issuer + AWSIdP->>AWSIdP: Inspect JWT Content and ensure it passes trust policies + AWSIdP->>SCM: Return temporary tokens for the role requested + +``` + +#### Non-Publicly Available CI/CD Platforms + +This diagram follows the [recommended approach](https://docs.gitlab.com/ci/cloud_services/aws/#configure-a-non-public-gitlab-instance) from GitLab for private CI/CD platform instances. The guidance is to host the public key in a publicly accessible S3 bucket and update the issuer in the CI/CD configuration. + +A common alternative approach to re-hosting the public key and OIDC configuration is to update the application firewalls to specifically allow requests to the `.well-known/openid-configuration` endpoint and the JWKS endpoint from the AWS IdP. + +```mermaid +sequenceDiagram + participant SCM as SCM (GitLab/GitHub etc.) + participant SCMPublicRoute as Public S3 Bucket (e.g. acme-public.s3.com) + participant AWSIdP as AWS IdP & STS + + + SCM->>SCM: Generate a public/private key pair + SCM->>SCMPublicRoute: Publish public key to S3 + SCM->>AwsIdP: Update provider URL in AWS IdP to S3 bucket public URL + SCM->>SCM: Update issuer to hostname of S3 bucket public URL + SCM->>SCM: Generate a JWT with updated issuer and sign with the private key + SCM->>AWSIdP: Send JWT to AWS requesting a role + AWSIdP->>SCMPublicRoute: Fetch public key via HTTPS
(HTTPS is important as it validates that the host is in fact the issuer) + SCMPublicRoute->>AWSIdP: Return the public key + AWSIdP->>AWSIdP: Validate signature on JWT using public key to validate that it was generated by the Issuer + AWSIdP->>AWSIdP: Inspect JWT Content and ensure it passes trust policies + AWSIdP->>SCM: Return temporary tokens for the role requested + +```