Skip to content
Open
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
3 changes: 3 additions & 0 deletions .changelog/45344.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_bedrockagentcore_gateway: Add `interceptor_configurations` argument
```
148 changes: 132 additions & 16 deletions internal/service/bedrockagentcore/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,59 @@ func (r *gatewayResource) Schema(ctx context.Context, request resource.SchemaReq
},
},
},
"interceptor_configurations": schema.ListNestedBlock{
CustomType: fwtypes.NewListNestedObjectTypeOf[gatewayInterceptorConfigurationModel](ctx),
Validators: []validator.List{
listvalidator.SizeBetween(1, 2),
},
NestedObject: schema.NestedBlockObject{
Attributes: map[string]schema.Attribute{
"interception_points": schema.SetAttribute{
CustomType: fwtypes.SetOfStringType,
Required: true,
},
},
Blocks: map[string]schema.Block{
"input_configuration": schema.ListNestedBlock{
CustomType: fwtypes.NewListNestedObjectTypeOf[interceptorInputConfigurationModel](ctx),
Validators: []validator.List{
listvalidator.SizeAtMost(1),
},
NestedObject: schema.NestedBlockObject{
Attributes: map[string]schema.Attribute{
"pass_request_headers": schema.BoolAttribute{
Required: true,
},
},
},
},
"interceptor": schema.ListNestedBlock{
CustomType: fwtypes.NewListNestedObjectTypeOf[interceptorConfigurationModel](ctx),
Validators: []validator.List{
listvalidator.SizeAtMost(1),
},
NestedObject: schema.NestedBlockObject{
Blocks: map[string]schema.Block{
"lambda": schema.ListNestedBlock{
CustomType: fwtypes.NewListNestedObjectTypeOf[lambdaInterceptorConfigurationModel](ctx),
Validators: []validator.List{
listvalidator.SizeAtMost(1),
},
NestedObject: schema.NestedBlockObject{
Attributes: map[string]schema.Attribute{
names.AttrARN: schema.StringAttribute{
CustomType: fwtypes.ARNType,
Required: true,
},
},
},
},
},
},
},
},
},
},
"protocol_configuration": schema.ListNestedBlock{
CustomType: fwtypes.NewListNestedObjectTypeOf[gatewayProtocolConfigurationModel](ctx),
Validators: []validator.List{
Expand Down Expand Up @@ -455,22 +508,23 @@ func findGateway(ctx context.Context, conn *bedrockagentcorecontrol.Client, inpu

type gatewayResourceModel struct {
framework.WithRegionModel
AuthorizerConfiguration fwtypes.ListNestedObjectValueOf[authorizerConfigurationModel] `tfsdk:"authorizer_configuration"`
AuthorizerType fwtypes.StringEnum[awstypes.AuthorizerType] `tfsdk:"authorizer_type"`
Description types.String `tfsdk:"description"`
ExceptionLevel fwtypes.StringEnum[awstypes.ExceptionLevel] `tfsdk:"exception_level"`
GatewayARN types.String `tfsdk:"gateway_arn"`
GatewayID types.String `tfsdk:"gateway_id"`
GatewayURL types.String `tfsdk:"gateway_url"`
KMSKeyARN fwtypes.ARN `tfsdk:"kms_key_arn"`
Name types.String `tfsdk:"name"`
ProtocolConfiguration fwtypes.ListNestedObjectValueOf[gatewayProtocolConfigurationModel] `tfsdk:"protocol_configuration"`
ProtocolType fwtypes.StringEnum[awstypes.GatewayProtocolType] `tfsdk:"protocol_type"`
RoleARN fwtypes.ARN `tfsdk:"role_arn"`
Tags tftags.Map `tfsdk:"tags"`
TagsAll tftags.Map `tfsdk:"tags_all"`
Timeouts timeouts.Value `tfsdk:"timeouts"`
WorkloadIdentityDetails fwtypes.ListNestedObjectValueOf[workloadIdentityDetailsModel] `tfsdk:"workload_identity_details"`
AuthorizerConfiguration fwtypes.ListNestedObjectValueOf[authorizerConfigurationModel] `tfsdk:"authorizer_configuration"`
AuthorizerType fwtypes.StringEnum[awstypes.AuthorizerType] `tfsdk:"authorizer_type"`
Description types.String `tfsdk:"description"`
ExceptionLevel fwtypes.StringEnum[awstypes.ExceptionLevel] `tfsdk:"exception_level"`
GatewayARN types.String `tfsdk:"gateway_arn"`
GatewayID types.String `tfsdk:"gateway_id"`
GatewayURL types.String `tfsdk:"gateway_url"`
InterceptorConfigurations fwtypes.ListNestedObjectValueOf[gatewayInterceptorConfigurationModel] `tfsdk:"interceptor_configurations"`
KMSKeyARN fwtypes.ARN `tfsdk:"kms_key_arn"`
Name types.String `tfsdk:"name"`
ProtocolConfiguration fwtypes.ListNestedObjectValueOf[gatewayProtocolConfigurationModel] `tfsdk:"protocol_configuration"`
ProtocolType fwtypes.StringEnum[awstypes.GatewayProtocolType] `tfsdk:"protocol_type"`
RoleARN fwtypes.ARN `tfsdk:"role_arn"`
Tags tftags.Map `tfsdk:"tags"`
TagsAll tftags.Map `tfsdk:"tags_all"`
Timeouts timeouts.Value `tfsdk:"timeouts"`
WorkloadIdentityDetails fwtypes.ListNestedObjectValueOf[workloadIdentityDetailsModel] `tfsdk:"workload_identity_details"`
}

type gatewayProtocolConfigurationModel struct {
Expand Down Expand Up @@ -526,3 +580,65 @@ type mcpGatewayConfigurationModel struct {
SearchType fwtypes.StringEnum[awstypes.SearchType] `tfsdk:"search_type"`
SupportedVersions fwtypes.SetOfString `tfsdk:"supported_versions"`
}

type gatewayInterceptorConfigurationModel struct {
InputConfiguration fwtypes.ListNestedObjectValueOf[interceptorInputConfigurationModel] `tfsdk:"input_configuration"`
InterceptionPoints fwtypes.SetOfString `tfsdk:"interception_points"`
Interceptor fwtypes.ListNestedObjectValueOf[interceptorConfigurationModel] `tfsdk:"interceptor"`
}

type interceptorInputConfigurationModel struct {
PassRequestHeaders types.Bool `tfsdk:"pass_request_headers"`
}

type interceptorConfigurationModel struct {
Lambda fwtypes.ListNestedObjectValueOf[lambdaInterceptorConfigurationModel] `tfsdk:"lambda"`
}

var (
_ fwflex.Expander = interceptorConfigurationModel{}
_ fwflex.Flattener = &interceptorConfigurationModel{}
)

func (m *interceptorConfigurationModel) Flatten(ctx context.Context, v any) diag.Diagnostics {
var diags diag.Diagnostics
switch t := v.(type) {
case awstypes.InterceptorConfigurationMemberLambda:
var data lambdaInterceptorConfigurationModel
smerr.AddEnrich(ctx, &diags, fwflex.Flatten(ctx, t.Value, &data))
if diags.HasError() {
return diags
}
m.Lambda = fwtypes.NewListNestedObjectValueOfPtrMust(ctx, &data)

default:
diags.AddError(
"Unsupported Type",
fmt.Sprintf("interceptor configuration flatten: %T", v),
)
}
return diags
}

func (m interceptorConfigurationModel) Expand(ctx context.Context) (any, diag.Diagnostics) {
var diags diag.Diagnostics
switch {
case !m.Lambda.IsNull():
data, d := m.Lambda.ToPtr(ctx)
smerr.AddEnrich(ctx, &diags, d)
if diags.HasError() {
return nil, diags
}
var r awstypes.InterceptorConfigurationMemberLambda
smerr.AddEnrich(ctx, &diags, fwflex.Expand(ctx, data, &r.Value))
if diags.HasError() {
return nil, diags
}
return &r, diags
}
return nil, diags
}

type lambdaInterceptorConfigurationModel struct {
ARN fwtypes.ARN `tfsdk:"arn"`
}
85 changes: 85 additions & 0 deletions internal/service/bedrockagentcore/gateway_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,42 @@ func TestAccBedrockAgentCoreGateway_tags(t *testing.T) {
})
}

func TestAccBedrockAgentCoreGateway_interceptorConfigurations(t *testing.T) {
ctx := acctest.Context(t)
var gateway bedrockagentcorecontrol.GetGatewayOutput
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_bedrockagentcore_gateway.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
acctest.PreCheck(ctx, t)
acctest.PreCheckPartitionHasService(t, names.BedrockEndpointID)
testAccPreCheckGateways(ctx, t)
},
ErrorCheck: acctest.ErrorCheck(t, names.BedrockAgentCoreServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckGatewayDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccGatewayConfig_interceptorConfigurations(rName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckGatewayExists(ctx, resourceName, &gateway),
),
ConfigStateChecks: []statecheck.StateCheck{
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("interceptor_configurations"), knownvalue.ListSizeExact(1)),
},
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateIdFunc: acctest.AttrImportStateIdFunc(resourceName, "gateway_id"),
ImportStateVerify: true,
ImportStateVerifyIdentifierAttribute: "gateway_id",
},
},
})
}

func TestAccBedrockAgentCoreGateway_description(t *testing.T) {
ctx := acctest.Context(t)
var gateway bedrockagentcorecontrol.GetGatewayOutput
Expand Down Expand Up @@ -696,3 +732,52 @@ resource "aws_bedrockagentcore_gateway" "test" {
}
`, rName, tagKey1, tagValue1, tagKey2, tagValue2))
}

