Skip to content

Commit

Permalink
Merge pull request #165 from jfrog/add-multiple-tfc-workload-identity…
Browse files Browse the repository at this point in the history
…-tokens-support

Add 'tfc_credential_tag_name' config attribute
  • Loading branch information
alexhung authored Oct 17, 2024
2 parents 88db814 + 5114b07 commit 79f6505
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 21 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 1.9.0 (October 17, 2024). Tested on Artifactory 7.90.14 with Terraform 1.9.7 and OpenTofu 1.8.3

IMPROVEMENTS:

* provider: Add `tfc_credential_tag_name` configuration attribute to support use of different/[multiple Workload Identity Token in Terraform Cloud Platform](https://developer.hashicorp.com/terraform/cloud-docs/workspaces/dynamic-provider-credentials/manual-generation#generating-multiple-tokens). Issue: [#68](https://github.com/jfrog/terraform-provider-shared/issues/68) PR: [#165](https://github.com/jfrog/terraform-provider-project/pull/165)

## 1.8.0 (September 17, 2024)

IMPROVEMENTS:
Expand Down
4 changes: 4 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ In your workspace, add an environment variable `TFC_WORKLOAD_IDENTITY_AUDIENCE`

When a run starts on Terraform Cloud, it will create a workload identity token with the specified audience and assigns it to the environment variable `TFC_WORKLOAD_IDENTITY_TOKEN` for the provider to consume.

See [Generating Multiple Tokens](https://developer.hashicorp.com/terraform/cloud-docs/workspaces/dynamic-provider-credentials/manual-generation#generating-multiple-tokens) on HCP Terraform for more details on using different tokens.

#### Setup Terraform Cloud in your configuration

Add `cloud` block to `terraform` block, and add `oidc_provider_name` attribute (from JFrog OIDC integration) to provider block:
Expand All @@ -242,6 +244,7 @@ terraform {
provider "project" {
url = "https://myinstance.jfrog.io"
oidc_provider_name = "terraform-cloud"
tfc_credential_tag_name = "JFROG"
}
```

Expand All @@ -255,4 +258,5 @@ provider "project" {
- `access_token` (String, Sensitive) This is a Bearer token that can be given to you by your admin under `Identity and Access`. This can also be sourced from the `PROJECT_ACCESS_TOKEN` or `JFROG_ACCESS_TOKEN` environment variable. Defauult to empty string if not set.
- `check_license` (Boolean, Deprecated) Toggle for pre-flight checking of Artifactory Enterprise license. Default to `true`.
- `oidc_provider_name` (String) OIDC provider name. See [Configure an OIDC Integration](https://jfrog.com/help/r/jfrog-platform-administration-documentation/configure-an-oidc-integration) for more details.
- `tfc_credential_tag_name` (String) Terraform Cloud Workload Identity Token tag name. Use for generating multiple TFC workload identity tokens. When set, the provider will attempt to use env var with this tag name as suffix. **Note:** this is case sensitive, so if set to `JFROG`, then env var `TFC_WORKLOAD_IDENTITY_TOKEN_JFROG` is used instead of `TFC_WORKLOAD_IDENTITY_TOKEN`. See [Generating Multiple Tokens](https://developer.hashicorp.com/terraform/cloud-docs/workspaces/dynamic-provider-credentials/manual-generation#generating-multiple-tokens) on HCP Terraform for more details.
- `url` (String) URL of Artifactory. This can also be sourced from the `PROJECT_URL` or `JFROG_URL` environment variable. Default to 'http://localhost:8081' if not set.
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/jfrog/terraform-provider-project
// if you need to do local dev, literally just uncomment the line below
// replace github.com/jfrog/terraform-provider-shared => ../terraform-provider-shared

go 1.22.5
go 1.22.7

require (
github.com/go-resty/resty/v2 v2.15.3
Expand All @@ -12,7 +12,7 @@ require (
github.com/hashicorp/terraform-plugin-framework-validators v0.13.0
github.com/hashicorp/terraform-plugin-log v0.9.0
github.com/hashicorp/terraform-plugin-testing v1.10.0
github.com/jfrog/terraform-provider-shared v1.25.5
github.com/jfrog/terraform-provider-shared v1.26.0
github.com/samber/lo v1.47.0
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63
)
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM=
github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jfrog/terraform-provider-shared v1.25.5 h1:+hal/9yDAIt2mZljDR8Ymie28yAHr8CAkfthwQ3O3bM=
github.com/jfrog/terraform-provider-shared v1.25.5/go.mod h1:QthwPRUALElMt2RTGqoeB/3Vztx626YPBzIAoqEp0w0=
github.com/jfrog/terraform-provider-shared v1.26.0 h1:xfJfKcgejlFkIyo6VLJPzNtEVfbTYIiGKD2PWysdgw4=
github.com/jfrog/terraform-provider-shared v1.26.0/go.mod h1:IPwXN48K3uzJNDmT2x6zFGa5IS0KG2AK7jnQR2H4G1A=
github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c=
github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo=
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
Expand Down
45 changes: 28 additions & 17 deletions pkg/project/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ type ProjectProvider struct {

// ProjectProviderModel describes the provider data model.
type ProjectProviderModel struct {
Url types.String `tfsdk:"url"`
AccessToken types.String `tfsdk:"access_token"`
OIDCProviderName types.String `tfsdk:"oidc_provider_name"`
CheckLicense types.Bool `tfsdk:"check_license"`
Url types.String `tfsdk:"url"`
AccessToken types.String `tfsdk:"access_token"`
OIDCProviderName types.String `tfsdk:"oidc_provider_name"`
TFCCredentialTagName types.String `tfsdk:"tfc_credential_tag_name"`
CheckLicense types.Bool `tfsdk:"check_license"`
}

// Metadata satisfies the provider.Provider interface for ProjectProvider
Expand Down Expand Up @@ -69,6 +70,13 @@ func (p *ProjectProvider) Schema(ctx context.Context, req provider.SchemaRequest
},
Description: "OIDC provider name. See [Configure an OIDC Integration](https://jfrog.com/help/r/jfrog-platform-administration-documentation/configure-an-oidc-integration) for more details.",
},
"tfc_credential_tag_name": schema.StringAttribute{
Optional: true,
Validators: []validator.String{
stringvalidator.LengthAtLeast(1),
},
Description: "Terraform Cloud Workload Identity Token tag name. Use for generating multiple TFC workload identity tokens. When set, the provider will attempt to use env var with this tag name as suffix. **Note:** this is case sensitive, so if set to `JFROG`, then env var `TFC_WORKLOAD_IDENTITY_TOKEN_JFROG` is used instead of `TFC_WORKLOAD_IDENTITY_TOKEN`. See [Generating Multiple Tokens](https://developer.hashicorp.com/terraform/cloud-docs/workspaces/dynamic-provider-credentials/manual-generation#generating-multiple-tokens) on HCP Terraform for more details.",
},
"check_license": schema.BoolAttribute{
Optional: true,
Description: "Toggle for pre-flight checking of Artifactory Enterprise license. Default to `true`.",
Expand Down Expand Up @@ -114,19 +122,22 @@ func (p *ProjectProvider) Configure(ctx context.Context, req provider.ConfigureR
return
}

oidcAccessToken, err := util.OIDCTokenExchange(ctx, restyClient, config.OIDCProviderName.ValueString())
if err != nil {
resp.Diagnostics.AddError(
"Failed OIDC ID token exchange",
err.Error(),
)
return
}

// use token from OIDC provider, which should take precedence over
// environment variable data, if found.
if oidcAccessToken != "" {
accessToken = oidcAccessToken
oidcProviderName := config.OIDCProviderName.ValueString()
if oidcProviderName != "" {
oidcAccessToken, err := util.OIDCTokenExchange(ctx, restyClient, oidcProviderName, config.TFCCredentialTagName.ValueString())
if err != nil {
resp.Diagnostics.AddError(
"Failed OIDC ID token exchange",
err.Error(),
)
return
}

// use token from OIDC provider, which should take precedence over
// environment variable data, if found.
if oidcAccessToken != "" {
accessToken = oidcAccessToken
}
}

// Check configuration data, which should take precedence over
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
)

func TestAccProjectShareRepository_full(t *testing.T) {
t.Skip("project API is not returning/setting read_only field correctly")

client := acctest.GetTestResty(t)
version, err := util.GetArtifactoryVersion(client)
if err != nil {
Expand Down
3 changes: 3 additions & 0 deletions templates/index.md.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ In your workspace, add an environment variable `TFC_WORKLOAD_IDENTITY_AUDIENCE`

When a run starts on Terraform Cloud, it will create a workload identity token with the specified audience and assigns it to the environment variable `TFC_WORKLOAD_IDENTITY_TOKEN` for the provider to consume.

See [Generating Multiple Tokens](https://developer.hashicorp.com/terraform/cloud-docs/workspaces/dynamic-provider-credentials/manual-generation#generating-multiple-tokens) on HCP Terraform for more details on using different tokens.

#### Setup Terraform Cloud in your configuration

Add `cloud` block to `terraform` block, and add `oidc_provider_name` attribute (from JFrog OIDC integration) to provider block:
Expand All @@ -93,6 +95,7 @@ terraform {
provider "project" {
url = "https://myinstance.jfrog.io"
oidc_provider_name = "terraform-cloud"
tfc_credential_tag_name = "JFROG"
}
```

Expand Down

0 comments on commit 79f6505

Please sign in to comment.