Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 33 additions & 6 deletions docs/guides/workload_identity_federation.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
---
page_title: "Workload Identity Federation with GitHub Actions"
page_title: "Workload Identity Federation"
---

# Workload Identity Federation with GitHub Actions

Workload Identity Federation (WIF) allows you to authenticate the STACKIT Terraform provider without using long-lived Service Account keys.
This is particularly useful in CI/CD environments like **GitHub Actions**, **GitLab CI**, or **Azure DevOps**, where you can use short-lived
OIDC tokens. This guide focuses on using WIF with GitHub Actions, but the principles may apply to other CI/CD platforms that support OIDC.
OIDC tokens. This guide focuses on using WIF with GitHub Actions and Azure DevOps, but the principles may apply to other CI/CD platforms that support OIDC.

## Prerequisites

Expand All @@ -16,8 +16,13 @@ Before using Workload Identity Federation flow, you need to:
## Setup Workload Identity Federation

WIF can be configured to trust any public OIDC provider following the [docs page](https://docs.stackit.cloud/platform/access-and-identity/service-accounts/how-tos/manage-service-account-federations/#create-a-federated-identity-provider)
but for the purpose of this guide we will focus on GitHub Actions as OIDC provider. GitHub Actions supports OIDC authentication using
the public issuer "https://token.actions.githubusercontent.com" (for GH Enterprise you should check your issuer URL) and setting repository and action information
but for the purpose of this guide we will focus on GitHub Actions and AzureDevOps as OIDC providers.

> Important: The most closed assertions including all the data that you cant from the OIDC token should be used to avoid potential security risks of trusting tokens that are not issued in the context of your CI/CD pipeline.

### GitHub Actions assertions

GitHub Actions supports OIDC authentication using the public issuer "https://token.actions.githubusercontent.com" (for GH Enterprise you should check your issuer URL) and setting repository and action information
as part of the OIDC token claims. [More info here](https://docs.github.com/es/actions/concepts/security/openid-connect).

Using this provider [repository](https://github.com/stackitcloud/terraform-provider-stackit) (stackitcloud/terraform-provider-stackit) as example and assuming that we want to
Expand All @@ -28,7 +33,27 @@ execute terraform on the main branch, we will configure the service account "Fed
- **sub**->equals->repo:stackitcloud/terraform-provider-stackit:ref:refs/heads/main # This is the repository and branch where the action will run
- **aud**->equals->sts.accounts.stackit.cloud # Mandatory value

> Note: You can use more fine-grained assertions just adding them. More info about OIDC token claims in [GitHub](https://docs.github.com/en/actions/reference/security/oidc)
> Note: You can use more fine-grained assertions by adding them. More info about OIDC token claims in [GitHub](https://docs.github.com/en/actions/reference/security/oidc)

### Azure DevOps assertions

Azure DevOps supports OIDC authentication using the public issuer "https://vstoken.azure.com" (for Azure DevOps Server you should check your issuer URL) and setting information like organization, project, and pipeline
as part of the OIDC token claims.

Using a hypothetical pipeline named `terraform-ado-oidc` inside the prohect 'https://myorg.azure.com/project-abc` as example and assuming that we want to
execute terraform on the main branch, we will configure the service account "Federated identity Provider" with the following configuration:
- **Provider Name**: AzureDevOps # This is just an example, you can choose any name you want
- **Issuer URL**: https://vstoken.dev.azure.com/{ORGANIZATION_ID} # This is the public issuer for Azure DevOps OIDC tokens
- For most organizations, the URL uses `vstoken.dev.azure.com`, but some legacy organizations might use 'vstoken.azure.com' To be 100% sure, you can inspect the `iss` claim in a decoded OIDC token from your pipeline,
- How to find your ORGANIZATION_ID?
- Via Browser: Go to https://dev.azure.com/{YOUR_ORG_NAME}/_apis/connectionData and copy the value of instanceId.
- Via Pipeline: Add a script step echo $(System.CollectionId) to print it during a run.
- **Assertions**:
- **aud**->equals->api://AzureADTokenExchange # Mandatory value
- **sub**->equals->p://myorg/project-abc/terraform-ado-oidc # This is the pipeline where the process is running
- **rpo_ref**->equals->refs/heads/main # This is the branch where the pipeline will run

> Note: This is just an example, you can use more or less fine-grained assertions.

## Provider Configuration

Expand All @@ -50,7 +75,9 @@ provider "stackit" {
In most CI/CD scenarios, the cleanest way is to set the `STACKIT_SERVICE_ACCOUNT_EMAIL` environment variable as well as `STACKIT_USE_OIDC="1"` to enable the WIF flow. This way you don't need to
change your provider configuration and the provider will automatically fetch the OIDC token and exchange it for a short-lived access token.

## Example GitHub Actions Workflow
## Examples

### GitHub Actions Workflow

> Note: To request OIDC tokens, you need to [grant this permission to the GitHub Actions workflow](https://docs.github.com/en/actions/reference/security/oidc#required-permission).

Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ When using Workload Identity Federation (WIF), you don't need a static service a

WIF can be configured to trust any public OIDC provider following the [official documentation](https://docs.stackit.cloud/platform/access-and-identity/service-accounts/how-tos/manage-service-account-federations/#create-a-federated-identity-provider).

To use WIF, set the `use_oidc` flag to `true` and provide an OIDC token for the exchange. While you can provide the token directly via `service_account_federated_token`, this is **not recommended for GitHub Actions**, as the provider will automatically fetch the token from the environment. For a complete setup, see our [Workload Identity Federation guide](./guides/workload_identity_federation.md).
To use WIF, set the `use_oidc` flag to `true` and provide an OIDC token for the exchange. While you can provide the token directly via `service_account_federated_token`, this is **not recommended for GitHub Actions or Azure DevOps**, as the provider will automatically fetch the token from the environment. For a complete setup, see our [Workload Identity Federation guide](./docs/guides/workload_identity_federation.md).

In addition to this, you must set the `service_account_email` to specify which service account to impersonate.

Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ module github.com/stackitcloud/terraform-provider-stackit

go 1.24.0

replace github.com/stackitcloud/stackit-sdk-go/core => github.com/jorturfer/stackit-sdk-go/core v0.0.0-20260218191605-c1e0812ff15f

require (
github.com/google/go-cmp v0.7.0
github.com/google/uuid v1.6.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94=
github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8=
github.com/jorturfer/stackit-sdk-go/core v0.0.0-20260218191605-c1e0812ff15f h1:fTNZZta47QPQs8rG48i47wFQChjoYwUeoMGikLj6iSk=
github.com/jorturfer/stackit-sdk-go/core v0.0.0-20260218191605-c1e0812ff15f/go.mod h1:osMglDby4csGZ5sIfhNyYq1bS1TxIdPY88+skE/kkmI=
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
Expand Down Expand Up @@ -149,8 +151,6 @@ github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8=
github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY=
github.com/stackitcloud/stackit-sdk-go/core v0.21.1 h1:Y/PcAgM7DPYMNqum0MLv4n1mF9ieuevzcCIZYQfm3Ts=
github.com/stackitcloud/stackit-sdk-go/core v0.21.1/go.mod h1:osMglDby4csGZ5sIfhNyYq1bS1TxIdPY88+skE/kkmI=
github.com/stackitcloud/stackit-sdk-go/services/authorization v0.12.0 h1:HxPgBu04j5tj6nfZ2r0l6v4VXC0/tYOGe4sA5Addra8=
github.com/stackitcloud/stackit-sdk-go/services/authorization v0.12.0/go.mod h1:uYI9pHAA2g84jJN25ejFUxa0/JtfpPZqMDkctQ1BzJk=
github.com/stackitcloud/stackit-sdk-go/services/cdn v1.10.0 h1:YALzjYAApyQMKyt4C2LKhPRZHa6brmbFeKuuwl+KOTs=
Expand Down
13 changes: 12 additions & 1 deletion stackit/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ func (p *Provider) Configure(ctx context.Context, req provider.ConfigureRequest,
sdkConfig.ServiceAccountFederatedTokenFunc = oidcadapters.ReadJWTFromFileSystem(oidc_token_path)
}

// Workload Identity Federation via provided OIDC Token from GitHub Actions
// Workload Identity Federation via provided OIDC Token from GitHub Actions or Azure Dev Ops
if sdkConfig.ServiceAccountFederatedTokenFunc == nil && utils.GetEnvBoolIfValueAbsent(providerConfig.UseOIDC, "STACKIT_USE_OIDC") {
sdkConfig.WorkloadIdentityFederation = true
// https://docs.github.com/en/actions/reference/security/oidc#methods-for-requesting-the-oidc-token
Expand All @@ -558,6 +558,17 @@ func (p *Provider) Configure(ctx context.Context, req provider.ConfigureRequest,
if oidcReqURL != "" && oidcReqToken != "" {
sdkConfig.ServiceAccountFederatedTokenFunc = oidcadapters.RequestGHOIDCToken(oidcReqURL, oidcReqToken)
}

// https://learn.microsoft.com/en-us/rest/api/azure/devops/distributedtask/oidctoken/create?view=azure-devops-rest-7.1#taskhuboidctoken
// https://learn.microsoft.com/es-es/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml
oidcReqURL = utils.GetEnvStringOrDefault(providerConfig.OIDCTokenRequestURL, "SYSTEM_OIDCREQUESTURI", "")
oidcReqToken = utils.GetEnvStringOrDefault(providerConfig.OIDCTokenRequestToken, "SYSTEM_ACCESSTOKEN", "")
// This can be set to the ID of the service connection to restrict the token exchange to that connection, not supported by default to avoid additional configuration
// for users that don't need it, can be added as an additional provider config parameter in the future if there is demand
serviceConnectionID := ""
if oidcReqURL != "" && oidcReqToken != "" {
sdkConfig.ServiceAccountFederatedTokenFunc = oidcadapters.RequestAzureDevOpsOIDCToken(oidcReqURL, oidcReqToken, serviceConnectionID)
}
}

roundTripper, err := sdkauth.SetupAuth(sdkConfig)
Expand Down
39 changes: 33 additions & 6 deletions templates/guides/workload_identity_federation.md.tmpl
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
---
page_title: "Workload Identity Federation with GitHub Actions"
page_title: "Workload Identity Federation"
---

# Workload Identity Federation with GitHub Actions

Workload Identity Federation (WIF) allows you to authenticate the STACKIT Terraform provider without using long-lived Service Account keys.
This is particularly useful in CI/CD environments like **GitHub Actions**, **GitLab CI**, or **Azure DevOps**, where you can use short-lived
OIDC tokens. This guide focuses on using WIF with GitHub Actions, but the principles may apply to other CI/CD platforms that support OIDC.
OIDC tokens. This guide focuses on using WIF with GitHub Actions and Azure DevOps, but the principles may apply to other CI/CD platforms that support OIDC.

## Prerequisites

Expand All @@ -16,8 +16,13 @@ Before using Workload Identity Federation flow, you need to:
## Setup Workload Identity Federation

WIF can be configured to trust any public OIDC provider following the [docs page](https://docs.stackit.cloud/platform/access-and-identity/service-accounts/how-tos/manage-service-account-federations/#create-a-federated-identity-provider)
but for the purpose of this guide we will focus on GitHub Actions as OIDC provider. GitHub Actions supports OIDC authentication using
the public issuer "https://token.actions.githubusercontent.com" (for GH Enterprise you should check your issuer URL) and setting repository and action information
but for the purpose of this guide we will focus on GitHub Actions and AzureDevOps as OIDC providers.

> Important: The most closed assertions including all the data that you cant from the OIDC token should be used to avoid potential security risks of trusting tokens that are not issued in the context of your CI/CD pipeline.

### GitHub Actions assertions

GitHub Actions supports OIDC authentication using the public issuer "https://token.actions.githubusercontent.com" (for GH Enterprise you should check your issuer URL) and setting repository and action information
as part of the OIDC token claims. [More info here](https://docs.github.com/es/actions/concepts/security/openid-connect).

Using this provider [repository](https://github.com/stackitcloud/terraform-provider-stackit) (stackitcloud/terraform-provider-stackit) as example and assuming that we want to
Expand All @@ -28,7 +33,27 @@ execute terraform on the main branch, we will configure the service account "Fed
- **sub**->equals->repo:stackitcloud/terraform-provider-stackit:ref:refs/heads/main # This is the repository and branch where the action will run
- **aud**->equals->sts.accounts.stackit.cloud # Mandatory value

> Note: You can use more fine-grained assertions just adding them. More info about OIDC token claims in [GitHub](https://docs.github.com/en/actions/reference/security/oidc)
> Note: You can use more fine-grained assertions by adding them. More info about OIDC token claims in [GitHub](https://docs.github.com/en/actions/reference/security/oidc)

### Azure DevOps assertions

Azure DevOps supports OIDC authentication using the public issuer "https://vstoken.azure.com" (for Azure DevOps Server you should check your issuer URL) and setting information like organization, project, and pipeline
as part of the OIDC token claims.

Using a hypothetical pipeline named `terraform-ado-oidc` inside the prohect 'https://myorg.azure.com/project-abc` as example and assuming that we want to
execute terraform on the main branch, we will configure the service account "Federated identity Provider" with the following configuration:
- **Provider Name**: AzureDevOps # This is just an example, you can choose any name you want
- **Issuer URL**: https://vstoken.dev.azure.com/{ORGANIZATION_ID} # This is the public issuer for Azure DevOps OIDC tokens
- For most organizations, the URL uses `vstoken.dev.azure.com`, but some legacy organizations might use 'vstoken.azure.com' To be 100% sure, you can inspect the `iss` claim in a decoded OIDC token from your pipeline,
- How to find your ORGANIZATION_ID?
- Via Browser: Go to https://dev.azure.com/{YOUR_ORG_NAME}/_apis/connectionData and copy the value of instanceId.
- Via Pipeline: Add a script step echo $(System.CollectionId) to print it during a run.
- **Assertions**:
- **aud**->equals->api://AzureADTokenExchange # Mandatory value
- **sub**->equals->p://myorg/project-abc/terraform-ado-oidc # This is the pipeline where the process is running
- **rpo_ref**->equals->refs/heads/main # This is the branch where the pipeline will run
> Note: This is just an example, you can use more or less fine-grained assertions.
## Provider Configuration
Expand All @@ -50,7 +75,9 @@ provider "stackit" {
In most CI/CD scenarios, the cleanest way is to set the `STACKIT_SERVICE_ACCOUNT_EMAIL` environment variable as well as `STACKIT_USE_OIDC="1"` to enable the WIF flow. This way you don't need to
change your provider configuration and the provider will automatically fetch the OIDC token and exchange it for a short-lived access token.
## Example GitHub Actions Workflow
## Examples
### GitHub Actions Workflow
> Note: To request OIDC tokens, you need to [grant this permission to the GitHub Actions workflow](https://docs.github.com/en/actions/reference/security/oidc#required-permission).
Expand Down
2 changes: 1 addition & 1 deletion templates/index.md.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ When using Workload Identity Federation (WIF), you don't need a static service a

WIF can be configured to trust any public OIDC provider following the [official documentation](https://docs.stackit.cloud/platform/access-and-identity/service-accounts/how-tos/manage-service-account-federations/#create-a-federated-identity-provider).

To use WIF, set the `use_oidc` flag to `true` and provide an OIDC token for the exchange. While you can provide the token directly via `service_account_federated_token`, this is **not recommended for GitHub Actions**, as the provider will automatically fetch the token from the environment. For a complete setup, see our [Workload Identity Federation guide](./guides/workload_identity_federation.md).
To use WIF, set the `use_oidc` flag to `true` and provide an OIDC token for the exchange. While you can provide the token directly via `service_account_federated_token`, this is **not recommended for GitHub Actions or Azure DevOps**, as the provider will automatically fetch the token from the environment. For a complete setup, see our [Workload Identity Federation guide](./docs/guides/workload_identity_federation.md).

In addition to this, you must set the `service_account_email` to specify which service account to impersonate.

Expand Down
Loading