func testAccGatewayConfig_interceptorConfigurations(rName string) string {
return acctest.ConfigCompose(testAccGatewayConfig_iamRole(rName), fmt.Sprintf(`
resource "aws_lambda_function" "test" {
filename = "test-fixtures/lambdatest.zip"
function_name = %[1]q
role = aws_iam_role.lambda.arn
handler = "index.handler"
runtime = "python3.12"
}

resource "aws_iam_role" "lambda" {
name = "%[1]s-lambda"

assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "lambda.amazonaws.com"
}
}]
})
}

resource "aws_bedrockagentcore_gateway" "test" {
name = %[1]q
role_arn = aws_iam_role.test.arn

authorizer_type = "AWS_IAM"
protocol_type = "MCP"

interceptor_configurations {
interception_points = ["REQUEST", "RESPONSE"]

interceptor {
lambda {
arn = aws_lambda_function.test.arn
}
}

input_configuration {
pass_request_headers = true
}
}
}
`, rName))
}
61 changes: 61 additions & 0 deletions website/docs/r/bedrockagentcore_gateway.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,40 @@ resource "aws_bedrockagentcore_gateway" "example" {
}
```

### Gateway with Interceptor Configuration

```terraform
resource "aws_lambda_function" "interceptor" {
filename = "interceptor.zip"
function_name = "gateway-interceptor"
role = aws_iam_role.lambda.arn
handler = "index.handler"
runtime = "python3.12"
}

