diff --git a/CHANGELOG.md b/CHANGELOG.md index 90ff10089..82019946d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,9 @@ ## Unreleased +FEATURES: +* **New Data Source:** `d/hyok_customer_key_version` is a new data source for finding + HYOK customer key versions by @dominicretli [#1842](https://github.com/hashicorp/terraform-provider-tfe/pull/1842) +* **New Data Source:** `d/hyok_encrypted_data_key` is a new data source for finding + HYOK encrypted data keys by @dominicretli [#1842](https://github.com/hashicorp/terraform-provider-tfe/pull/1842) ## v0.69.0 diff --git a/docs/testing.md b/docs/testing.md index 23e59c3d0..eb07fe9f6 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -49,6 +49,8 @@ these values with the environment variables specified below: 1. `RUN_TASKS_HMAC` - The optional HMAC Key that should be used for Run Task operations. The default is no key. 1. `GITHUB_APP_INSTALLATION_ID` - GitHub App installation internal id in the format `ghain-xxxxxxx`. Required for running any tests that use GitHub App VCS (workspace, policy sets, registry module). 1. `GITHUB_APP_INSTALLATION_NAME` - GitHub App installation name. Required for running tfe_github_app_installation data source test. +1. `HYOK_ENCRYPTED_DATA_KEY_ID` - HYOK encrypted data key id. Required for running hyok_encrypted_data_key data source test. +1. `HYOK_CUSTOMER_KEY_VERSION_ID` - HYOK customer key version id. Required for running hyok_customer_key_version data source test. **Note:** In order to run integration tests for **Paid** features you will need a token `TFE_TOKEN` with HCP Terraform or Terraform Enterprise administrator privileges, otherwise the attempt to upgrade an organization's feature set will fail. diff --git a/internal/provider/data_source_hyok_customer_key_version.go b/internal/provider/data_source_hyok_customer_key_version.go new file mode 100644 index 000000000..8c45465f3 --- /dev/null +++ b/internal/provider/data_source_hyok_customer_key_version.go @@ -0,0 +1,115 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package provider + +import ( + "context" + "fmt" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" + "time" +) + +var ( + _ datasource.DataSource = &dataSourceHYOKCustomerKeyVersion{} + _ datasource.DataSourceWithConfigure = &dataSourceHYOKCustomerKeyVersion{} +) + +func NewHYOKCustomerKeyVersionDataSource() datasource.DataSource { + return &dataSourceHYOKCustomerKeyVersion{} +} + +type dataSourceHYOKCustomerKeyVersion struct { + config ConfiguredClient +} + +type HYOKCustomerKeyVersionDataSourceModel struct { + ID types.String `tfsdk:"id"` + Status types.String `tfsdk:"status"` + Error types.String `tfsdk:"error"` + KeyVersion types.String `tfsdk:"key_version"` + CreatedAt types.String `tfsdk:"created_at"` + WorkspacesSecured types.Int64 `tfsdk:"workspaces_secured"` +} + +func (d *dataSourceHYOKCustomerKeyVersion) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + client, ok := req.ProviderData.(ConfiguredClient) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Data Source Configure Type", + fmt.Sprintf("Expected tfe.ConfiguredClient, got %T. This is a bug in the tfe provider, so please report it on GitHub.", req.ProviderData), + ) + + return + } + d.config = client +} + +func (d *dataSourceHYOKCustomerKeyVersion) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_hyok_customer_key_version" +} + +func (d *dataSourceHYOKCustomerKeyVersion) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + Description: "This data source can be used to retrieve a HYOK customer key version.", + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Description: "The ID of the HYOK customer key version.", + Required: true, + }, + "status": schema.StringAttribute{ + Description: "The status of the HYOK customer key version.", + Computed: true, + }, + "error": schema.StringAttribute{ + Description: "Any error message associated with the HYOK customer key version.", + Computed: true, + }, + "key_version": schema.StringAttribute{ + Description: "The version number of the customer key version.", + Computed: true, + }, + "workspaces_secured": schema.Int64Attribute{ + Description: "The number workspaces secured by this customer key version.", + Computed: true, + }, + "created_at": schema.StringAttribute{ + Description: "The timestamp when the key version was created.", + Computed: true, + }, + }, + } +} + +func (d *dataSourceHYOKCustomerKeyVersion) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var data HYOKCustomerKeyVersionDataSourceModel + + // Read Terraform configuration data into the model + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + // Make API call to fetch the HYOK customer key version + keyVersion, err := d.config.Client.HYOKCustomerKeyVersions.Read(ctx, data.ID.ValueString()) + if err != nil { + resp.Diagnostics.AddError("Unable to read HYOK customer key version", err.Error()) + return + } + + // Set the computed attributes from the API response + data.Status = types.StringValue(string(keyVersion.Status)) + data.KeyVersion = types.StringValue(keyVersion.KeyVersion) + data.CreatedAt = types.StringValue(keyVersion.CreatedAt.Format(time.RFC3339)) + data.WorkspacesSecured = types.Int64Value(int64(keyVersion.WorkspacesSecured)) + data.Error = types.StringValue(keyVersion.Error) + + // Save data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} diff --git a/internal/provider/data_source_hyok_customer_key_version_test.go b/internal/provider/data_source_hyok_customer_key_version_test.go new file mode 100644 index 000000000..0108857d8 --- /dev/null +++ b/internal/provider/data_source_hyok_customer_key_version_test.go @@ -0,0 +1,40 @@ +package provider + +import ( + "os" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestAccTFEHYOKCustomerKeyVersionDataSource_basic(t *testing.T) { + hyokCustomerKeyVersionId := os.Getenv("HYOK_CUSTOMER_KEY_VERSION_ID") + if hyokCustomerKeyVersionId == "" { + t.Skip("HYOK_CUSTOMER_KEY_VERSION_ID environment variable must be set to run this test") + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccMuxedProviders, + Steps: []resource.TestStep{ + { + Config: testAccTFEHYOKCustomerKeyVersionDataSourceConfig(hyokCustomerKeyVersionId), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.tfe_hyok_customer_key_version.test", "id", hyokCustomerKeyVersionId), + resource.TestCheckResourceAttrSet("data.tfe_hyok_customer_key_version.test", "status"), + resource.TestCheckResourceAttrSet("data.tfe_hyok_customer_key_version.test", "key_version"), + resource.TestCheckResourceAttrSet("data.tfe_hyok_customer_key_version.test", "created_at"), + resource.TestCheckResourceAttrSet("data.tfe_hyok_customer_key_version.test", "workspaces_secured"), + ), + }, + }, + }) +} + +func testAccTFEHYOKCustomerKeyVersionDataSourceConfig(id string) string { + return ` +data "tfe_hyok_customer_key_version" "test" { + id = "` + id + `" +} +` +} diff --git a/internal/provider/data_source_hyok_encrypted_data_key.go b/internal/provider/data_source_hyok_encrypted_data_key.go new file mode 100644 index 000000000..64cd2d271 --- /dev/null +++ b/internal/provider/data_source_hyok_encrypted_data_key.go @@ -0,0 +1,103 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package provider + +import ( + "context" + "fmt" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" + "time" +) + +var ( + _ datasource.DataSource = &dataSourceHYOKEncryptedDataKey{} + _ datasource.DataSourceWithConfigure = &dataSourceHYOKEncryptedDataKey{} +) + +func NewHYOKEncryptedDataKeyDataSource() datasource.DataSource { + return &dataSourceHYOKEncryptedDataKey{} +} + +type dataSourceHYOKEncryptedDataKey struct { + config ConfiguredClient +} + +type HYOKEncryptedDataKeyDataSourceModel struct { + ID types.String `tfsdk:"id"` + EncryptedDEK types.String `tfsdk:"encrypted_dek"` + CustomerKeyName types.String `tfsdk:"customer_key_name"` + CreatedAt types.String `tfsdk:"created_at"` +} + +func (d *dataSourceHYOKEncryptedDataKey) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + client, ok := req.ProviderData.(ConfiguredClient) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Data Source Configure Type", + fmt.Sprintf("Expected tfe.ConfiguredClient, got %T. This is a bug in the tfe provider, so please report it on GitHub.", req.ProviderData), + ) + + return + } + d.config = client +} + +func (d *dataSourceHYOKEncryptedDataKey) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_hyok_encrypted_data_key" +} + +func (d *dataSourceHYOKEncryptedDataKey) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + Description: "This data source can be used to retrieve a HYOK customer key version.", + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Description: "The ID of the HYOK encrypted data key.", + Required: true, + }, + "encrypted_dek": schema.StringAttribute{ + Description: "The encrypted data encryption key of the HYOK encrypted data key.", + Computed: true, + }, + "customer_key_name": schema.StringAttribute{ + Description: "The customer provided name of the HYOK encrypted data key.", + Computed: true, + }, + "created_at": schema.StringAttribute{ + Description: "The timestamp when the key version was created.", + Computed: true, + }, + }, + } +} + +func (d *dataSourceHYOKEncryptedDataKey) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var data HYOKEncryptedDataKeyDataSourceModel + + // Read Terraform configuration data into the model + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + // Make API call to fetch the HYOK customer key version + keyVersion, err := d.config.Client.HYOKEncryptedDataKeys.Read(ctx, data.ID.ValueString()) + if err != nil { + resp.Diagnostics.AddError("Unable to read HYOK customer key version", err.Error()) + return + } + + // Set the computed attributes from the API response + data.EncryptedDEK = types.StringValue(keyVersion.EncryptedDEK) + data.CustomerKeyName = types.StringValue(keyVersion.CustomerKeyName) + data.CreatedAt = types.StringValue(keyVersion.CreatedAt.Format(time.RFC3339)) // TODO DOM: Check this format + + // Save data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} diff --git a/internal/provider/data_source_hyok_encrypted_data_key_test.go b/internal/provider/data_source_hyok_encrypted_data_key_test.go new file mode 100644 index 000000000..d591fa80b --- /dev/null +++ b/internal/provider/data_source_hyok_encrypted_data_key_test.go @@ -0,0 +1,39 @@ +package provider + +import ( + "os" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestAccTFEHYOKEncryptedDataKeyDataSource_basic(t *testing.T) { + hyokEncryptedDataKeyID := os.Getenv("HYOK_ENCRYPTED_DATA_KEY_ID") + if hyokEncryptedDataKeyID == "" { + t.Skip("HYOK_ENCRYPTED_DATA_KEY_ID environment variable must be set to run this test") + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccMuxedProviders, + Steps: []resource.TestStep{ + { + Config: testAccTFEHYOKEncryptedDataKeyDataSourceConfig(hyokEncryptedDataKeyID), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.tfe_hyok_encrypted_data_key.test", "id", hyokEncryptedDataKeyID), + resource.TestCheckResourceAttrSet("data.tfe_hyok_encrypted_data_key.test", "encrypted_dek"), + resource.TestCheckResourceAttrSet("data.tfe_hyok_encrypted_data_key.test", "customer_key_name"), + resource.TestCheckResourceAttrSet("data.tfe_hyok_encrypted_data_key.test", "created_at"), + ), + }, + }, + }) +} + +func testAccTFEHYOKEncryptedDataKeyDataSourceConfig(id string) string { + return ` +data "tfe_hyok_encrypted_data_key" "test" { + id = "` + id + `" +} +` +} diff --git a/internal/provider/provider_next.go b/internal/provider/provider_next.go index 3eecf8c71..8234e1e63 100644 --- a/internal/provider/provider_next.go +++ b/internal/provider/provider_next.go @@ -130,6 +130,8 @@ func (p *frameworkProvider) Configure(ctx context.Context, req provider.Configur func (p *frameworkProvider) DataSources(ctx context.Context) []func() datasource.DataSource { return []func() datasource.DataSource{ + NewHYOKCustomerKeyVersionDataSource, + NewHYOKEncryptedDataKeyDataSource, NewNoCodeModuleDataSource, NewOrganizationRunTaskDataSource, NewOrganizationRunTaskGlobalSettingsDataSource, diff --git a/website/docs/d/hyok_customer_key_version.markdown b/website/docs/d/hyok_customer_key_version.markdown new file mode 100644 index 000000000..f17616ff5 --- /dev/null +++ b/website/docs/d/hyok_customer_key_version.markdown @@ -0,0 +1,35 @@ +--- +layout: "tfe" +page_title: "Terraform Enterprise: tfe_agent_pool" +description: |- + Get information on an agent pool. +--- + +# Data Source: tfe_hyok_customer_key_version + +Use this data source to get information about a Hold Your Own Keys (HYOK) customer key version. + +## Example Usage + +```hcl +data "tfe_hyok_customer_key_version" "tfe_hyok_customer_key_version1" { + id = "keyv-" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `id` - (Required) The ID of the HYOK customer key version. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `created_at` - The time when the customer key version was created. +* `error` - Any error message associated with the customer key version. +* `id` - The ID of the customer key version. +* `key_version` - The version number of the customer key. +* `status` - The status of the customer key version. +* `workspaces_secured` - The number of workspaces securefd by this customer key version. diff --git a/website/docs/d/hyok_encrypted_data_key.markdown b/website/docs/d/hyok_encrypted_data_key.markdown new file mode 100644 index 000000000..3f6dde651 --- /dev/null +++ b/website/docs/d/hyok_encrypted_data_key.markdown @@ -0,0 +1,33 @@ +--- +layout: "tfe" +page_title: "Terraform Enterprise: tfe_agent_pool" +description: |- + Get information on an agent pool. +--- + +# Data Source: tfe_hyok_encrypted_data_key + +Use this data source to get information about a Hold Your Own Keys (HYOK) encrypted data key. + +## Example Usage + +```hcl +data "tfe_hyok_encrypted_data_key" "tfe_hyok_encrypted_data_key1" { + id = "dek-" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `id` - (Required) The ID of the HYOK encrypted data key. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `created_at` - The time when the encrypted data key was created. +* `customer_key_name` - The name of the customer key used to encrypt the data key. +* `encrypted_dek` - The encrypted data encryption key (DEK). +* `id` - The ID of the encrypted data key. \ No newline at end of file