Skip to content

feat: add agentic coding sandbox composition building block #47

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
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
8 changes: 8 additions & 0 deletions modules/aws/agentic-coding-sandbox/backplane/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Agentic Coding Sandbox Backplane

This building block is a composition of the following components:
- [AWS Bedrock LZ](./landingzone/README.md): A landing zone for using AWS Bedrock in sandboxed to access LLM models for developers.
- [AWS Budget Alert Building Block](https://hub.meshcloud.io/definitions/aws-budget-alert)
- [AWS Enable Opt-In Region Building Block](https://hub.meshcloud.io/definitions/aws-opt-in-region)

As a composition, this building block does not need any dedicated backplane except a meshObject API Key with appropriate permissions to manage meshProjects, meshTenants and meshBuildingBlocks in the users workspace.
45 changes: 45 additions & 0 deletions modules/aws/agentic-coding-sandbox/backplane/landingzone/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
name: AWS Bedrock LZ
summary: |
A landing zone for using AWS Bedrock in sandboxed to access LLM models for developers.
---

# AWS Bedrock LZ

This Landing Zone restricts access to only the AWS Bedrock service and necessary supporting services. This landing zone is a "single purpose" landing zone that's easy to audit and verify. It's designed to be handed to individual developers who need to:

- Access specific AWS Bedrock LLM models
- Use LLM models via AWS Bedrock for developer tools like Aider
- Interact with AI/ML capabilities provided by AWS Bedrock
- Have control over individual token consumption via standard AWS Billing

<!-- BEGIN_TF_DOCS -->
## Requirements

No requirements.

## Modules

No modules.

## Resources

| Name | Type |
|------|------|
| [aws_organizations_organizational_unit.bedrock](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/organizations_organizational_unit) | resource |
| [aws_organizations_policy.only_bedrock](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/organizations_policy) | resource |
| [aws_organizations_policy_attachment.only_bedrock](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/organizations_policy_attachment) | resource |
| [aws_iam_policy_document.only_bedrock](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_parent_ou_id"></a> [parent\_ou\_id](#input\_parent\_ou\_id) | id of the parent OU | `string` | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_organizational_unit_id"></a> [organizational\_unit\_id](#output\_organizational\_unit\_id) | The ID of the Organizational Unit created in this module. |
<!-- END_TF_DOCS -->
93 changes: 93 additions & 0 deletions modules/aws/agentic-coding-sandbox/backplane/landingzone/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
resource "aws_organizations_organizational_unit" "bedrock" {
name = "bedrock"
parent_id = var.parent_ou_id
}

# Sonnet 4 is available in eu-south-2 (spain) apparently even though the public docs are not super clear on that
# https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-support.html#inference-profiles-support-user
# eu.anthropic.claude-sonnet-4-20250514-v1:0

locals {
# see https://docs.aws.amazon.com/bedrock/latest/userguide/model-access-permissions.html
allowed_models = [
"prod-4dlfvry4v5hbi", // Anthropic Claude 3.7 Sonnet
"prod-m5ilt4siql27k", // Anthropic Claude 3.5 Sonnet
"prod-4pmewlybdftbs", // Anthropic Claude 4.0 Sonnet
]

# EU regions where Bedrock is allowed
allowed_eu_regions = [
"eu-west-1", // Ireland
"eu-west-2", // London
"eu-west-3", // Paris
"eu-central-1", // Frankfurt
"eu-north-1", // Stockholm
"eu-south-1", // Milan
"eu-south-2", // Spain
"eu-central-2", // Zurich
]
}

data "aws_iam_policy_document" "only_bedrock" {

# Restrict Bedrock usage to EU regions only
statement {
sid = "DenyBedrockOutsideEURegions"
effect = "Deny"
actions = [
"bedrock:*"
]
resources = ["*"]
condition {
test = "ForAnyValue:StringNotEquals"
variable = "aws:RequestedRegion"
values = local.allowed_eu_regions
}
}

# 3rd party bedrock models like claude from anthropic need to be enabled via marketplace
# see https://docs.aws.amazon.com/bedrock/latest/userguide/model-access-permissions.html
# NOTE: there are also some issues with payment methods for EMEA customers, see https://repost.aws/questions/QU0UOsutrWSSS4nOqgHcIUJg/invalid-payment-instrument-after-requesting-model-access-in-amazon-bedrock
# This needs to be configured correctly on the AWS Organization payer account.
statement {
sid = "DenyMarketplaceActionsExceptForAllowedModels"
effect = "Deny"
actions = [
"aws-marketplace:Subscribe",
"aws-marketplace:Unsubscribe",
"aws-marketplace:ViewSubscriptions"
]
resources = ["*"]
condition {
test = "ForAnyValue:StringNotEquals"
variable = "aws-marketplace:ProductId"
values = local.allowed_models
}
}

statement {
sid = "DenyAllExceptBedrockRelated"
effect = "Deny"
not_actions = [
"bedrock:*", // Allow all Bedrock actions
"aws-marketplace:*", // Required for marketplace subscriptions that enable model access
"logs:*", // Required for logging
"iam:*", // Make no restriction on AWS IAM functionality which is basic for AWS functioning
"ce:*", // For Cost Explorer
"budgets:*", // For Budgets
"cloudformation:*", // Required to enable stacksets deployed from the organization
]
resources = ["*"]
}
}

resource "aws_organizations_policy" "only_bedrock" {
name = "only_bedrock"
description = "Block access to all services except AWS Bedrock and related services for LLM model access."
content = data.aws_iam_policy_document.only_bedrock.json
}

resource "aws_organizations_policy_attachment" "only_bedrock" {
policy_id = aws_organizations_policy.only_bedrock.id
target_id = aws_organizations_organizational_unit.bedrock.id
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
output "organizational_unit_id" {
description = "The ID of the Organizational Unit created in this module."
value = aws_organizations_organizational_unit.bedrock.id
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
variable "parent_ou_id" {
type = string
description = "id of the parent OU"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
Agentic Coding Sandbox provides access to agentic coding tools like Claude, enabling developers to leverage AI for code generation and experimentation.

**Usage Motivation:**

This building block is designed for developers who want to leverage AI for code generation, experimentation, and other coding tasks. It provides a pre-configured environment with access to approved agentic coding tools, allowing developers to explore the capabilities of AI-assisted coding without managing the underlying infrastructure.

**Usage Examples:**

Use Claude (via AWS Bedrock) to generate code snippets for common tasks, speeding up development time. Use it with tools like [aider](https://aider.chat/) or [cline](https://github.com/cline/cline).


**Shared Responsibility:**

| Responsibility | Platform Team ✅ | Application Team ✅/❌ |
|--------------------------------------|----------------|----------------------|
| Provides access to approved agentic coding models (e.g., Claude Sonnet 3.7 via AWS Bedrock) | ✅ | ❌ |
| Enforces policies to ensure compliance with meshcloud rules | ✅ | ❌ |
| Evaluate model compliance with meshcloud rules and makes only checked models available | ✅ | ❌ |
| Provides easy-to-use budget alerts | ✅ | ❌ |
| Monitors usage quota and costs | ❌ | ✅ |

## Accessing Models via AWS Bedrock

Before you can start using models like Claude AI, you need to request access to them within the AWS Bedrock console.

Please use the `eu-central-1` (Frankfurt) region preferably. You may also use `eu-south-2`(Spain) where more models are available.

Follow these steps:

1. **Log in to the AWS Console:** Access the AWS Management Console. You can use the direct link from your meshStack tenant to open the AWS Management Console.
2. **Navigate to Amazon Bedrock:** Search for "Bedrock" in the AWS service search bar and select "Amazon Bedrock".
3. **Request Model Access following the [official instructions](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html):**
* In the left navigation pane, click on "Model access".
* You will see a list of available models. Locate "Claude" (or other models you wish to use).
* Click the "Request access" button next to the desired model(s).
* Review the terms and conditions, and then submit your request.
4. **Wait for Approval:** AWS will review your request. Approval times may vary. You can check the status of your request in the "Model access" section of the Bedrock console.

## Using the Bedrock API

Once your model access request is approved, you can start using the Bedrock API to interact with the models.

Configure your AWS credentials (e.g., using `aws configure` or setting environment variables) to allow your applications to authenticate with AWS. Ensure your IAM role or user has the necessary permissions to invoke Bedrock models.

Here's a quick example of how to set up the correct sso session


Example with the right config values.

```shellsession
$ aws configure sso-session
SSO session name: meshcloud-prod
SSO start URL [https://meshcloud-prod.awsapps.com/start/#]:
SSO region [eu-central-1]:
SSO registration scopes [sso:account:access]:

$ aws sso login --sso-session meshcloud-prod
```

You then need to create an aws cli profile using this session pointing into your AWS Account. The quickest way is to just edit your `~/.aws/config` directly

```
[profile ai-sandbox]
sso_session = meshcloud-prod
sso_account_id = <your aws account number>
sso_role_name = AdministratorAccess
region = eu-central-1
``

Verify that it works using

```shellsession
$ aws bedrock list-foundation-models --profile ai-sandbox
```
108 changes: 108 additions & 0 deletions modules/aws/agentic-coding-sandbox/buildingblock/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
name: Agentic Coding Sandbox
supportedPlatforms:
- aws
description: |
A composition building block that provides developers with a sandboxed AWS environment
to access agentic coding tools like Claude via AWS Bedrock, with automatic budget alerts
and region enablement for AI model access.
---
# Agentic Coding Sandbox

This building block is a **composition** that orchestrates multiple components to provide developers with a complete agentic coding environment. It automatically provisions a meshStack project and AWS tenant configured for AI-powered development workflows.

## Prerequisites

Before deploying this building block:

1. ✅ Deploy the [AWS Bedrock landing zone](../backplane/landingzone/README.md) to your AWS platform.
2. ✅ Import [AWS Budget Alert Building Block](https://hub.meshcloud.io/definitions/aws-budget-alert) from meshStack Hub into your meshStack
3. ✅ Import [AWS Enable Opt-In Region building block](https://hub.meshcloud.io/definitions/aws-opt-in-region) from meshStack Hub into your meshStack
4. ✅ Configure the `composition_config_yaml` with the correct UUIDs and identifiers
5. ✅ Configure an meshStack API key for the composition with admin permissions for projects, tenants, and building blocks

## What This Building Block Does

This composition creates:

1. **meshProject**: A dedicated project with auto-generated naming (`acs-{username}-{suffix}`) to avoid conflicts. The project allows you to manage IAM and Billing with ease in meshStack.
2. **AWS Account**: A tenant in the specified AWS platform using the configured landing zone
3. **Budget Alert**: Automated cost monitoring with email notifications to the user
4. **EU South 2 Region Access**: Enables the Spain region where advanced models like Anthropic's Claude Sonnet 4 are available as an alternative to the primary Frankfurt region used in this example.

## Configuration Requirements

⚠️ **Important**: Since this is a composition, platform operators **must** populate the `composition_config_yaml` variable with the correct UUIDs and identifiers from the building blocks deployed to their meshStack from meshStack Hub. Configure this as a static code input in your meshStack.

### Required Configuration

The `composition_config_yaml` variable must contain:

```yaml
landing_zone:
landing_zone_identifier: "your-bedrock-landing-zone-id" # From your AWS Bedrock LZ deployment
platform_identifier: "your-aws-platform-id" # Your AWS platform identifier

budget_alert_building_block:
definition_uuid: "uuid-from-meshstack-hub" # UUID from AWS Budget Alert BB deployment
definition_version: 1 # Version from your deployment

enable_eu_south_2_region_building_block:
definition_uuid: "uuid-from-meshstack-hub" # UUID from AWS Enable Opt-In Region BB deployment
definition_version: 1 # Version from your deployment

project: # Optional project configuration
default_tags:
environment: "sandbox"
cost_center: "engineering"
owner_tag_key: "project_owner" # Optional: adds owner tag to project
```

### How to Get the Required Values

1. **Landing Zone Identifiers**: Check your AWS platform configuration in meshStack
2. **Building Block UUIDs**: After importing building blocks from meshStack Hub, find their UUIDs in:
- meshStack Admin Area → Building Block Definitions
- Or via meshStack API: `GET /api/meshobjects/meshbuildingblockdefinitions`

## User Inputs

End users provide:

- **username**: Must be a `@meshcloud.io` email address (validated)
- **budget_amount**: Monthly budget limit for cost alerts

<!-- BEGIN_TF_DOCS -->
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_meshstack"></a> [meshstack](#requirement\_meshstack) | 0.7.1 |

## Modules

No modules.

## Resources

| Name | Type |
|------|------|
| [meshstack_buildingblock.budget_alert](https://registry.terraform.io/providers/meshcloud/meshstack/0.7.1/docs/resources/buildingblock) | resource |
| [meshstack_buildingblock.enable_eu_south_2_region](https://registry.terraform.io/providers/meshcloud/meshstack/0.7.1/docs/resources/buildingblock) | resource |
| [meshstack_project.sandbox](https://registry.terraform.io/providers/meshcloud/meshstack/0.7.1/docs/resources/project) | resource |
| [meshstack_tenant.sandbox](https://registry.terraform.io/providers/meshcloud/meshstack/0.7.1/docs/resources/tenant) | resource |
| [random_string.suffix](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_budget_amount"></a> [budget\_amount](#input\_budget\_amount) | Monthly budget amount. You will receive an alert when the budget is exceeded. | `number` | n/a | yes |
| <a name="input_composition_config_yaml"></a> [composition\_config\_yaml](#input\_composition\_config\_yaml) | YAML configuration for landing zone and building blocks. Expected structure:<pre>yaml<br>landing_zone:<br> landing_zone_identifier: "my-landing-zone"<br> platform_identifier: "my-platform"<br>budget_alert_building_block:<br> definition_uuid: "uuid-here"<br> definition_version: 1<br>enable_eu_south_2_region_building_block:<br> definition_uuid: "uuid-here"<br> definition_version: 1<br>project:<br> default_tags:<br> environment: "sandbox"<br> cost_center: "engineering"<br> owner_tag_key: "project_owner" # optional, if not set no project owner tag will be set</pre> | `string` | n/a | yes |
| <a name="input_username"></a> [username](#input\_username) | meshStack username of the project contact. This should be an email. | `string` | n/a | yes |
| <a name="input_workspace_identifier"></a> [workspace\_identifier](#input\_workspace\_identifier) | Identifier for the owning workspace | `string` | n/a | yes |

## Outputs

No outputs.
<!-- END_TF_DOCS -->
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading