| name | AWS Ecosystem |
| description | This skill should be used when the user asks to "aws cli", "aws configure", "aws sso", "aws sts", "terraform aws", or works with AWS CLI and Terraform AWS Provider patterns. Provides comprehensive AWS ecosystem patterns and best practices. |
Provide comprehensive patterns for AWS CLI configuration, authentication, common operations, and Terraform AWS Provider infrastructure as code.
<cli_configuration>
<config_files>
AWS CLI configuration file
[default]
region = ap-northeast-1
output = json
[profile dev]
region = ap-northeast-1
output = json
[profile prod]
region = ap-northeast-1
output = json
</example>
</file>
<file name="~/.aws/credentials">
<description>AWS credentials file (avoid storing long-term credentials)</description>
<example>
[default]
aws_access_key_id = AKIA...
aws_secret_access_key = ...
</example>
<warning>Prefer SSO or IAM roles over long-term credentials</warning>
</file>
</config_files>
<environment_variables>
Active profile name
Override region
Default region
Access key (avoid in production)
Secret key (avoid in production)
Session token for temporary credentials
Custom config file path
Custom credentials file path
</environment_variables>
<profile_switching>
Set profile via environment variable
export AWS_PROFILE=dev
Set profile inline with command
aws s3 ls --profile prod
</profile_switching>
</cli_configuration>
Are you authenticating for human access or programmatic access?
Human: Use SSO for temporary credentials; Programmatic: Use IAM roles or OIDC federation
Never use long-term access keys in production
AWS IAM Identity Center (SSO) authentication (2025 recommended)
[profile sso-dev]
sso_session = my-sso
sso_account_id = 123456789012
sso_role_name = DeveloperAccess
region = ap-northeast-1
output = json
[sso-session my-sso]
sso_start_url = https://example.awsapps.com/start
sso_region = ap-northeast-1
sso_registration_scopes = sso:account:access
</example>
<commands>
<command name="login">aws sso login --sso-session my-sso</command>
<command name="logout">aws sso logout --sso-session my-sso</command>
</commands>
<concept name="pkce_authorization">
<description>PKCE authorization (default since AWS CLI v2.22.0)</description>
<note>Recommended for desktop/mobile access; provides secure OAuth 2.0 flow</note>
</concept>
<concept name="token_refresh">
<description>Automatic token refresh without re-authentication</description>
<note>Requires AWS CLI v2.9.0+ or v1.27.10+; sso-session configuration enables token refresh support</note>
</concept>
<note>Use SSO with sso-session for human users; use IAM roles for services</note>
<assume_role>
Cross-account or elevated access via role assumption
[profile cross-account]
role_arn = arn:aws:iam::987654321098:role/CrossAccountRole
source_profile = default
region = ap-northeast-1
aws sts assume-role --role-arn arn:aws:iam::123456789012:role/MyRole --role-session-name session1
Assume role from another assumed role
[profile chained]
role_arn = arn:aws:iam::111111111111:role/FinalRole
source_profile = cross-account
</assume_role>
Multi-factor authentication for CLI
[profile mfa-required]
role_arn = arn:aws:iam::123456789012:role/AdminRole
source_profile = default
mfa_serial = arn:aws:iam::123456789012:mfa/username
aws sts get-session-token --serial-number arn:aws:iam::123456789012:mfa/username --token-code 123456
<credential_process>
External credential provider
[profile external]
credential_process = /path/to/credential-provider
Integration with 1Password, Vault, or custom providers
</credential_process>
<oidc_federation>
OIDC federation for CI/CD (2025 best practice)
Use cases: GitHub Actions, GitLab CI, Azure DevOps with OIDC
<file_reference>.github/workflows/deploy.yml</file_reference>
permissions:
id-token: write
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps: - uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsRole
aws-region: ap-northeast-1
</example>
<note>No long-term credentials stored in CI/CD; temporary credentials via STS</note>
<warning>Validate OIDC thumbprints and restrict ClientIDList to prevent misconfiguration</warning>
</oidc_federation>
Verify current AWS identity
aws sts get-caller-identity
{
"UserId": "AIDAEXAMPLE",
"Account": "123456789012",
"Arn": "arn:aws:iam::123456789012:user/username"
}
<output_filtering>
<decision_tree name="when_to_use">
Do you need to filter or transform AWS CLI output?
<if_yes>Use --query for AWS-native filtering or pipe to jq for complex transformations</if_yes>
<if_no>Use default JSON output for full response data</if_no>
</decision_tree>
<output_formats>
Default, machine-readable (--output json)
Tab-delimited, scriptable (--output text)
Human-readable (--output table)
YAML format (--output yaml)
</output_formats>
<query_examples>
Extract single value from query
aws ec2 describe-instances --query 'Reservations[0].Instances[0].InstanceId' --output text
<pattern name="list">
<description>Extract list of values</description>
<example>aws ec2 describe-instances --query 'Reservations[].Instances[].InstanceId' --output text</example>
</pattern>
<pattern name="filtered">
<description>Filter results by condition</description>
<example>aws ec2 describe-instances --query 'Reservations[].Instances[?State.Name==`running`].InstanceId' --output text</example>
</pattern>
<pattern name="projection">
<description>Project multiple fields with custom formatting</description>
<example>aws ec2 describe-instances --query 'Reservations[].Instances[].[InstanceId,State.Name,Tags[?Key==`Name`].Value|[0]]' --output table</example>
</pattern>
<pattern name="sorting">
<description>Sort results by field</description>
<example>aws ec2 describe-instances --query 'sort_by(Reservations[].Instances[], &LaunchTime)[].InstanceId'</example>
</pattern>
</query_examples>
<jq_integration>
Basic jq filtering
aws ec2 describe-instances | jq '.Reservations[].Instances[].InstanceId'
Complex jq transformation with TSV output
aws ec2 describe-instances | jq -r '.Reservations[].Instances[] | [.InstanceId, .State.Name] | @tsv'
</jq_integration>
</output_filtering>
<common_commands>
aws s3 ls
aws s3 ls s3://bucket-name/prefix/
aws s3 cp file.txt s3://bucket-name/
aws s3 sync ./local-dir s3://bucket-name/prefix/
aws s3 presign s3://bucket-name/object-key --expires-in 3600
aws ec2 describe-instances
aws ec2 start-instances --instance-ids i-1234567890abcdef0
aws ec2 stop-instances --instance-ids i-1234567890abcdef0
aws ec2 terminate-instances --instance-ids i-1234567890abcdef0
aws iam list-users
aws iam list-roles
aws iam get-policy --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess
aws lambda list-functions
aws lambda invoke --function-name my-function --payload '{"key": "value"}' response.json
aws logs tail /aws/lambda/my-function --follow
aws ecs list-clusters
aws ecs list-services --cluster cluster-name
aws ecs describe-tasks --cluster cluster-name --tasks task-arn
aws ecs execute-command --cluster cluster-name --task task-id --container container-name --interactive --command "/bin/sh"
aws logs tail /aws/lambda/function-name --follow
aws logs filter-log-events --log-group-name /aws/lambda/function-name --filter-pattern "ERROR"
aws cloudwatch get-metric-statistics --namespace AWS/EC2 --metric-name CPUUtilization --dimensions Name=InstanceId,Value=i-1234567890abcdef0 --start-time 2024-01-01T00:00:00Z --end-time 2024-01-02T00:00:00Z --period 3600 --statistics Average
aws ssm get-parameter --name /path/to/param --with-decryption
aws ssm put-parameter --name /path/to/param --value "secret" --type SecureString
aws ssm start-session --target i-1234567890abcdef0
<secrets_manager>
aws secretsmanager get-secret-value --secret-id my-secret --query SecretString --output text
aws secretsmanager create-secret --name my-secret --secret-string '{"key":"value"}'
</secrets_manager>
</common_commands>
<scripting_patterns>
<wait_commands>
Wait for EC2 instance to reach running state
aws ec2 wait instance-running --instance-ids i-1234567890abcdef0
Wait for CloudFormation stack creation
aws cloudformation wait stack-create-complete --stack-name my-stack
</wait_commands>
Manual pagination with token
aws s3api list-objects-v2 --bucket bucket-name --max-items 100 --starting-token TOKEN
Automatic pagination with query
aws s3api list-objects-v2 --bucket bucket-name --query 'Contents[].Key' --output text
Test commands without execution
aws ec2 run-instances --dry-run --image-id ami-12345678 --instance-type t3.micro
<batch_operations>
Batch operations using shell loop
for id in $(aws ec2 describe-instances --query 'Reservations[].Instances[].InstanceId' --output text); do
aws ec2 create-tags --resources "$id" --tags Key=Environment,Value=Dev
done
<pattern name="xargs">
<description>Batch operations using xargs</description>
<example>
aws ec2 describe-instances --query 'Reservations[].Instances[].InstanceId' --output text | \
xargs -I {} aws ec2 create-tags --resources {} --tags Key=Backup,Value=true
</example>
</pattern>
</batch_operations>
</scripting_patterns>
<anti_patterns>
Never hardcode credentials in scripts or config
Use IAM roles, SSO, or credential_process
Avoid using long-term access keys
Use temporary credentials via SSO or AssumeRole
Never use root account credentials for CLI
Create IAM users or use SSO with appropriate permissions
Do not share credentials between team members
Each user should have their own SSO access or IAM user
Avoid exporting credentials in shell history
Use aws configure or credential files with proper permissions
Avoid policies with Resource: "*" and Action: "*"
Follow least privilege principle
<best_practices>
Eliminate long-term access keys; use SSO or IAM roles instead
Use sso-session configuration for token refresh support (CLI v2.9.0+)
Use OIDC federation for CI/CD (GitHub Actions, GitLab CI)
Use Instance Profiles for EC2, EKS Service Accounts for K8s, Lambda Execution Roles for serverless
Enable MFA for all human users
Follow least privilege principle; avoid wildcard permissions
Enable CloudTrail for CLI activity monitoring
Use --query for filtering instead of jq when possible
Set default region in config to avoid specifying every time
Use named profiles for different environments
Use aws sts get-caller-identity to verify current identity
Enable CLI auto-prompt: export AWS_CLI_AUTO_PROMPT=on-partial
Use --dry-run for destructive operations first
Use wait commands in scripts for async operations
Store credentials file with 600 permissions
</best_practices>
Are you managing AWS infrastructure as code?
Use Terraform for declarative, version-controlled infrastructure
Use AWS CLI for one-off operations or AWS Console for exploration
<provider_configuration>
Basic AWS provider configuration
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
</example>
</pattern>
<pattern name="with_profile">
<description>Using AWS CLI profile</description>
<example>
provider "aws" {
region = "ap-northeast-1"
profile = "dev"
}
</example>
</pattern>
<pattern name="with_assume_role">
<description>Cross-account access with assume role</description>
<example>
provider "aws" {
region = "ap-northeast-1"
assume_role {
role_arn = "arn:aws:iam::987654321098:role/TerraformRole"
session_name = "terraform-session"
external_id = "unique-external-id"
}
}
</example>
</pattern>
<pattern name="multi_region">
<description>Multiple region configuration with aliases</description>
<example>
provider "aws" {
region = "ap-northeast-1"
alias = "tokyo"
}
provider "aws" {
region = "us-east-1"
alias = "virginia"
}
resource "aws_s3_bucket" "tokyo_bucket" {
provider = aws.tokyo
bucket = "my-tokyo-bucket"
}
resource "aws_s3_bucket" "virginia_bucket" {
provider = aws.virginia
bucket = "my-virginia-bucket"
}
</example>
</pattern>
<pattern name="default_tags">
<description>Apply default tags to all resources</description>
<example>
provider "aws" {
region = "ap-northeast-1"
default_tags {
tags = {
Environment = "dev"
ManagedBy = "terraform"
Project = "my-project"
}
}
}
</example>
</pattern>
</provider_configuration>
<backend_configuration>
Remote state with S3 and DynamoDB locking
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "env/dev/terraform.tfstate"
region = "ap-northeast-1"
encrypt = true
dynamodb_table = "terraform-locks"
}
}
<pattern name="state_locking">
<description>DynamoDB table for state locking</description>
<example>
resource "aws_dynamodb_table" "terraform_locks" {
name = "terraform-locks"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
</example>
</pattern>
</backend_configuration>
<common_resources>
VPC with subnets and internet gateway
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "main-vpc"
}
}
resource "aws_subnet" "public" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)
availability_zone = data.aws_availability_zones.available.names[count.index]
map_public_ip_on_launch = true
tags = {
Name = "public-subnet-${count.index + 1}"
}
}
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
}
</example>
</pattern>
<pattern name="security_group">
<description>Security group with ingress and egress rules</description>
<example>
resource "aws_security_group" "web" {
name = "web-sg"
description = "Security group for web servers"
vpc_id = aws_vpc.main.id
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
</example>
</pattern>
<pattern name="iam_role">
<description>IAM role with policy attachment</description>
<example>
resource "aws_iam_role" "lambda_role" {
name = "lambda-execution-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "lambda.amazonaws.com"
}
}
]
})
}
resource "aws_iam_role_policy_attachment" "lambda_basic" {
role = aws_iam_role.lambda_role.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
</example>
</pattern>
<pattern name="oidc_provider">
<description>OIDC provider for GitHub Actions (2025 recommended)</description>
<example>
resource "aws_iam_openid_connect_provider" "github" {
url = "https://token.actions.githubusercontent.com"
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = ["ffffffffffffffffffffffffffffffffffffffff"]
}
resource "aws_iam_role" "github_actions" {
name = "github-actions-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Federated = aws_iam_openid_connect_provider.github.arn
}
Action = "sts:AssumeRoleWithWebIdentity"
Condition = {
StringEquals = {
"token.actions.githubusercontent.com:aud" = "sts.amazonaws.com"
}
StringLike = {
"token.actions.githubusercontent.com:sub" = "repo:org/repo:*"
}
}
}
]
})
}
</example>
<note>Always restrict sub claim to specific repos/branches</note>
</pattern>
<pattern name="sts_preferences">
<description>STS global endpoint token version (2025 security)</description>
<example>
resource "aws_iam_security_token_service_preferences" "main" {
global_endpoint_token_version = "v2Token"
}
</example>
<note>v2Token provides regional STS tokens for improved security</note>
</pattern>
<pattern name="s3_bucket">
<description>S3 bucket with versioning, encryption, and public access block</description>
<example>
resource "aws_s3_bucket" "main" {
bucket = "my-unique-bucket-name"
}
resource "aws_s3_bucket_versioning" "main" {
bucket = aws_s3_bucket.main.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "main" {
bucket = aws_s3_bucket.main.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
resource "aws_s3_bucket_public_access_block" "main" {
bucket = aws_s3_bucket.main.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
</example>
</pattern>
<pattern name="lambda">
<description>Lambda function with environment variables</description>
<example>
resource "aws_lambda_function" "main" {
function_name = "my-function"
role = aws_iam_role.lambda_role.arn
handler = "index.handler"
runtime = "nodejs20.x" # or "nodejs22.x" (Node.js 22 LTS)
timeout = 30
memory_size = 256
filename = "lambda.zip"
source_code_hash = filebase64sha256("lambda.zip")
environment {
variables = {
ENV = "production"
}
}
}
</example>
</pattern>
<pattern name="ecs">
<description>ECS cluster with Fargate task definition</description>
<example>
resource "aws_ecs_cluster" "main" {
name = "my-cluster"
setting {
name = "containerInsights"
value = "enabled"
}
}
resource "aws_ecs_task_definition" "app" {
family = "my-app"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
cpu = "256"
memory = "512"
execution_role_arn = aws_iam_role.ecs_execution.arn
task_role_arn = aws_iam_role.ecs_task.arn
container_definitions = jsonencode([
{
name = "app"
image = "nginx:latest"
portMappings = [
{
containerPort = 80
hostPort = 80
}
]
}
])
}
</example>
</pattern>
<pattern name="rds">
<description>RDS PostgreSQL instance with encryption and backups</description>
<example>
resource "aws_db_instance" "main" {
identifier = "my-database"
engine = "postgres"
engine_version = "15"
instance_class = "db.t3.micro"
allocated_storage = 20
storage_encrypted = true
db_name = "mydb"
username = "admin"
password = var.db_password
vpc_security_group_ids = [aws_security_group.rds.id]
db_subnet_group_name = aws_db_subnet_group.main.name
backup_retention_period = 7
skip_final_snapshot = false
final_snapshot_identifier = "my-database-final"
tags = {
Name = "my-database"
}
}
</example>
</pattern>
</common_resources>
<data_sources>
Get available availability zones
data "aws_availability_zones" "available" {
state = "available"
}
<pattern name="caller_identity">
<description>Get current AWS account ID and ARN</description>
<example>
data "aws_caller_identity" "current" {}
output "account_id" {
value = data.aws_caller_identity.current.account_id
}
</example>
</pattern>
<pattern name="region">
<description>Get current AWS region</description>
<example>
data "aws_region" "current" {}
output "region" {
value = data.aws_region.current.name
}
</example>
</pattern>
<pattern name="ami">
<description>Find latest Amazon Linux AMI</description>
<example>
data "aws_ami" "amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
}
</example>
</pattern>
</data_sources>
Local module reference
module "vpc" {
source = "./modules/vpc"
cidr_block = "10.0.0.0/16"
name = "main"
}
</example>
</pattern>
<pattern name="registry_module">
<description>Terraform Registry module</description>
<example>
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.0.0"
name = "my-vpc"
cidr = "10.0.0.0/16"
azs = ["ap-northeast-1a", "ap-northeast-1c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24"]
enable_nat_gateway = true
single_nat_gateway = true
}
</example>
</pattern>
<terraform_commands>
terraform init
terraform plan -out=tfplan
terraform apply tfplan
terraform destroy
terraform fmt -recursive
terraform validate
terraform state list
terraform state show aws_instance.example
terraform import aws_instance.example i-1234567890abcdef0
terraform refresh
terraform output -json
</terraform_commands>
<terraform_anti_patterns>
Never hardcode AWS credentials in Terraform files
Use environment variables, AWS CLI profiles, or IAM roles
<avoid name="hardcoded_secrets">
<description>Never store secrets in terraform.tfvars or state</description>
<instead>Use AWS Secrets Manager, SSM Parameter Store, or external secret management</instead>
</avoid>
<avoid name="no_state_locking">
<description>Running Terraform without state locking in teams</description>
<instead>Use DynamoDB table for S3 backend locking</instead>
</avoid>
<avoid name="wildcard_permissions">
<description>Using "*" for resources and actions in IAM policies</description>
<instead>Follow least privilege principle with specific resources</instead>
</avoid>
<avoid name="unencrypted_state">
<description>Storing state without encryption</description>
<instead>Enable encryption for S3 backend state</instead>
</avoid>
<avoid name="no_versioning">
<description>Not versioning provider and module versions</description>
<instead>Pin versions with ~> or exact versions</instead>
</avoid>
</terraform_anti_patterns>
<terraform_best_practices>
Use remote state with S3 backend and DynamoDB locking
Enable state encryption with encrypt = true
Pin provider versions to avoid breaking changes
Use default_tags for consistent resource tagging
Separate environments using workspaces or directory structure
Run terraform plan before apply to review changes
Use terraform fmt before committing code
Use data sources instead of hardcoding ARNs
Store sensitive variables in environment or secret managers
Use modules for reusable infrastructure components
Enable versioning on S3 state bucket
Use lifecycle rules to prevent accidental deletion
</terraform_best_practices>
<context7_integration>
Library ID is already known: /hashicorp/terraform-provider-aws (trust score 9.8, 31100 snippets)
<tool name="get-library-docs">
<description>Fetch documentation with specific topic</description>
<use_case>VPC and networking resources (topic: vpc)</use_case>
<use_case>IAM roles and policies (topic: iam)</use_case>
<use_case>Lambda function configuration (topic: lambda)</use_case>
<use_case>ECS cluster and task definitions (topic: ecs)</use_case>
<use_case>S3 bucket configuration (topic: s3)</use_case>
</tool>
</context7_integration>
Understand AWS infrastructure requirements
1. Identify target AWS services and regions
2. Review existing infrastructure patterns
3. Check IAM permissions and policies
Implement AWS resources safely
1. Use Terraform for infrastructure as code
2. Follow least-privilege IAM principles
3. Tag resources appropriately
Verify AWS configuration correctness
1. Run terraform plan to preview changes
2. Verify security group rules
3. Test access and connectivity
<error_escalation>
Minor tagging inconsistency
Fix tags, follow naming conventions
IAM policy too permissive
Restrict permissions, apply least privilege
Security group allows unrestricted access
Stop, require security review before proceeding
Potential data exposure or credential leak
Block operation, require immediate remediation
</error_escalation>
Use Terraform for infrastructure management
Follow least-privilege IAM principles
Enable encryption at rest and in transit
Hardcoding credentials in code
Overly permissive security groups
Untagged resources
<related_skills>
Symbol operations for Terraform code navigation
Terraform AWS Provider documentation via /hashicorp/terraform-provider-aws
Debugging authentication failures and service quota issues
Creating infrastructure documentation and runbooks
</related_skills>