Skip to content

feat: add AWS Bedrock access for OpenCode with batch inference support - #14

Merged
xnoto merged 1 commit into
mainfrom
feat/bedrock-opencode
Aug 25, 2026
Merged

feat: add AWS Bedrock access for OpenCode with batch inference support#14
xnoto merged 1 commit into
mainfrom
feat/bedrock-opencode

Conversation

@xnoto

Copy link
Copy Markdown
Contributor

Summary

Adds AWS Bedrock access for OpenCode (Claude Opus) with full batch inference support for the 50% Batch API discount.

  • aws-bedrock.tf (new):
    • opencode-bedrock IAM user + access key, scoped to Anthropic models via both foundation-model/anthropic.* and inference-profile/*.anthropic.* ARNs — Opus 4.x rejects base model IDs and must be called through inference profiles
    • bedrock-batch-inference service role (trusted by bedrock.amazonaws.com, SourceAccount/SourceArn conditions) — CreateModelInvocationJob requires a roleArn for S3 I/O
    • mitw-bedrock-batch S3 bucket (fully private, prevent_destroy) for batch input JSONL and output
    • User policy statements: on-demand invoke, inference profile discovery, batch job management (Create/Get/Stop/List), batch S3 data access, and iam:PassRole constrained with iam:PassedToService: bedrock.amazonaws.com
  • outputs.tf: bedrock_opencode_access_key (sensitive), user ARN, batch service role ARN, batch bucket name
  • README.md: regenerated via terraform-docs

Notes

  • Batch inference is asynchronous (up to 24h) — interactive OpenCode sessions use on-demand invoke at full price; the discount applies only to submitted batch jobs
  • Bedrock model access entitlement remains a manual AWS Console step
  • Verify Anthropic model availability in the configured provider region before apply

Validation

  • make test — all canonical pre-commit hooks pass (tofu validate with -backend=false, tflint, checkov, fmt, terraform-docs, gitleaks)
  • No live plan/apply run locally; CI plan on this PR is authoritative

Add opencode-bedrock IAM user scoped to Anthropic models via foundation
model and inference profile ARNs (Opus 4.x requires inference profiles).
Batch inference (50% discount vs on-demand) requires CreateModelInvocationJob
with a mandatory service role ARN and S3 input/output, so this also adds the
bedrock-batch-inference service role, mitw-bedrock-batch bucket, and
PassRole/S3 permissions for the user.
@xnoto
xnoto requested a review from a team as a code ownerAugust 25, 2026 19:17
@github-actions

Copy link
Copy Markdown

OpenTofu Plan

OpenTofu will perform the following actions:
# aws_iam_access_key.bedrock_opencode will be created
+ resource "aws_iam_access_key" "bedrock_opencode" {
+ create_date = (known after apply)
+ encrypted_secret = (known after apply)
+ encrypted_ses_smtp_password_v4 = (known after apply)
+ id = (known after apply)
+ key_fingerprint = (known after apply)
+ secret = (sensitive value)
+ ses_smtp_password_v4 = (sensitive value)
+ status = "Active"
+ user = "opencode-bedrock"
}
# aws_iam_role.bedrock_batch will be created
+ resource "aws_iam_role" "bedrock_batch" {
+ arn = (known after apply)
+ assume_role_policy = jsonencode(
{
+ Statement = [
+ {
+ Action = "sts:AssumeRole"
+ Condition = {
+ ArnEquals = {
+ "aws:SourceArn" = "arn:aws:bedrock:*:332355796717:model-invocation-job/*"
}
+ StringEquals = {
+ "aws:SourceAccount" = "332355796717"
}
}
+ Effect = "Allow"
+ Principal = {
+ Service = "bedrock.amazonaws.com"
}
},
]
+ Version = "2012-10-17"
}
)
+ create_date = (known after apply)
+ force_detach_policies = false
+ id = (known after apply)
+ managed_policy_arns = (known after apply)
+ max_session_duration = 3600
+ name = "bedrock-batch-inference"
+ name_prefix = (known after apply)
+ path = "/"
+ tags = {
+ "ManagedBy" = "Terraform"
+ "Purpose" = "bedrock-batch-inference"
}
+ tags_all = {
+ "ManagedBy" = "Terraform"
+ "Purpose" = "bedrock-batch-inference"
}
+ unique_id = (known after apply)
+ inline_policy (known after apply)
}
# aws_iam_role_policy.bedrock_batch_invoke will be created
+ resource "aws_iam_role_policy" "bedrock_batch_invoke" {
+ id = (known after apply)
+ name = "bedrock-batch-invoke"
+ name_prefix = (known after apply)
+ policy = jsonencode(
{
+ Statement = [
+ {
+ Action = [
+ "bedrock:InvokeModel",
]
+ Effect = "Allow"
+ Resource = [
+ "arn:aws:bedrock:*::foundation-model/anthropic.*",
+ "arn:aws:bedrock:*:332355796717:inference-profile/*.anthropic.*",
]
+ Sid = "InvokeAnthropicModels"
},
]
+ Version = "2012-10-17"
}
)
+ role = "bedrock-batch-inference"
}
# aws_iam_role_policy.bedrock_batch_s3 will be created
+ resource "aws_iam_role_policy" "bedrock_batch_s3" {
+ id = (known after apply)
+ name = "bedrock-batch-s3"
+ name_prefix = (known after apply)
+ policy = (known after apply)
+ role = "bedrock-batch-inference"
}
# aws_iam_user.bedrock_opencode will be created
+ resource "aws_iam_user" "bedrock_opencode" {
+ arn = (known after apply)
+ force_destroy = false
+ id = (known after apply)
+ name = "opencode-bedrock"
+ path = "/"
+ tags = {
+ "ManagedBy" = "Terraform"
+ "Purpose" = "opencode-bedrock"
}
+ tags_all = {
+ "ManagedBy" = "Terraform"
+ "Purpose" = "opencode-bedrock"
}
+ unique_id = (known after apply)
}
# aws_iam_user_policy.bedrock_opencode will be created
+ resource "aws_iam_user_policy" "bedrock_opencode" {
+ id = (known after apply)
+ name = "bedrock-invoke"
+ name_prefix = (known after apply)
+ policy = (known after apply)
+ user = "opencode-bedrock"
}
# aws_s3_bucket.bedrock_batch will be created
+ resource "aws_s3_bucket" "bedrock_batch" {
+ acceleration_status = (known after apply)
+ acl = (known after apply)
+ arn = (known after apply)
+ bucket = "mitw-bedrock-batch"
+ bucket_domain_name = (known after apply)
+ bucket_namespace = (known after apply)
+ bucket_prefix = (known after apply)
+ bucket_region = (known after apply)
+ bucket_regional_domain_name = (known after apply)
+ force_destroy = false
+ hosted_zone_id = (known after apply)
+ id = (known after apply)
+ object_lock_enabled = (known after apply)
+ policy = (known after apply)
+ region = "us-west-2"
+ request_payer = (known after apply)
+ tags = {
+ "ManagedBy" = "Terraform"
+ "Purpose" = "bedrock-batch-inference"
}
+ tags_all = {
+ "ManagedBy" = "Terraform"
+ "Purpose" = "bedrock-batch-inference"
}
+ website_domain = (known after apply)
+ website_endpoint = (known after apply)
+ cors_rule (known after apply)
+ grant (known after apply)
+ lifecycle_rule (known after apply)
+ logging (known after apply)
+ object_lock_configuration (known after apply)
+ replication_configuration (known after apply)
+ server_side_encryption_configuration (known after apply)
+ versioning (known after apply)
+ website (known after apply)
}
# aws_s3_bucket_public_access_block.bedrock_batch will be created
+ resource "aws_s3_bucket_public_access_block" "bedrock_batch" {
+ block_public_acls = true
+ block_public_policy = true
+ bucket = "mitw-bedrock-batch"
+ id = (known after apply)
+ ignore_public_acls = true
+ region = "us-west-2"
+ restrict_public_buckets = true
}
Plan: 8 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ bedrock_batch_bucket_name = "mitw-bedrock-batch"
+ bedrock_batch_service_role_arn = (known after apply)
+ bedrock_opencode_access_key = (sensitive value)
+ bedrock_opencode_iam_user_arn = (known after apply)

@xnoto
xnoto merged commit 34df956 into mainAug 25, 2026
4 checks passed
@xnoto
xnoto deleted the feat/bedrock-opencode branch August 25, 2026 19:23
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@xnoto