diff --git a/.changelog/32204.txt b/.changelog/32204.txt new file mode 100644 index 00000000000..e1db85a7275 --- /dev/null +++ b/.changelog/32204.txt @@ -0,0 +1,11 @@ +```release-note:new-resource +aws_verifiedpermissions_policy_store +``` + +```release-note:new-resource +aws_verifiedpermissions_schema +``` + +```release-note:new-data-source +aws_verifiedpermissions_policy_store +``` \ No newline at end of file diff --git a/internal/service/verifiedpermissions/exports_test.go b/internal/service/verifiedpermissions/exports_test.go new file mode 100644 index 00000000000..f6061a32bbf --- /dev/null +++ b/internal/service/verifiedpermissions/exports_test.go @@ -0,0 +1,13 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package verifiedpermissions + +// Exports for use in tests only. +var ( + ResourcePolicyStore = newResourcePolicyStore + ResourceSchema = newResourceSchema + + FindPolicyStoreByID = findPolicyStoreByID + FindSchemaByPolicyStoreID = findSchemaByPolicyStoreID +) diff --git a/internal/service/verifiedpermissions/policy_store.go b/internal/service/verifiedpermissions/policy_store.go new file mode 100644 index 00000000000..4a01f3f2bdc --- /dev/null +++ b/internal/service/verifiedpermissions/policy_store.go @@ -0,0 +1,274 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package verifiedpermissions + +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions" + awstypes "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions/types" + "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/errs" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @FrameworkResource(name="Policy Store") +func newResourcePolicyStore(context.Context) (resource.ResourceWithConfigure, error) { + r := &resourcePolicyStore{} + + return r, nil +} + +const ( + ResNamePolicyStore = "Policy Store" +) + +type resourcePolicyStore struct { + framework.ResourceWithConfigure +} + +func (r *resourcePolicyStore) Metadata(_ context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) { + response.TypeName = "aws_verifiedpermissions_policy_store" +} + +func (r *resourcePolicyStore) Schema(ctx context.Context, request resource.SchemaRequest, response *resource.SchemaResponse) { + s := schema.Schema{ + Attributes: map[string]schema.Attribute{ + "arn": framework.ARNAttributeComputedOnly(), + "description": schema.StringAttribute{ + Optional: true, + }, + "id": framework.IDAttribute(), + "policy_store_id": schema.StringAttribute{ + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + }, + Blocks: map[string]schema.Block{ + "validation_settings": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[validationSettings](ctx), + Validators: []validator.List{ + listvalidator.IsRequired(), + listvalidator.SizeAtMost(1), + }, + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "mode": schema.StringAttribute{ + CustomType: fwtypes.StringEnumType[awstypes.ValidationMode](), + Required: true, + }, + }, + }, + }, + }, + } + + response.Schema = s +} + +func (r *resourcePolicyStore) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var plan resourcePolicyStoreData + + response.Diagnostics.Append(request.Plan.Get(ctx, &plan)...) + + if response.Diagnostics.HasError() { + return + } + + input := &verifiedpermissions.CreatePolicyStoreInput{} + response.Diagnostics.Append(flex.Expand(ctx, plan, input)...) + + if response.Diagnostics.HasError() { + return + } + + clientToken := id.UniqueId() + input.ClientToken = aws.String(clientToken) + + output, err := conn.CreatePolicyStore(ctx, input) + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyStore, clientToken, err), + err.Error(), + ) + return + } + + state := plan + state.ID = flex.StringToFramework(ctx, output.PolicyStoreId) + + response.Diagnostics.Append(flex.Flatten(ctx, output, &state)...) + + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(response.State.Set(ctx, &state)...) +} + +func (r *resourcePolicyStore) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var state resourcePolicyStoreData + + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + + if response.Diagnostics.HasError() { + return + } + + output, err := findPolicyStoreByID(ctx, conn, state.ID.ValueString()) + + if tfresource.NotFound(err) { + response.State.RemoveResource(ctx) + return + } + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyStore, state.PolicyStoreID.ValueString(), err), + err.Error(), + ) + return + } + + response.Diagnostics.Append(flex.Flatten(ctx, output, &state)...) + + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(response.State.Set(ctx, &state)...) +} + +func (r *resourcePolicyStore) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var state, plan resourcePolicyStoreData + + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(request.Plan.Get(ctx, &plan)...) + + if response.Diagnostics.HasError() { + return + } + + if !plan.Description.Equal(state.Description) || !plan.ValidationSettings.Equal(state.ValidationSettings) { + input := &verifiedpermissions.UpdatePolicyStoreInput{} + response.Diagnostics.Append(flex.Expand(ctx, plan, input)...) + + if response.Diagnostics.HasError() { + return + } + + output, err := conn.UpdatePolicyStore(ctx, input) + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyStore, state.PolicyStoreID.ValueString(), err), + err.Error(), + ) + return + } + + response.Diagnostics.Append(flex.Flatten(ctx, output, &plan)...) + } + + response.Diagnostics.Append(response.State.Set(ctx, &plan)...) +} + +func (r *resourcePolicyStore) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var state resourcePolicyStoreData + + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + + if response.Diagnostics.HasError() { + return + } + + tflog.Debug(ctx, "deleting Verified Permissions Policy Store", map[string]interface{}{ + "id": state.ID.ValueString(), + }) + + input := &verifiedpermissions.DeletePolicyStoreInput{ + PolicyStoreId: flex.StringFromFramework(ctx, state.ID), + } + + _, err := conn.DeletePolicyStore(ctx, input) + + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return + } + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionDeleting, ResNamePolicyStore, state.PolicyStoreID.ValueString(), err), + err.Error(), + ) + return + } +} + +func (r *resourcePolicyStore) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), request, response) +} + +type resourcePolicyStoreData struct { + ARN types.String `tfsdk:"arn"` + Description types.String `tfsdk:"description"` + ID types.String `tfsdk:"id"` + PolicyStoreID types.String `tfsdk:"policy_store_id"` + ValidationSettings fwtypes.ListNestedObjectValueOf[validationSettings] `tfsdk:"validation_settings"` +} + +type validationSettings struct { + Mode fwtypes.StringEnum[awstypes.ValidationMode] `tfsdk:"mode"` +} + +func findPolicyStoreByID(ctx context.Context, conn *verifiedpermissions.Client, id string) (*verifiedpermissions.GetPolicyStoreOutput, error) { + in := &verifiedpermissions.GetPolicyStoreInput{ + PolicyStoreId: aws.String(id), + } + + out, err := conn.GetPolicyStore(ctx, in) + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: in, + } + } + if err != nil { + return nil, err + } + + if out == nil || out.Arn == nil { + return nil, tfresource.NewEmptyResultError(in) + } + + return out, nil +} diff --git a/internal/service/verifiedpermissions/policy_store_data_source.go b/internal/service/verifiedpermissions/policy_store_data_source.go new file mode 100644 index 00000000000..ed019f502e5 --- /dev/null +++ b/internal/service/verifiedpermissions/policy_store_data_source.go @@ -0,0 +1,102 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package verifiedpermissions + +import ( + "context" + + awstypes "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions/types" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @FrameworkDataSource(name="Policy Store") +func newDataSourcePolicyStore(context.Context) (datasource.DataSourceWithConfigure, error) { + return &dataSourcePolicyStore{}, nil +} + +const ( + DSNamePolicyStore = "Policy Store Data Source" +) + +type dataSourcePolicyStore struct { + framework.DataSourceWithConfigure +} + +func (d *dataSourcePolicyStore) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name + resp.TypeName = "aws_verifiedpermissions_policy_store" +} + +func (d *dataSourcePolicyStore) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "arn": framework.ARNAttributeComputedOnly(), + "created_date": schema.StringAttribute{ + CustomType: fwtypes.TimestampType, + Computed: true, + }, + "description": schema.StringAttribute{ + Computed: true, + }, + "id": schema.StringAttribute{ + Required: true, + }, + "last_updated_date": schema.StringAttribute{ + CustomType: fwtypes.TimestampType, + Computed: true, + }, + "validation_settings": schema.ListAttribute{ + CustomType: fwtypes.NewListNestedObjectTypeOf[validationSettingsDataSource](ctx), + ElementType: fwtypes.NewObjectTypeOf[validationSettingsDataSource](ctx), + Computed: true, + }, + }, + } +} +func (d *dataSourcePolicyStore) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + conn := d.Meta().VerifiedPermissionsClient(ctx) + + var data dataSourcePolicyStoreData + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + out, err := findPolicyStoreByID(ctx, conn, data.ID.ValueString()) + + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionReading, DSNamePolicyStore, data.ID.ValueString(), err), + err.Error(), + ) + return + } + + resp.Diagnostics.Append(flex.Flatten(ctx, out, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +type dataSourcePolicyStoreData struct { + ARN types.String `tfsdk:"arn"` + CreatedDate fwtypes.Timestamp `tfsdk:"created_date"` + Description types.String `tfsdk:"description"` + ID types.String `tfsdk:"id"` + LastUpdatedDate fwtypes.Timestamp `tfsdk:"last_updated_date"` + ValidationSettings fwtypes.ListNestedObjectValueOf[validationSettingsDataSource] `tfsdk:"validation_settings"` +} + +type validationSettingsDataSource struct { + Mode fwtypes.StringEnum[awstypes.ValidationMode] `tfsdk:"mode"` +} diff --git a/internal/service/verifiedpermissions/policy_store_data_source_test.go b/internal/service/verifiedpermissions/policy_store_data_source_test.go new file mode 100644 index 00000000000..ed400172636 --- /dev/null +++ b/internal/service/verifiedpermissions/policy_store_data_source_test.go @@ -0,0 +1,64 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package verifiedpermissions_test + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccVerifiedPermissionsPolicyStoreDataSource_basic(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var policystore verifiedpermissions.GetPolicyStoreOutput + dataSourceName := "data.aws_verifiedpermissions_policy_store.test" + resourceName := "aws_verifiedpermissions_policy_store.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.VerifiedPermissionsEndpointID) + testAccPolicyStoresPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissionsEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckPolicyStoreDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccPolicyStoreDataSourceConfig_basic("OFF"), + Check: resource.ComposeTestCheckFunc( + testAccCheckPolicyStoreExists(ctx, dataSourceName, &policystore), + resource.TestCheckResourceAttrPair(resourceName, "validation_settings.0.mode", dataSourceName, "validation_settings.0.mode"), + resource.TestCheckResourceAttrPair(resourceName, "description", dataSourceName, "description"), + resource.TestCheckResourceAttrPair(resourceName, "arn", dataSourceName, "arn"), + resource.TestCheckResourceAttrSet(dataSourceName, "created_date"), + resource.TestCheckResourceAttrSet(dataSourceName, "last_updated_date"), + ), + }, + }, + }) +} + +func testAccPolicyStoreDataSourceConfig_basic(mode string) string { + return fmt.Sprintf(` +resource "aws_verifiedpermissions_policy_store" "test" { + description = "Terraform acceptance test" + validation_settings { + mode = %[1]q + } +} + +data "aws_verifiedpermissions_policy_store" "test" { + id = aws_verifiedpermissions_policy_store.test.id +} +`, mode) +} diff --git a/internal/service/verifiedpermissions/policy_store_test.go b/internal/service/verifiedpermissions/policy_store_test.go new file mode 100644 index 00000000000..6a28d6464d3 --- /dev/null +++ b/internal/service/verifiedpermissions/policy_store_test.go @@ -0,0 +1,200 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package verifiedpermissions_test + +import ( + "context" + "errors" + "fmt" + "testing" + + "github.com/YakDriver/regexache" + "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/create" + tfverifiedpermissions "github.com/hashicorp/terraform-provider-aws/internal/service/verifiedpermissions" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccVerifiedPermissionsPolicyStore_basic(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var policystore verifiedpermissions.GetPolicyStoreOutput + resourceName := "aws_verifiedpermissions_policy_store.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.VerifiedPermissionsEndpointID) + testAccPolicyStoresPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissionsEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckPolicyStoreDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccPolicyStoreConfig_basic("OFF"), + Check: resource.ComposeTestCheckFunc( + testAccCheckPolicyStoreExists(ctx, resourceName, &policystore), + resource.TestCheckResourceAttr(resourceName, "validation_settings.0.mode", "OFF"), + resource.TestCheckResourceAttr(resourceName, "description", "Terraform acceptance test"), + acctest.MatchResourceAttrGlobalARN(resourceName, "arn", "verifiedpermissions", regexache.MustCompile(`policy-store/+.`)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccVerifiedPermissionsPolicyStore_update(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var policystore verifiedpermissions.GetPolicyStoreOutput + resourceName := "aws_verifiedpermissions_policy_store.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.VerifiedPermissionsEndpointID) + testAccPolicyStoresPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissionsEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckPolicyStoreDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccPolicyStoreConfig_basic("OFF"), + Check: resource.ComposeTestCheckFunc( + testAccCheckPolicyStoreExists(ctx, resourceName, &policystore), + resource.TestCheckResourceAttr(resourceName, "validation_settings.0.mode", "OFF"), + ), + }, + { + Config: testAccPolicyStoreConfig_basic("STRICT"), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "validation_settings.0.mode", "STRICT"), + ), + }, + }, + }) +} + +func TestAccVerifiedPermissionsPolicyStore_disappears(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var policystore verifiedpermissions.GetPolicyStoreOutput + resourceName := "aws_verifiedpermissions_policy_store.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.VerifiedPermissionsEndpointID) + testAccPolicyStoresPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissionsEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckPolicyStoreDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccPolicyStoreConfig_basic("OFF"), + Check: resource.ComposeTestCheckFunc( + testAccCheckPolicyStoreExists(ctx, resourceName, &policystore), + acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfverifiedpermissions.ResourcePolicyStore, resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckPolicyStoreDestroy(ctx context.Context) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).VerifiedPermissionsClient(ctx) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_verifiedpermissions_policy_store" { + continue + } + + _, err := tfverifiedpermissions.FindPolicyStoreByID(ctx, conn, rs.Primary.ID) + + if tfresource.NotFound(err) { + continue + } + + if err != nil { + return err + } + + return create.Error(names.VerifiedPermissions, create.ErrActionCheckingDestroyed, tfverifiedpermissions.ResNamePolicyStore, rs.Primary.ID, errors.New("not destroyed")) + } + + return nil + } +} + +func testAccCheckPolicyStoreExists(ctx context.Context, name string, policystore *verifiedpermissions.GetPolicyStoreOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return create.Error(names.VerifiedPermissions, create.ErrActionCheckingExistence, tfverifiedpermissions.ResNamePolicyStore, name, errors.New("not found")) + } + + if rs.Primary.ID == "" { + return create.Error(names.VerifiedPermissions, create.ErrActionCheckingExistence, tfverifiedpermissions.ResNamePolicyStore, name, errors.New("not set")) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).VerifiedPermissionsClient(ctx) + resp, err := tfverifiedpermissions.FindPolicyStoreByID(ctx, conn, rs.Primary.ID) + + if err != nil { + return create.Error(names.VerifiedPermissions, create.ErrActionCheckingExistence, tfverifiedpermissions.ResNamePolicyStore, rs.Primary.ID, err) + } + + *policystore = *resp + + return nil + } +} + +func testAccPolicyStoresPreCheck(ctx context.Context, t *testing.T) { + conn := acctest.Provider.Meta().(*conns.AWSClient).VerifiedPermissionsClient(ctx) + + input := &verifiedpermissions.ListPolicyStoresInput{} + _, err := conn.ListPolicyStores(ctx, input) + + if acctest.PreCheckSkipError(err) { + t.Skipf("skipping acceptance testing: %s", err) + } + if err != nil { + t.Fatalf("unexpected PreCheck error: %s", err) + } +} + +func testAccPolicyStoreConfig_basic(mode string) string { + return fmt.Sprintf(` +resource "aws_verifiedpermissions_policy_store" "test" { + description = "Terraform acceptance test" + validation_settings { + mode = %[1]q + } +}`, mode) +} diff --git a/internal/service/verifiedpermissions/schema.go b/internal/service/verifiedpermissions/schema.go new file mode 100644 index 00000000000..4049a556175 --- /dev/null +++ b/internal/service/verifiedpermissions/schema.go @@ -0,0 +1,323 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package verifiedpermissions + +import ( + "context" + "encoding/json" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions" + awstypes "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions/types" + "github.com/hashicorp/terraform-plugin-framework-validators/objectvalidator" + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/errs" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + fwvalidators "github.com/hashicorp/terraform-provider-aws/internal/framework/validators" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @FrameworkResource(name="Schema") +func newResourceSchema(context.Context) (resource.ResourceWithConfigure, error) { + r := &resourceSchema{} + + return r, nil +} + +const ( + ResNamePolicyStoreSchema = "Schema" +) + +type resourceSchema struct { + framework.ResourceWithConfigure +} + +func (r *resourceSchema) Metadata(_ context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) { + response.TypeName = "aws_verifiedpermissions_schema" +} + +func (r *resourceSchema) Schema(ctx context.Context, request resource.SchemaRequest, response *resource.SchemaResponse) { + s := schema.Schema{ + Attributes: map[string]schema.Attribute{ + "id": framework.IDAttribute(), + "namespaces": schema.SetAttribute{ + ElementType: types.StringType, + Computed: true, + }, + "policy_store_id": schema.StringAttribute{ + Required: true, + }, + }, + Blocks: map[string]schema.Block{ + "definition": schema.SingleNestedBlock{ + Validators: []validator.Object{ + objectvalidator.IsRequired(), + }, + Attributes: map[string]schema.Attribute{ + "value": schema.StringAttribute{ + Required: true, + Validators: []validator.String{ + fwvalidators.JSON(), + }, + }, + }, + }, + }, + } + + response.Schema = s +} + +func (r *resourceSchema) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var plan resourceSchemaData + + response.Diagnostics.Append(request.Plan.Get(ctx, &plan)...) + + if response.Diagnostics.HasError() { + return + } + + input := &verifiedpermissions.PutSchemaInput{ + PolicyStoreId: flex.StringFromFramework(ctx, plan.PolicyStoreID), + Definition: expandDefinition(ctx, plan.Definition, &response.Diagnostics), + } + + if response.Diagnostics.HasError() { + return + } + + output, err := conn.PutSchema(ctx, input) + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyStoreSchema, plan.PolicyStoreID.ValueString(), err), + err.Error(), + ) + return + } + + state := plan + state.ID = flex.StringToFramework(ctx, output.PolicyStoreId) + + state.Namespaces = flex.FlattenFrameworkStringValueSet(ctx, output.Namespaces) + + response.Diagnostics.Append(response.State.Set(ctx, &state)...) +} + +func (r *resourceSchema) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var state resourceSchemaData + + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + + if response.Diagnostics.HasError() { + return + } + + output, err := findSchemaByPolicyStoreID(ctx, conn, state.ID.ValueString()) + + if tfresource.NotFound(err) { + response.State.RemoveResource(ctx) + return + } + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyStoreSchema, state.PolicyStoreID.ValueString(), err), + err.Error(), + ) + return + } + + state.PolicyStoreID = flex.StringToFramework(ctx, output.PolicyStoreId) + state.Namespaces = flex.FlattenFrameworkStringValueSet(ctx, output.Namespaces) + state.Definition = flattenDefinition(ctx, output, &response.Diagnostics) + + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(response.State.Set(ctx, &state)...) +} + +func (r *resourceSchema) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var state, plan resourceSchemaData + + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(request.Plan.Get(ctx, &plan)...) + + if response.Diagnostics.HasError() { + return + } + + if !plan.Definition.Equal(state.Definition) { + input := &verifiedpermissions.PutSchemaInput{ + PolicyStoreId: flex.StringFromFramework(ctx, state.ID), + Definition: expandDefinition(ctx, plan.Definition, &response.Diagnostics), + } + + if response.Diagnostics.HasError() { + return + } + + _, err := conn.PutSchema(ctx, input) + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyStoreSchema, state.PolicyStoreID.ValueString(), err), + err.Error(), + ) + return + } + + out, err := findSchemaByPolicyStoreID(ctx, conn, state.ID.ValueString()) + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyStoreSchema, state.PolicyStoreID.ValueString(), err), + err.Error(), + ) + return + } + + plan.Namespaces = flex.FlattenFrameworkStringValueSet(ctx, out.Namespaces) + } + + response.Diagnostics.Append(response.State.Set(ctx, &plan)...) +} + +func (r *resourceSchema) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var state resourceSchemaData + + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + + if response.Diagnostics.HasError() { + return + } + + tflog.Debug(ctx, "deleting Verified Permissions Policy Store Schema", map[string]interface{}{ + "id": state.ID.ValueString(), + }) + + input := &verifiedpermissions.PutSchemaInput{ + PolicyStoreId: flex.StringFromFramework(ctx, state.ID), + Definition: &awstypes.SchemaDefinitionMemberCedarJson{ + Value: "{}", + }, + } + + _, err := conn.PutSchema(ctx, input) + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionDeleting, ResNamePolicyStoreSchema, state.PolicyStoreID.ValueString(), err), + err.Error(), + ) + return + } +} + +func (r *resourceSchema) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), request, response) +} + +type resourceSchemaData struct { + ID types.String `tfsdk:"id"` + Definition types.Object `tfsdk:"definition"` + Namespaces types.Set `tfsdk:"namespaces"` + PolicyStoreID types.String `tfsdk:"policy_store_id"` +} + +type definition struct { + Value types.String `tfsdk:"value"` +} + +func findSchemaByPolicyStoreID(ctx context.Context, conn *verifiedpermissions.Client, id string) (*verifiedpermissions.GetSchemaOutput, error) { + in := &verifiedpermissions.GetSchemaInput{ + PolicyStoreId: aws.String(id), + } + + out, err := conn.GetSchema(ctx, in) + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: in, + } + } + if err != nil { + return nil, err + } + + if out == nil || out.Schema == nil { + return nil, tfresource.NewEmptyResultError(in) + } + + return out, nil +} + +func expandDefinition(ctx context.Context, object types.Object, diags *diag.Diagnostics) *awstypes.SchemaDefinitionMemberCedarJson { + var de definition + diags.Append(object.As(ctx, &de, basetypes.ObjectAsOptions{})...) + if diags.HasError() { + return nil + } + + out := &awstypes.SchemaDefinitionMemberCedarJson{ + Value: de.Value.ValueString(), + } + + return out +} + +func flattenDefinition(ctx context.Context, input *verifiedpermissions.GetSchemaOutput, diags *diag.Diagnostics) types.Object { + if input == nil { + return fwtypes.NewObjectValueOfNull[definition](ctx).ObjectValue + } + + var data any + err := json.Unmarshal([]byte(aws.ToString(input.Schema)), &data) + if err != nil { + diags.AddError( + "unable to unmarshal schema", + err.Error(), + ) + return fwtypes.NewObjectValueOfNull[definition](ctx).ObjectValue + } + + val, err := json.Marshal(data) + if err != nil { + diags.AddError( + "unable to marshal schema", + err.Error(), + ) + return fwtypes.NewObjectValueOfNull[definition](ctx).ObjectValue + } + + attributeTypes := fwtypes.AttributeTypesMust[definition](ctx) + attrs := map[string]attr.Value{} + attrs["value"] = flex.StringValueToFramework(ctx, string(val)) + + return types.ObjectValueMust(attributeTypes, attrs) +} diff --git a/internal/service/verifiedpermissions/schema_test.go b/internal/service/verifiedpermissions/schema_test.go new file mode 100644 index 00000000000..11e459ca118 --- /dev/null +++ b/internal/service/verifiedpermissions/schema_test.go @@ -0,0 +1,192 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package verifiedpermissions_test + +import ( + "context" + "errors" + "fmt" + "testing" + + "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/create" + tfverifiedpermissions "github.com/hashicorp/terraform-provider-aws/internal/service/verifiedpermissions" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccVerifiedPermissionsSchema_basic(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var schema verifiedpermissions.GetSchemaOutput + resourceName := "aws_verifiedpermissions_schema.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.VerifiedPermissionsEndpointID) + testAccPolicyStoresPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissionsEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckSchemaDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccSchemaConfig_basic("NAMESPACE"), + Check: resource.ComposeTestCheckFunc( + testAccCheckSchemaExists(ctx, resourceName, &schema), + resource.TestCheckTypeSetElemAttr(resourceName, "namespaces.*", "NAMESPACE"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccVerifiedPermissionsSchema_update(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var schema verifiedpermissions.GetSchemaOutput + resourceName := "aws_verifiedpermissions_schema.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.VerifiedPermissionsEndpointID) + testAccPolicyStoresPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissionsEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckSchemaDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccSchemaConfig_basic("NAMESPACE"), + Check: resource.ComposeTestCheckFunc( + testAccCheckSchemaExists(ctx, resourceName, &schema), + resource.TestCheckTypeSetElemAttr(resourceName, "namespaces.*", "NAMESPACE"), + ), + }, + { + Config: testAccSchemaConfig_basic("CHANGED"), + Check: resource.ComposeTestCheckFunc( + testAccCheckSchemaExists(ctx, resourceName, &schema), + resource.TestCheckTypeSetElemAttr(resourceName, "namespaces.*", "CHANGED"), + ), + }, + }, + }) +} + +func TestAccVerifiedPermissionsSchema_disappears(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var schema verifiedpermissions.GetSchemaOutput + resourceName := "aws_verifiedpermissions_schema.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.VerifiedPermissionsEndpointID) + testAccPolicyStoresPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissionsEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckSchemaDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccSchemaConfig_basic("NAMESPACE"), + Check: resource.ComposeTestCheckFunc( + testAccCheckSchemaExists(ctx, resourceName, &schema), + acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfverifiedpermissions.ResourceSchema, resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckSchemaDestroy(ctx context.Context) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).VerifiedPermissionsClient(ctx) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_verifiedpermissions_schema" { + continue + } + + _, err := tfverifiedpermissions.FindSchemaByPolicyStoreID(ctx, conn, rs.Primary.ID) + + if tfresource.NotFound(err) { + continue + } + + if err != nil { + return err + } + + return create.Error(names.VerifiedPermissions, create.ErrActionCheckingDestroyed, tfverifiedpermissions.ResNamePolicyStoreSchema, rs.Primary.ID, errors.New("not destroyed")) + } + + return nil + } +} + +func testAccCheckSchemaExists(ctx context.Context, name string, schema *verifiedpermissions.GetSchemaOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return create.Error(names.VerifiedPermissions, create.ErrActionCheckingExistence, tfverifiedpermissions.ResNamePolicyStoreSchema, name, errors.New("not found")) + } + + if rs.Primary.ID == "" { + return create.Error(names.VerifiedPermissions, create.ErrActionCheckingExistence, tfverifiedpermissions.ResNamePolicyStoreSchema, name, errors.New("not set")) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).VerifiedPermissionsClient(ctx) + resp, err := tfverifiedpermissions.FindSchemaByPolicyStoreID(ctx, conn, rs.Primary.ID) + + if err != nil { + return create.Error(names.VerifiedPermissions, create.ErrActionCheckingExistence, tfverifiedpermissions.ResNamePolicyStoreSchema, rs.Primary.ID, err) + } + + *schema = *resp + + return nil + } +} + +func testAccSchemaConfig_basic(namespace string) string { + return fmt.Sprintf(` +resource "aws_verifiedpermissions_policy_store" "test" { + description = "Terraform acceptance test" + validation_settings { + mode = "STRICT" + } +} + +resource "aws_verifiedpermissions_schema" "test" { + policy_store_id = aws_verifiedpermissions_policy_store.test.policy_store_id + + definition { + value = "{\"%[1]s\":{\"actions\":{},\"entityTypes\":{}}}" + } +}`, namespace) +} diff --git a/internal/service/verifiedpermissions/service_package_gen.go b/internal/service/verifiedpermissions/service_package_gen.go index 39166c46f0d..38544b542f4 100644 --- a/internal/service/verifiedpermissions/service_package_gen.go +++ b/internal/service/verifiedpermissions/service_package_gen.go @@ -15,11 +15,25 @@ import ( type servicePackage struct{} func (p *servicePackage) FrameworkDataSources(ctx context.Context) []*types.ServicePackageFrameworkDataSource { - return []*types.ServicePackageFrameworkDataSource{} + return []*types.ServicePackageFrameworkDataSource{ + { + Factory: newDataSourcePolicyStore, + Name: "Policy Store", + }, + } } func (p *servicePackage) FrameworkResources(ctx context.Context) []*types.ServicePackageFrameworkResource { - return []*types.ServicePackageFrameworkResource{} + return []*types.ServicePackageFrameworkResource{ + { + Factory: newResourcePolicyStore, + Name: "Policy Store", + }, + { + Factory: newResourceSchema, + Name: "Schema", + }, + } } func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePackageSDKDataSource { diff --git a/names/names.go b/names/names.go index 7e662128ae2..ca113a0aa02 100644 --- a/names/names.go +++ b/names/names.go @@ -93,6 +93,7 @@ const ( SWFEndpointID = "swf" TimestreamWriteEndpointID = "ingest.timestream" TranscribeEndpointID = "transcribe" + VerifiedPermissionsEndpointID = "verifiedpermissions" VPCLatticeEndpointID = "vpc-lattice" XRayEndpointID = "xray" ) diff --git a/website/docs/d/verifiedpermissions_policy_store.html.markdown b/website/docs/d/verifiedpermissions_policy_store.html.markdown new file mode 100644 index 00000000000..e75674e10bd --- /dev/null +++ b/website/docs/d/verifiedpermissions_policy_store.html.markdown @@ -0,0 +1,36 @@ +--- +subcategory: "Verified Permissions" +layout: "aws" +page_title: "AWS: aws_verifiedpermissions_policy_store" +description: |- + Terraform data source for managing an AWS Verified Permissions Policy Store. +--- + +# Data Source: aws_verifiedpermissions_policy_store + +Terraform data source for managing an AWS Verified Permissions Policy Store. + +## Example Usage + +### Basic Usage + +```terraform +data "aws_verifiedpermissions_policy_store" "example" { + id = "example" +} +``` + +## Argument Reference + +The following arguments are required: + +* `id` - (Required) The ID of the Policy Store. + +## Attribute Reference + +This data source exports the following attributes in addition to the arguments above: + +* `arn` - The ARN of the Policy Store. +* `created_date` - The date the Policy Store was created. +* `last_updated_date` - The date the Policy Store was last updated. +* `validation_settings` - Validation settings for the policy store. diff --git a/website/docs/r/verifiedpermissions_policy_store.html.markdown b/website/docs/r/verifiedpermissions_policy_store.html.markdown new file mode 100644 index 00000000000..a16ffd03b46 --- /dev/null +++ b/website/docs/r/verifiedpermissions_policy_store.html.markdown @@ -0,0 +1,58 @@ +--- +subcategory: "Verified Permissions" +layout: "aws" +page_title: "AWS: aws_verifiedpermissions_policy_store" +description: |- + This is a Terraform resource for managing an AWS Verified Permissions Policy Store. +--- + +# Resource: aws_verifiedpermissions_policy_store + +This is a Terraform resource for managing an AWS Verified Permissions Policy Store. + +## Example Usage + +### Basic Usage + +```terraform +resource "aws_verifiedpermissions_policy_store" "example" { + validation_settings { + mode = "STRICT" + } +} +``` + +## Argument Reference + +The following arguments are required: + +* `validation_settings` - (Required) Validation settings for the policy store. + * `mode` - (Required) The mode for the validation settings. Valid values: `OFF`, `STRICT`. + +The following arguments are optional: + +* `description` - (Optional) A description of the Policy Store. + +## Attribute Reference + +This resource exports the following attributes in addition to the arguments above: + +* `policy_store_id` - The ID of the Policy Store. +* `arn` - The ARN of the Policy Store. + +## Import + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import Verified Permissions Policy Store using the `policy_store_id`. For example: + +```terraform +import { + to = aws_verifiedpermissions_policy_store.example + id = "DxQg2j8xvXJQ1tQCYNWj9T" +} +``` + +Using `terraform import`, import Verified Permissions Policy Store using the `policy_store_id`. For example: + +```console + % terraform import aws_verifiedpermissions_policy_store.example DxQg2j8xvXJQ1tQCYNWj9T +``` diff --git a/website/docs/r/verifiedpermissions_schema.html.markdown b/website/docs/r/verifiedpermissions_schema.html.markdown new file mode 100644 index 00000000000..1397648c790 --- /dev/null +++ b/website/docs/r/verifiedpermissions_schema.html.markdown @@ -0,0 +1,61 @@ +--- +subcategory: "Verified Permissions" +layout: "aws" +page_title: "AWS: aws_verifiedpermissions_schema" +description: |- + This is a Terraform resource for managing an AWS Verified Permissions Policy Store Schema. +--- + +# Resource: aws_verifiedpermissions_schema + +This is a Terraform resource for managing an AWS Verified Permissions Policy Store Schema. + +## Example Usage + +### Basic Usage + +```terraform +resource "aws_verifiedpermissions_schema" "example" { + policy_store_id = aws_verifiedpermissions_policy_store.example.policy_store_id + + definition { + value = jsonencode({ + "Namespace" : { + "entityTypes" : {}, + "actions" : {} + } + }) + } +} +``` + +## Argument Reference + +The following arguments are required: + +* `policy_store_id` - (Required) The ID of the Policy Store. +* `definition` - (Required) The definition of the schema. + * `value` - (Required) A JSON string representation of the schema. + +## Attribute Reference + +This resource exports the following attributes in addition to the arguments above: + +* `namespaces` - (Optional) Identifies the namespaces of the entities referenced by this schema. + +## Import + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import Verified Permissions Policy Store using the `policy_store_id`. For example: + +```terraform +import { + to = aws_verifiedpermissions_schema.example + id = "DxQg2j8xvXJQ1tQCYNWj9T" +} +``` + +Using `terraform import`, import Verified Permissions Policy Store Schema using the `policy_store_id`. For example: + +```console + % terraform import aws_verifiedpermissions_schema.example DxQg2j8xvXJQ1tQCYNWj9T +```