AWS Account
The aws_account resource provisions sandboxed AWS accounts for lab environments. It creates controlled AWS accounts with user management, service restrictions, and regional limitations suitable for educational and training purposes.
Use Cases
Section titled “Use Cases”As a lab author, you can use aws_account resources to:
- AWS Training Labs: Create realistic AWS environments for hands-on cloud training and certification preparation
- Service-Specific Learning: Restrict access to specific AWS services for focused learning experiences
AWS account resources provide realistic cloud environments while maintaining educational control and cost management.
HCL Syntax
Section titled “HCL Syntax”Basic Syntax
Section titled “Basic Syntax”resource "aws_account" "name" { regions = ["us-east-1"] services = ["ec2", "s3"]
user "student" { managed_policies = [ "arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess" ] }}Full Syntax
Section titled “Full Syntax”resource "aws_account" "name" { regions = ["us-east-1", "us-west-2"] services = ["ec2", "s3", "iam", "cloudformation"]
tags = { Environment = "Training" Purpose = "Lab" Team = "Education" }
user "admin" { iam_policy = file("./policies/admin-policy.json") managed_policies = [ "arn:aws:iam::aws:policy/PowerUserAccess", "arn:aws:iam::aws:policy/IAMReadOnlyAccess" ] }
user "developer" { iam_policy = file("./policies/dev-policy.json") managed_policies = [ "arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess" ] }
scp_policy = file("./policies/lab-restrictions.json")}Fields
| Field | Type | Required | Description |
|---|---|---|---|
services | list(string) | ✓ | AWS services users can access, as AWS service namespaces - the prefix used in IAM policy actions (e.g. ec2, s3, lambda). At least one service is required.Constraintsat least one service must be specified |
regions | list(string) | ✓ | AWS regions where resources can be provisioned, as standard AWS region codes (e.g. us-east-1, eu-west-1). At least one region is required.Constraintsat least one region must be specified |
tags | map(string) | — | Add metadata tags to organize and track AWS resources (e.g., 'Environment: Production') |
scp_ | string | — | Define organization-wide restrictions using AWS SCP JSON syntax. Leave empty for no restrictions. |
user | block | — | Define IAM users with specific permissions for lab participantsrepeatable Constraintsat least one user must be specified |
service_ | block | — | One block per service, named by its service ID. Each service block must also be listed in services. |
IAM User
IAM users to create in the AWS account
| Field | Type | Required | Description |
|---|---|---|---|
slug | label | — | Unique identifier for the IAM user (e.g., 'alice', 'admin') |
iam_ | string | — | Define custom permissions using AWS IAM policy JSON syntax. Overrides managed policies if specified. |
managed_ | list(string) | — | Attach AWS-managed policies by ARN (e.g., 'arn:aws:iam::aws:policy/ReadOnlyAccess') |
Service Limits
Restrictions on the services listed in services
| Field | Type | Required | Description |
|---|---|---|---|
bedrock | block | — | Only the listed models can be invoked |
Amazon Bedrock
Amazon Bedrock models learners may invoke, with optional token limits per model
| Field | Type | Required | Description |
|---|---|---|---|
model | block | — | Learners can invoke only the models listed hererepeatable |
Model
A model learners may invoke
| Field | Type | Required | Description |
|---|---|---|---|
slug | label | — | Any name, unique within the service block |
name | string | ✓ | For example 'anthropic.claude-sonnet-4-5-20250929-v1:0' |
input_ | number | — | Input tokens a session may use on this model ConstraintsMinimum 1 |
output_ | number | — | Output tokens a session may use on this model ConstraintsMinimum 1 |
Computed Attributes
These attributes are set by the system and are read-only.
| Attribute | Type | Description |
|---|---|---|
account_id | string | The AWS account ID assigned to this sandbox account |
account_name | string | The AWS account name assigned to this sandbox account |
user[].username | string | The IAM username assigned to this user |
user[].password | string | The console password for this IAM user |
user[].access_key_id | string | The AWS access key ID for programmatic access |
user[].secret_access_key | string | The AWS secret access key for programmatic access |
User Block
Section titled “User Block”aws_account → user
User blocks define IAM users to create within the AWS account:
| Field | Required | Type | Description |
|---|---|---|---|
slug | ✓ | label | Username for the IAM user, written as the block label: user “alice” { … } |
iam_ | string | Custom IAM policy JSON for the user | |
managed_ | list(string) | AWS managed policy ARNs to attach to the user. Defaults to empty list. |
The block label is a short name you choose, such as alice, student, or admin. It doesn’t have to match anything outside the lab. Pick a name that describes the user’s role in the scenario.
In the UI, the label is the Username field of the IAM User section. The Name (internal) field at the top of the form is the name of the aws_account resource itself, not of an IAM user.
Instruqt creates an IAM user from the label and generates its sign-in credentials. The learner signs in with the computed attributes below (username, password, access_key_id, secret_access_key). You usually show them in a cloud credentials tab or with instruction variables.
User Computed Attributes
Section titled “User Computed Attributes”For each user block, these attributes are computed:
| Field | Type | Description |
|---|---|---|
username | string | The IAM username |
password | string | Console password for the user |
access_key_id | string | AWS access key ID for programmatic access |
secret_access_key | string | AWS secret access key for programmatic access |
Service Limits Block
Section titled “Service Limits Block”aws_account → service_limits
The service_limits block lists the Amazon Bedrock models users can call in the account, with optional token limits for each model. Its fields are listed under Service Limits.
resource "aws_account" "ai_lab" { regions = ["us-east-1"] services = ["bedrock", "s3"]
service_limits { bedrock { model "sonnet" { name = "anthropic.claude-sonnet-4-5-20250929-v1:0" input_token_count = 500000 output_token_count = 100000 }
model "nova" { name = "amazon.nova-micro-v1:0" } } }
user "student" { managed_policies = [ "arn:aws:iam::aws:policy/AmazonBedrockFullAccess" ] }}- One block per service:
service_limitsholds one block per service.bedrockis the only service block anaws_accountaccepts; any other fails validation withunknown block. - Listed in services: The service must also be in
services. Abedrockblock without"bedrock"inservicesfails withservice_limits: bedrock: not listed in services. - Empty service block: A
bedrockblock withoutmodelblocks validates but restricts nothing. Users can call any Bedrock model the account allows. - Model label: The label, such as
"sonnet", is your own name for the entry. It must be unique within the service block and doesn’t have to match the model. - Model ID:
nameis the Bedrock model ID, and it must be a model Instruqt supports. Any other ID fails withunknown model "<id>" for service "bedrock", and the error lists the supported model IDs. - Inference profiles:
nametakes the base model ID, not an inference profile ID such asus.anthropic.claude-sonnet-4-5-20250929-v1:0. Listing a model also allows calls through its inference profiles. Users must call models that Bedrock serves only through inference profiles (e.g. Claude Sonnet 4.5) by the profile ID. - Token limits:
input_token_countandoutput_token_countare optional. Each must be a whole number of at least 1. A model without them has no token limit.
Examples
Section titled “Examples”Basic Training Account
Section titled “Basic Training Account”resource "aws_account" "training" { regions = ["us-east-1"] services = ["ec2", "s3", "iam"]
tags = { Environment = "Training" Course = "AWS Fundamentals" }
user "student" { managed_policies = [ "arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess", "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess" ] }}
output "student_credentials" { value = { username = resource.aws_account.training.user.0.username # e.g., "student" password = resource.aws_account.training.user.0.password # e.g., "TempPass123!" access_key = resource.aws_account.training.user.0.access_key_id # e.g., "AKIAIOSFODNN7EXAMPLE" } sensitive = true}Multi-User Workshop Environment
Section titled “Multi-User Workshop Environment”resource "aws_account" "workshop" { regions = ["us-east-1", "us-west-2"] services = [ "ec2", "s3", "iam", "cloudformation", "lambda" ]
tags = { Environment = "Workshop" Event = "AWS Solutions Architect Training" Instructor = "Jane Doe" }
# Instructor with administrative access user "instructor" { iam_policy = file("./policies/instructor-policy.json") managed_policies = [ "arn:aws:iam::aws:policy/PowerUserAccess", "arn:aws:iam::aws:policy/IAMFullAccess" ] }
# Student with controlled permissions user "student" { managed_policies = [ "arn:aws:iam::aws:policy/AmazonEC2FullAccess", "arn:aws:iam::aws:policy/AmazonS3FullAccess" ] }
# Observer with read-only access user "observer" { managed_policies = [ "arn:aws:iam::aws:policy/ReadOnlyAccess" ] }
scp_policy = file("./policies/workshop-restrictions.json")}Serverless Development Lab
Section titled “Serverless Development Lab”resource "aws_account" "serverless_lab" { regions = ["us-east-1"] services = [ "lambda", "apigateway", "dynamodb", "s3", "cloudwatch", "iam" ]
tags = { Environment = "Serverless-Lab" Technology = "AWS Lambda" Level = "Intermediate" }
user "developer" { iam_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Effect = "Allow" Action = [ "lambda:*", "apigateway:*", "dynamodb:*", "s3:*", "logs:*" ] Resource = "*" } ] }) }}
resource "container" "aws_cli" { image { name = "amazon/aws-cli:latest" }
environment = { AWS_ACCESS_KEY_ID = resource.aws_account.serverless_lab.user.0.access_key_id # e.g., "AKIAIOSFODNN7EXAMPLE" AWS_SECRET_ACCESS_KEY = resource.aws_account.serverless_lab.user.0.secret_access_key # e.g., "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" AWS_DEFAULT_REGION = "us-east-1" }}Credential Template Integration
Section titled “Credential Template Integration”resource "aws_account" "lab" { regions = ["us-east-1"] services = ["ec2", "s3"]
user "student" { managed_policies = [ "arn:aws:iam::aws:policy/AmazonEC2FullAccess" ] }}
resource "template" "aws_credentials" { source = <<-EOF [default] aws_access_key_id = ${resource.aws_account.lab.user.0.access_key_id} # e.g., "AKIAIOSFODNN7EXAMPLE" aws_secret_access_key = ${resource.aws_account.lab.user.0.secret_access_key} # e.g., "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" region = us-east-1
# Account Information # Account ID: ${resource.aws_account.lab.account_id} # e.g., "123456789012" # Account Name: ${resource.aws_account.lab.account_name} # e.g., "instruqt-lab-account" EOF
destination = "./aws-credentials"}
resource "template" "lab_instructions" { source = <<-EOF # AWS Lab Environment
## Account Details - Account ID: ${resource.aws_account.lab.account_id} # e.g., "123456789012" - Account Name: ${resource.aws_account.lab.account_name} # e.g., "instruqt-lab-account"
## User Credentials - Username: ${resource.aws_account.lab.user.0.username} # e.g., "student" - Password: ${resource.aws_account.lab.user.0.password} # e.g., "TempPass123!"
## Programmatic Access - Access Key ID: ${resource.aws_account.lab.user.0.access_key_id} - Secret Access Key: ${resource.aws_account.lab.user.0.secret_access_key} EOF
destination = "./lab-info.md"}Multi-Region Training Setup
Section titled “Multi-Region Training Setup”resource "aws_account" "global_training" { regions = [ "us-east-1", # N. Virginia "us-west-2", # Oregon "eu-west-1", # Ireland "ap-southeast-1" # Singapore ]
services = [ "ec2", "s3", "cloudfront", "route53", "iam" ]
tags = { Environment = "Multi-Region-Training" Topic = "Global Infrastructure" Duration = "4-hours" }
user "architect" { iam_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Effect = "Allow" Action = [ "ec2:*", "s3:*", "cloudfront:*", "route53:*" ] Resource = "*" Condition = { StringEquals = { "aws:RequestedRegion" = [ "us-east-1", "us-west-2", "eu-west-1", "ap-southeast-1" ] } } } ] }) }}Security Training with SCP
Section titled “Security Training with SCP”resource "aws_account" "security_lab" { regions = ["us-east-1"] services = ["ec2", "s3", "iam"]
tags = { Environment = "Security-Training" Focus = "IAM-and-Policies" }
user "security_student" { iam_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Effect = "Allow" Action = [ "ec2:DescribeInstances", "ec2:RunInstances", "ec2:TerminateInstances" ] Resource = "*" Condition = { StringEquals = { "ec2:InstanceType" = ["t2.micro", "t3.micro"] } } } ] }) }
# Restrictive SCP to prevent privilege escalation scp_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Effect = "Deny" Action = [ "iam:CreateRole", "iam:DeleteRole", "iam:AttachRolePolicy", "iam:DetachRolePolicy", "organizations:*", "account:*" ] Resource = "*" }, { Effect = "Deny" Action = "ec2:RunInstances" Resource = "arn:aws:ec2:*:*:instance/*" Condition = { ForAllValues:StringNotEquals = { "ec2:InstanceType" = [ "t2.micro", "t2.small", "t3.micro", "t3.small" ] } } } ] })}Best Practices
Section titled “Best Practices”- Principle of Least Privilege: Grant only the minimum permissions required for the lab objectives
- Service Restrictions: Limit services to those essential for the learning experience
- Regional Constraints: Restrict regions to control costs and simplify the environment
- Policy Management: Use external JSON files for complex IAM policies and SCPs
- User Separation: Create distinct users for different roles (student, instructor, observer)
- Cost Controls: Implement SCPs to prevent expensive resource creation
- Tagging Strategy: Use consistent tags for cost tracking and resource management
- Credential Security: Mark credential outputs as sensitive and manage access carefully
