diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f3ece02d..05b51e0a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## Unreleased +FEATURES: + +* `d/tfe_organization_audit_configuration`: is a new resource for reading the auditing configuration for an organizations, by @glennsarti-hashi [#1778](https://github.com/hashicorp/terraform-provider-tfe/pull/1778) + ## v0.68.2 BUG FIXES: diff --git a/go.mod b/go.mod index 109b73f1e..5efb9288a 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-retryablehttp v0.7.7 // indirect github.com/hashicorp/go-slug v0.16.7 - github.com/hashicorp/go-tfe v1.87.0 + github.com/hashicorp/go-tfe v1.88.0 github.com/hashicorp/go-version v1.7.0 github.com/hashicorp/hcl v1.0.0 github.com/hashicorp/hcl/v2 v2.23.0 // indirect diff --git a/go.sum b/go.sum index e885e0e42..905d72e14 100644 --- a/go.sum +++ b/go.sum @@ -72,8 +72,8 @@ github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISH github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/hashicorp/go-slug v0.16.7 h1:sBW8y1sX+JKOZKu9a+DQZuWDVaX+U9KFnk6+VDQvKcw= github.com/hashicorp/go-slug v0.16.7/go.mod h1:X5fm++dL59cDOX8j48CqHr4KARTQau7isGh0ZVxJB5I= -github.com/hashicorp/go-tfe v1.87.0 h1:0ejo3SegLoQ/Uj/2U0ECGppm3E/VZfSu+KscvzxvRNs= -github.com/hashicorp/go-tfe v1.87.0/go.mod h1:6dUFMBKh0jkxlRsrw7bYD2mby0efdwE4dtlAuTogIzA= +github.com/hashicorp/go-tfe v1.88.0 h1:xTzjNOPoA5oz0X544Rn8T8zRRFGHqIjZDL4wXRR/0Xk= +github.com/hashicorp/go-tfe v1.88.0/go.mod h1:6dUFMBKh0jkxlRsrw7bYD2mby0efdwE4dtlAuTogIzA= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= diff --git a/internal/provider/data_source_organization_audit_configuration.go b/internal/provider/data_source_organization_audit_configuration.go new file mode 100644 index 000000000..d489df37d --- /dev/null +++ b/internal/provider/data_source_organization_audit_configuration.go @@ -0,0 +1,149 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package provider + +import ( + "context" + "fmt" + + tfe "github.com/hashicorp/go-tfe" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +// Ensure the implementation satisfies the expected interfaces. +var ( + _ datasource.DataSource = &dataSourceOrganizationAuditConfiguration{} + _ datasource.DataSourceWithConfigure = &dataSourceOrganizationAuditConfiguration{} +) + +type modelDataTFEOrganizationAuditConfigurationV0 struct { + ID types.String `tfsdk:"id"` + Organization types.String `tfsdk:"organization"` + + AuditTrailsEnabled types.Bool `tfsdk:"audit_trails_enabled"` + HCPAuditLogStreamingEnabled types.Bool `tfsdk:"hcp_log_streaming_enabled"` + HCPOrganization types.String `tfsdk:"hcp_organization"` +} + +func dataTFEOrganizationAuditConfiguration(v *tfe.OrganizationAuditConfiguration) modelDataTFEOrganizationAuditConfigurationV0 { + result := modelDataTFEOrganizationAuditConfigurationV0{ + ID: types.StringValue(v.ID), + Organization: types.StringValue(v.Organization.Name), + + AuditTrailsEnabled: types.BoolValue(v.AuditTrails.Enabled), + HCPAuditLogStreamingEnabled: types.BoolValue(v.HCPAuditLogStreaming.Enabled), + HCPOrganization: types.StringValue(v.HCPAuditLogStreaming.OrganizationID), + } + + return result +} + +// NewOrganizationAuditConfigurationDataSource is a helper function to simplify the provider implementation. +func NewOrganizationAuditConfigurationDataSource() datasource.DataSource { + return &dataSourceOrganizationAuditConfiguration{} +} + +// dataSourceOrganizationAuditConfiguration is the data source implementation. +type dataSourceOrganizationAuditConfiguration struct { + config ConfiguredClient +} + +// Metadata returns the data source type name. +func (d *dataSourceOrganizationAuditConfiguration) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_organization_audit_configuration" +} + +func (d *dataSourceOrganizationAuditConfiguration) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Computed: true, + Description: "Service-generated identifier for the configuration.", + }, + "organization": schema.StringAttribute{ + Required: true, + Description: "Name of the organization.", + }, + + "audit_trails_enabled": schema.BoolAttribute{ + Optional: true, + Description: "Whether Audit Trails is enabled for the organization.", + }, + "hcp_log_streaming_enabled": schema.BoolAttribute{ + Optional: true, + Description: "Whether HCP Audit Log Streaming is enabled for the organization.", + }, + "hcp_organization": schema.StringAttribute{ + Optional: true, + Description: "The destination HCP Organization for HCP Audit Log Streaming.", + }, + }, + } +} + +// Configure adds the provider configured client to the data source. +func (d *dataSourceOrganizationAuditConfiguration) 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 +} + +// Read refreshes the Terraform state with the latest data. +func (d *dataSourceOrganizationAuditConfiguration) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var data modelDataTFEOrganizationAuditConfigurationV0 + + // Read Terraform configuration data into the model + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + var organization string + resp.Diagnostics.Append(d.config.dataOrDefaultOrganization(ctx, req.Config, &organization)...) + if resp.Diagnostics.HasError() { + return + } + + org, err := d.config.Client.Organizations.Read(ctx, organization) + if err != nil { + resp.Diagnostics.AddError("Error reading Organization Audit Configuration", + fmt.Sprintf("Could not read Organization %q, unexpected error: %s", organization, err.Error()), + ) + return + } + + if !org.Permissions.CanManageAuditing { + resp.Diagnostics.AddWarning("Cannot read audit configuration", + fmt.Sprintf("Cannot not read the audit configuration in organization %q due to insufficient permissions or the organization not supporting auditing", organization), + ) + return + } + + ac, err := d.config.Client.OrganizationAuditConfigurations.Read(ctx, organization) + if err != nil { + resp.Diagnostics.AddError("Error reading Organization Audit Configuration", + fmt.Sprintf("Could not read Audit Configuration in organization %q, unexpected error: %s", organization, err.Error()), + ) + return + } + + result := dataTFEOrganizationAuditConfiguration(ac) + + // Save updated data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &result)...) +} diff --git a/internal/provider/data_source_organization_audit_configuration_test.go b/internal/provider/data_source_organization_audit_configuration_test.go new file mode 100644 index 000000000..6feaa8df4 --- /dev/null +++ b/internal/provider/data_source_organization_audit_configuration_test.go @@ -0,0 +1,78 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package provider + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestAccTFEOrganizationAuditConfigurationDataSource_basic(t *testing.T) { + skipUnlessBeta(t) + + tfeClient, err := getClientUsingEnv() + if err != nil { + t.Fatal(err) + } + + org, orgCleanup := createBusinessOrganization(t, tfeClient) + t.Cleanup(orgCleanup) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV5ProviderFactories: testAccMuxedProviders, + Steps: []resource.TestStep{ + { + Config: testAccTFEOrganizationAuditConfigDataSourceConfig(org.Name), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.tfe_organization_audit_configuration.foobar", "organization", org.Name), + resource.TestCheckResourceAttrSet("data.tfe_organization_audit_configuration.foobar", "id"), + resource.TestCheckResourceAttrSet("data.tfe_organization_audit_configuration.foobar", "audit_trails_enabled"), + resource.TestCheckResourceAttrSet("data.tfe_organization_audit_configuration.foobar", "hcp_log_streaming_enabled"), + ), + }, + }, + }) +} + +func TestAccTFEOrganizationAuditConfigurationDataSource_disallowed(t *testing.T) { + skipUnlessBeta(t) + + tfeClient, err := getClientUsingEnv() + if err != nil { + t.Fatal(err) + } + + org, orgCleanup := createTrialOrganization(t, tfeClient) + t.Cleanup(orgCleanup) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV5ProviderFactories: testAccMuxedProviders, + Steps: []resource.TestStep{ + { + Config: testAccTFEOrganizationAuditConfigDataSourceConfig(org.Name), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.tfe_organization_audit_configuration.foobar", "organization", org.Name), + resource.TestCheckNoResourceAttr("data.tfe_organization_audit_configuration.foobar", "id"), + resource.TestCheckNoResourceAttr("data.tfe_organization_audit_configuration.foobar", "audit_trails_enabled"), + resource.TestCheckNoResourceAttr("data.tfe_organization_audit_configuration.foobar", "hcp_log_streaming_enabled"), + ), + }, + }, + }) +} + +func testAccTFEOrganizationAuditConfigDataSourceConfig(orgName string) string { + return fmt.Sprintf(` +locals { + organization_name = "%s" +} + +data "tfe_organization_audit_configuration" "foobar" { + organization = local.organization_name +}`, orgName) +} diff --git a/internal/provider/provider_next.go b/internal/provider/provider_next.go index a66c79402..3126589f4 100644 --- a/internal/provider/provider_next.go +++ b/internal/provider/provider_next.go @@ -131,6 +131,7 @@ func (p *frameworkProvider) Configure(ctx context.Context, req provider.Configur func (p *frameworkProvider) DataSources(ctx context.Context) []func() datasource.DataSource { return []func() datasource.DataSource{ NewNoCodeModuleDataSource, + NewOrganizationAuditConfigurationDataSource, NewOrganizationRunTaskDataSource, NewOrganizationRunTaskGlobalSettingsDataSource, NewOutputsDataSource, diff --git a/website/docs/d/organization_audit_configuration.html.markdown b/website/docs/d/organization_audit_configuration.html.markdown new file mode 100644 index 000000000..86fa508b4 --- /dev/null +++ b/website/docs/d/organization_audit_configuration.html.markdown @@ -0,0 +1,38 @@ +--- +layout: "tfe" +page_title: "Terraform Enterprise: tfe_organization_audit_configuration" +description: |- + Get information on an organization's audit configuration. +--- + +# Data Source: tfe_organization_audit_configuration + +Use this data source to get information about the audit configuration for a given organization. + +~> **NOTE:** This data source requires using the provider with HCP Terraform. + +## Example Usage + +```hcl +data "tfe_organization_audit_configuration" "example" { + organization = "my-org-name" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `organization` - (Required) Name of the organization. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The ID of the audit configuration + +* `audit_trails_enabled` - Whether or not Audit Trails is enabled as an auditing method. + +* `hcp_log_streaming_enabled` - Whether or not HCP Audit Log Streaming is enabled as an auditing method. + +* `hcp_organization` - The destination HCP Organization for HCP Audit Log Streaming.