|
|
|
@ -17,9 +17,9 @@ topics:
|
|
|
|
|
|
|
|
|
|
## Overview of OpenID Connect
|
|
|
|
|
|
|
|
|
|
{% data variables.product.prodname_actions %} workflows are often designed to access a cloud provider (such as AWS, Azure, GCP, or HashiCorp Vault) in order to deploy software or use the cloud's services. Before the workflow can access these resources, it will supply credentials, such as a password or token, to the cloud provider. These credentials are usually stored as a secret in {% data variables.product.prodname_dotcom %}, and the workflow presents this secret to the cloud provider every time it runs.
|
|
|
|
|
{% data variables.product.prodname_actions %} workflows are often designed to access a cloud provider (such as AWS, Azure, GCP, or HashiCorp Vault) in order to deploy software or use the cloud's services. Before the workflow can access these resources, it will supply credentials, such as a password or token, to the cloud provider. These credentials are usually stored as a secret in {% data variables.product.prodname_dotcom %}, and the workflow presents this secret to the cloud provider every time it runs.
|
|
|
|
|
|
|
|
|
|
However, using hardcoded secrets requires you to create credentials in the cloud provider and then duplicate them in {% data variables.product.prodname_dotcom %} as a secret.
|
|
|
|
|
However, using hardcoded secrets requires you to create credentials in the cloud provider and then duplicate them in {% data variables.product.prodname_dotcom %} as a secret.
|
|
|
|
|
|
|
|
|
|
With OpenID Connect (OIDC), you can take a different approach by configuring your workflow to request a short-lived access token directly from the cloud provider. Your cloud provider also needs to support OIDC on their end, and you must configure a trust relationship that controls which workflows are able to request the access tokens. Providers that currently support OIDC include Amazon Web Services, Azure, Google Cloud Platform, and HashiCorp Vault, among others.
|
|
|
|
|
|
|
|
|
@ -27,7 +27,7 @@ With OpenID Connect (OIDC), you can take a different approach by configuring you
|
|
|
|
|
|
|
|
|
|
By updating your workflows to use OIDC tokens, you can adopt the following good security practices:
|
|
|
|
|
|
|
|
|
|
- **No cloud secrets**: You won't need to duplicate your cloud credentials as long-lived {% data variables.product.prodname_dotcom %} secrets. Instead, you can configure the OIDC trust on your cloud provider, and then update your workflows to request a short-lived access token from the cloud provider through OIDC.
|
|
|
|
|
- **No cloud secrets**: You won't need to duplicate your cloud credentials as long-lived {% data variables.product.prodname_dotcom %} secrets. Instead, you can configure the OIDC trust on your cloud provider, and then update your workflows to request a short-lived access token from the cloud provider through OIDC.
|
|
|
|
|
- **Authentication and authorization management**: You have more granular control over how workflows can use credentials, using your cloud provider's authentication (authN) and authorization (authZ) tools to control access to cloud resources.
|
|
|
|
|
- **Rotating credentials**: With OIDC, your cloud provider issues a short-lived access token that is only valid for a single job, and then automatically expires.
|
|
|
|
|
|
|
|
|
@ -48,7 +48,7 @@ When you configure your cloud to trust {% data variables.product.prodname_dotcom
|
|
|
|
|
|
|
|
|
|
- Before granting an access token, your cloud provider checks that the [`subject`](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) and other claims used to set conditions in its trust settings match those in the request's JSON Web Token (JWT). As a result, you must take care to correctly define the _subject_ and other conditions in your cloud provider.
|
|
|
|
|
- The OIDC trust configuration steps and the syntax to set conditions for cloud roles (using _Subject_ and other claims) will vary depending on which cloud provider you're using. For some examples, see "[Example subject claims](#example-subject-claims)."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Understanding the OIDC token
|
|
|
|
|
|
|
|
|
|
Each job requests an OIDC token from {% data variables.product.prodname_dotcom %}'s OIDC provider, which responds with an automatically generated JSON web token (JWT) that is unique for each workflow job where it is generated. When the job runs, the OIDC token is presented to the cloud provider. To validate the token, the cloud provider checks if the OIDC token's subject and other claims are a match for the conditions that were preconfigured on the cloud role's OIDC trust definition.
|
|
|
|
@ -92,51 +92,58 @@ The following example OIDC token uses a subject (`sub`) that references a job en
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
To see all the claims supported by {% data variables.product.prodname_dotcom %}'s OIDC provider, review the `claims_supported` entries at
|
|
|
|
|
To see all the claims supported by {% data variables.product.prodname_dotcom %}'s OIDC provider, review the `claims_supported` entries at
|
|
|
|
|
{% ifversion ghes %}`https://HOSTNAME/_services/token/.well-known/openid-configuration`{% else %}https://token.actions.githubusercontent.com/.well-known/openid-configuration{% endif %}.
|
|
|
|
|
|
|
|
|
|
The token includes the standard audience, issuer, and subject claims:
|
|
|
|
|
|
|
|
|
|
| Claim | Description |
|
|
|
|
|
| ----------- | ---------------------- |
|
|
|
|
|
| `aud`| _(Audience)_ By default, this is the URL of the repository owner, such as the organization that owns the repository. This is the only claim that can be customized. You can set a custom audience with a toolkit command: [`core.getIDToken(audience)`](https://www.npmjs.com/package/@actions/core/v/1.6.0) |
|
|
|
|
|
| `iss`| _(Issuer)_ The issuer of the OIDC token: {% ifversion ghes %}`https://HOSTNAME/_services/token`{% else %}`https://token.actions.githubusercontent.com`{% endif %} |
|
|
|
|
|
| `aud`| _(Audience)_ By default, this is the URL of the repository owner, such as the organization that owns the repository. This is the only claim that can be customized. You can set a custom audience with a toolkit command: [`core.getIDToken(audience)`](https://www.npmjs.com/package/@actions/core/v/1.6.0) |
|
|
|
|
|
| `iss`| _(Issuer)_ The issuer of the OIDC token: {% ifversion ghes %}`https://HOSTNAME/_services/token`{% else %}`https://token.actions.githubusercontent.com`{% endif %} |
|
|
|
|
|
| `sub`| _(Subject)_ Defines the subject claim that is to be validated by the cloud provider. This setting is essential for making sure that access tokens are only allocated in a predictable way.|
|
|
|
|
|
|
|
|
|
|
The OIDC token also includes additional standard claims:
|
|
|
|
|
|
|
|
|
|
| Claim | Description |
|
|
|
|
|
| ----------- | ---------------------- |
|
|
|
|
|
| `alg`| _(Algorithm)_ The algorithm used by the OIDC provider. |
|
|
|
|
|
| `exp`| _(Expires at)_ Identifies the expiry time of the JWT. |
|
|
|
|
|
| `iat`| _(Issued at)_ The time when the JWT was issued. |
|
|
|
|
|
| `jti`| _(JWT token identifier)_ Unique identifier for the OIDC token. |
|
|
|
|
|
| `kid`| _(Key identifier)_ Unique key for the OIDC token. |
|
|
|
|
|
| `nbf`| _(Not before)_ JWT is not valid for use before this time. |
|
|
|
|
|
| `typ`| _(Type)_ Describes the type of token. This is a JSON Web Token (JWT). |
|
|
|
|
|
| `alg`| _(Algorithm)_ The algorithm used by the OIDC provider. |
|
|
|
|
|
| `exp`| _(Expires at)_ Identifies the expiry time of the JWT. |
|
|
|
|
|
| `iat`| _(Issued at)_ The time when the JWT was issued. |
|
|
|
|
|
| `jti`| _(JWT token identifier)_ Unique identifier for the OIDC token. |
|
|
|
|
|
| `kid`| _(Key identifier)_ Unique key for the OIDC token. |
|
|
|
|
|
| `nbf`| _(Not before)_ JWT is not valid for use before this time. |
|
|
|
|
|
| `typ`| _(Type)_ Describes the type of token. This is a JSON Web Token (JWT). |
|
|
|
|
|
|
|
|
|
|
The token also includes custom claims provided by {% data variables.product.prodname_dotcom %}:
|
|
|
|
|
|
|
|
|
|
| Claim | Description |
|
|
|
|
|
| ----------- | ---------------------- |
|
|
|
|
|
| `actor`| The personal account that initiated the workflow run. |
|
|
|
|
|
| `actor`| The personal account that initiated the workflow run. |
|
|
|
|
|
| `actor_id`| The ID of personal account that initiated the workflow run. |
|
|
|
|
|
| `base_ref`| The target branch of the pull request in a workflow run. |
|
|
|
|
|
| `environment`| The name of the environment used by the job. |
|
|
|
|
|
| `event_name`| The name of the event that triggered the workflow run. |
|
|
|
|
|
| `head_ref`| The source branch of the pull request in a workflow run. |
|
|
|
|
|
| `job_workflow_ref`| This is the ref path to the reusable workflow used by this job. For more information, see "["Using OpenID Connect with reusable workflows"](/actions/deployment/security-hardening-your-deployments/using-openid-connect-with-reusable-workflows)." |
|
|
|
|
|
| `ref`| _(Reference)_ The git ref that triggered the workflow run. |
|
|
|
|
|
| `ref_type`| The type of `ref`, for example: "branch". |
|
|
|
|
|
| `repository_visibility` | The visibility of the repository where the workflow is running. Accepts the following values: `internal`, `private`, or `public`. |
|
|
|
|
|
| `repository`| The repository from where the workflow is running. |
|
|
|
|
|
| `base_ref`| The target branch of the pull request in a workflow run. |
|
|
|
|
|
| `environment`| The name of the environment used by the job. |
|
|
|
|
|
| `event_name`| The name of the event that triggered the workflow run. |
|
|
|
|
|
| `head_ref`| The source branch of the pull request in a workflow run. |
|
|
|
|
|
| `job_workflow_ref`| For jobs using a reusable workflow, the ref path to the reusable workflow. For more information, see "[Using OpenID Connect with reusable workflows](/actions/deployment/security-hardening-your-deployments/using-openid-connect-with-reusable-workflows)." |
|
|
|
|
|
{%- ifversion actions-oidc-custom-claims %}
|
|
|
|
|
| `job_workflow_sha`| {% data reusables.actions.job-workflow-sha-description %} |
|
|
|
|
|
{%- endif %}
|
|
|
|
|
| `ref`| _(Reference)_ The git ref that triggered the workflow run. |
|
|
|
|
|
| `ref_type`| The type of `ref`, for example: "branch". |
|
|
|
|
|
| `repository_visibility` | The visibility of the repository where the workflow is running. Accepts the following values: `internal`, `private`, or `public`. |
|
|
|
|
|
| `repository`| The repository from where the workflow is running. |
|
|
|
|
|
| `repository_id`| The ID of the repository from where the workflow is running. |
|
|
|
|
|
| `repository_owner`| The name of the organization in which the `repository` is stored. |
|
|
|
|
|
| `repository_owner`| The name of the organization in which the `repository` is stored. |
|
|
|
|
|
| `repository_owner_id`| The ID of the organization in which the `repository` is stored. |
|
|
|
|
|
| `run_id`| The ID of the workflow run that triggered the workflow. |
|
|
|
|
|
| `run_number`| The number of times this workflow has been run. |
|
|
|
|
|
| `run_attempt`| The number of times this workflow run has been retried. |
|
|
|
|
|
| `workflow`| The name of the workflow. |
|
|
|
|
|
| `run_id`| The ID of the workflow run that triggered the workflow. |
|
|
|
|
|
| `run_number`| The number of times this workflow has been run. |
|
|
|
|
|
| `run_attempt`| The number of times this workflow run has been retried. |
|
|
|
|
|
| `workflow`| The name of the workflow. |
|
|
|
|
|
{%- ifversion actions-oidc-custom-claims %}
|
|
|
|
|
| `workflow_ref`| {% data reusables.actions.workflow-ref-description %} |
|
|
|
|
|
| `workflow_sha`| {% data reusables.actions.workflow-sha-description %} |
|
|
|
|
|
{%- endif %}
|
|
|
|
|
|
|
|
|
|
### Defining trust conditions on cloud roles using OIDC claims
|
|
|
|
|
|
|
|
|
@ -168,7 +175,7 @@ You can configure a subject that filters for a specific [environment](/actions/d
|
|
|
|
|
|
|
|
|
|
| | |
|
|
|
|
|
| ------ | ----------- |
|
|
|
|
|
| Syntax: | `repo:<orgName/repoName>:environment:<environmentName>` |
|
|
|
|
|
| Syntax: | `repo:<orgName/repoName>:environment:<environmentName>` |
|
|
|
|
|
| Example:| `repo:octo-org/octo-repo:environment:Production` |
|
|
|
|
|
|
|
|
|
|
#### Filtering for `pull_request` events
|
|
|
|
@ -179,7 +186,7 @@ You can configure a subject that filters for the [`pull_request`](/actions/learn
|
|
|
|
|
|
|
|
|
|
| | |
|
|
|
|
|
| ------ | ----------- |
|
|
|
|
|
| Syntax: | `repo:<orgName/repoName>:pull_request` |
|
|
|
|
|
| Syntax: | `repo:<orgName/repoName>:pull_request` |
|
|
|
|
|
| Example:| `repo:octo-org/octo-repo:pull_request` |
|
|
|
|
|
|
|
|
|
|
#### Filtering for a specific branch
|
|
|
|
@ -190,7 +197,7 @@ You can configure a subject that filters for a specific branch name. In this exa
|
|
|
|
|
|
|
|
|
|
| | |
|
|
|
|
|
| ------ | ----------- |
|
|
|
|
|
| Syntax: | `repo:<orgName/repoName>:ref:refs/heads/branchName` |
|
|
|
|
|
| Syntax: | `repo:<orgName/repoName>:ref:refs/heads/branchName` |
|
|
|
|
|
| Example:| `repo:octo-org/octo-repo:ref:refs/heads/demo-branch` |
|
|
|
|
|
|
|
|
|
|
#### Filtering for a specific tag
|
|
|
|
@ -201,7 +208,7 @@ You can create a subject that filters for specific tag. In this example, the wor
|
|
|
|
|
|
|
|
|
|
| | |
|
|
|
|
|
| ------ | ----------- |
|
|
|
|
|
| Syntax: | `repo:<orgName/repoName>:ref:refs/tags/<tagName>` |
|
|
|
|
|
| Syntax: | `repo:<orgName/repoName>:ref:refs/tags/<tagName>` |
|
|
|
|
|
| Example:| `repo:octo-org/octo-repo:ref:refs/tags/demo-tag` |
|
|
|
|
|
|
|
|
|
|
### Configuring the subject in your cloud provider
|
|
|
|
@ -210,7 +217,7 @@ To configure the subject in your cloud provider's trust relationship, you must a
|
|
|
|
|
|
|
|
|
|
| | |
|
|
|
|
|
| ------ | ----------- |
|
|
|
|
|
| Amazon Web Services | `"{% ifversion ghes %}HOSTNAME/_services/token{% else %}token.actions.githubusercontent.com{% endif %}:sub": "repo:octo-org/octo-repo:ref:refs/heads/demo-branch"` |
|
|
|
|
|
| Amazon Web Services | `"{% ifversion ghes %}HOSTNAME/_services/token{% else %}token.actions.githubusercontent.com{% endif %}:sub": "repo:octo-org/octo-repo:ref:refs/heads/demo-branch"` |
|
|
|
|
|
| Azure| `repo:octo-org/octo-repo:ref:refs/heads/demo-branch` |
|
|
|
|
|
| Google Cloud Platform| `(assertion.sub=='repo:octo-org/octo-repo:ref:refs/heads/demo-branch')` |
|
|
|
|
|
| HashiCorp Vault| `bound_subject="repo:octo-org/octo-repo:ref:refs/heads/demo-branch" ` |
|
|
|
|
@ -225,7 +232,7 @@ You could also use a `curl` command to request the JWT, using the following envi
|
|
|
|
|
|
|
|
|
|
| | |
|
|
|
|
|
| ------ | ----------- |
|
|
|
|
|
| `ACTIONS_ID_TOKEN_REQUEST_URL` | The URL for {% data variables.product.prodname_dotcom %}'s OIDC provider. |
|
|
|
|
|
| `ACTIONS_ID_TOKEN_REQUEST_URL` | The URL for {% data variables.product.prodname_dotcom %}'s OIDC provider. |
|
|
|
|
|
| `ACTIONS_ID_TOKEN_REQUEST_TOKEN` | Bearer token for the request to the OIDC provider. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -256,7 +263,7 @@ To customize these claim formats, organization and repository admins can use the
|
|
|
|
|
|
|
|
|
|
By default, the JWT is issued by {% data variables.product.prodname_dotcom %}'s OIDC provider at `https://token.actions.githubusercontent.com`. This path is presented to your cloud provider using the `iss` value in the JWT.
|
|
|
|
|
|
|
|
|
|
Enterprise admins can security harden their OIDC configuration by configuring their enterprise to receive tokens from a unique URL at `https://token.actions.githubusercontent.com/<enterpriseSlug>`. Replace `<enterpriseSlug>` with the slug value of your enterprise.
|
|
|
|
|
Enterprise admins can security harden their OIDC configuration by configuring their enterprise to receive tokens from a unique URL at `https://token.actions.githubusercontent.com/<enterpriseSlug>`. Replace `<enterpriseSlug>` with the slug value of your enterprise.
|
|
|
|
|
|
|
|
|
|
This configuration means that your enterprise will receive the OIDC token from a unique URL, and you can then configure your cloud provider to only accept tokens from that URL. This helps ensure that only the enterprise's repositories can access your cloud resources using OIDC.
|
|
|
|
|
|
|
|
|
@ -291,7 +298,7 @@ To help improve security, compliance, and standardization, you can customize the
|
|
|
|
|
|
|
|
|
|
Customizing the claims results in a new format for the entire `sub` claim, which replaces the default predefined `sub` format in the token described in "[Example subject claims](/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#example-subject-claims)."
|
|
|
|
|
|
|
|
|
|
The following example templates demonstrate various ways to customize the subject claim. To configure these settings on {% data variables.product.prodname_dotcom %}, admins use the REST API to specify a list of claims that must be included in the subject (`sub`) claim.
|
|
|
|
|
The following example templates demonstrate various ways to customize the subject claim. To configure these settings on {% data variables.product.prodname_dotcom %}, admins use the REST API to specify a list of claims that must be included in the subject (`sub`) claim.
|
|
|
|
|
|
|
|
|
|
{% data reusables.actions.use-request-body-api %}
|
|
|
|
|
|
|
|
|
@ -314,7 +321,7 @@ In your cloud provider's OIDC configuration, configure the `sub` condition to re
|
|
|
|
|
|
|
|
|
|
#### Example: Allowing access to all repositories with a specific owner
|
|
|
|
|
|
|
|
|
|
This example template enables the `sub` claim to have a new format with only the value of `repository_owner`.
|
|
|
|
|
This example template enables the `sub` claim to have a new format with only the value of `repository_owner`.
|
|
|
|
|
|
|
|
|
|
{% data reusables.actions.use-request-body-api %}
|
|
|
|
|
|
|
|
|
@ -365,12 +372,12 @@ This example also demonstrates how to use `"context"` to define your conditions.
|
|
|
|
|
|
|
|
|
|
In your cloud provider's OIDC configuration, configure the `sub` condition to require that claims must include specific values for `repo`, `context`, and `job_workflow_ref`.
|
|
|
|
|
|
|
|
|
|
This customization template requires that the `sub` uses the following format: `repo:<orgName/repoName>:environment:<environmentName>:job_workflow_ref:<reusableWorkflowPath>`.
|
|
|
|
|
This customization template requires that the `sub` uses the following format: `repo:<orgName/repoName>:environment:<environmentName>:job_workflow_ref:<reusableWorkflowPath>`.
|
|
|
|
|
For example: `"sub": "repo:octo-org/octo-repo:environment:prod:job_workflow_ref:octo-org/octo-automation/.github/workflows/oidc.yml@refs/heads/main"`
|
|
|
|
|
|
|
|
|
|
#### Example: Granting access to a specific repository
|
|
|
|
|
|
|
|
|
|
This example template lets you grant cloud access to all the workflows in a specific repository, across all branches/tags and environments. To help improve security, combine this template with the custom issuer URL described in "[Customizing the token URL for an enterprise](/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#customizing-the-token-url-for-an-enterprise)."
|
|
|
|
|
This example template lets you grant cloud access to all the workflows in a specific repository, across all branches/tags and environments. To help improve security, combine this template with the custom issuer URL described in "[Customizing the token URL for an enterprise](/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#customizing-the-token-url-for-an-enterprise)."
|
|
|
|
|
|
|
|
|
|
{% data reusables.actions.use-request-body-api %}
|
|
|
|
|
|
|
|
|
@ -386,7 +393,7 @@ In your cloud provider's OIDC configuration, configure the `sub` condition to re
|
|
|
|
|
|
|
|
|
|
#### Example: Using system-generated GUIDs
|
|
|
|
|
|
|
|
|
|
This example template enables predictable OIDC claims with system-generated GUIDs that do not change between renames of entities (such as renaming a repository).
|
|
|
|
|
This example template enables predictable OIDC claims with system-generated GUIDs that do not change between renames of entities (such as renaming a repository).
|
|
|
|
|
|
|
|
|
|
{% data reusables.actions.use-request-body-api %}
|
|
|
|
|
|
|
|
|
@ -431,7 +438,7 @@ In your cloud provider's OIDC configuration, configure the `sub` condition to re
|
|
|
|
|
|
|
|
|
|
#### Using the default subject claims
|
|
|
|
|
|
|
|
|
|
For repositories that can receive a subject claim policy from their organization, the repository owner can later choose to opt-out and instead use the default `sub` claim format. This means that the repository will not use the organization's customized template.
|
|
|
|
|
For repositories that can receive a subject claim policy from their organization, the repository owner can later choose to opt-out and instead use the default `sub` claim format. This means that the repository will not use the organization's customized template.
|
|
|
|
|
|
|
|
|
|
To configure the repository to use the default `sub` claim format, a repository admin must use the REST API endpoint at "[Set the customization template for an OIDC subject claim for a repository](/rest/actions/oidc#set-the-customization-template-for-an-oidc-subject-claim-for-a-repository)" with the following request body:
|
|
|
|
|
|
|
|
|
|