resource "aws_bedrockagentcore_gateway" "example" {
name = "gateway-with-interceptor"
role_arn = aws_iam_role.example.arn

authorizer_type = "AWS_IAM"
protocol_type = "MCP"

interceptor_configurations {
interception_points = ["REQUEST", "RESPONSE"]

interceptor {
lambda {
arn = aws_lambda_function.interceptor.arn
}
}

input_configuration {
pass_request_headers = true
}
}
}
```

## Argument Reference

The following arguments are required:
Expand All @@ -90,6 +124,7 @@ The following arguments are optional:
* `authorizer_configuration` - (Optional) Configuration for request authorization. Required when `authorizer_type` is set to `CUSTOM_JWT`. See [`authorizer_configuration`](#authorizer_configuration) below.
* `description` - (Optional) Description of the gateway.
* `exception_level` - (Optional) Exception level for the gateway. Valid values: `INFO`, `WARN`, `ERROR`.
* `interceptor_configurations` - (Optional) List of interceptor configurations for the gateway. Minimum of 1, maximum of 2. See [`interceptor_configurations`](#interceptor_configurations) below.
* `kms_key_arn` - (Optional) ARN of the KMS key used to encrypt the gateway data.
* `protocol_configuration` - (Optional) Protocol-specific configuration for the gateway. See [`protocol_configuration`](#protocol_configuration) below.
* `tags` - (Optional) Key-value map of resource tags. If configured with a provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level.
Expand All @@ -108,6 +143,32 @@ The `custom_jwt_authorizer` block supports the following:
* `allowed_audience` - (Optional) Set of allowed audience values for JWT token validation.
* `allowed_clients` - (Optional) Set of allowed client IDs for JWT token validation.

### `interceptor_configurations`

The `interceptor_configurations` block supports the following:

* `interception_points` - (Required) Set of interception points. Valid values: `REQUEST`, `RESPONSE`.
* `interceptor` - (Required) Interceptor infrastructure configuration. See [`interceptor`](#interceptor) below.
* `input_configuration` - (Optional) Input configuration for the interceptor. See [`input_configuration`](#input_configuration) below.

### `interceptor`

The `interceptor` block supports the following:

* `lambda` - (Required) Lambda function configuration for the interceptor. See [`lambda`](#lambda) below.

### `lambda`

The `lambda` block supports the following:

* `arn` - (Required) ARN of the Lambda function to invoke for the interceptor.

### `input_configuration`

The `input_configuration` block supports the following:

* `pass_request_headers` - (Required) Whether to pass request headers to the interceptor.

### `protocol_configuration`

The `protocol_configuration` block supports the following:
Expand Down
Loading