| 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. |
| version | 0.2.0 |
Provide comprehensive patterns for AWS CLI configuration, authentication, common operations, and Terraform AWS Provider infrastructure as code.
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
AWS credentials file (avoid storing long-term credentials)
[default]
aws_access_key_id = AKIA...
aws_secret_access_key = ...
Prefer SSO or IAM roles over long-term credentials
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
Set profile via environment variable
export AWS_PROFILE=dev
Set profile inline with command
aws s3 ls --profile prod
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
aws sso login --sso-session my-sso
aws sso logout --sso-session my-sso
PKCE authorization (default since AWS CLI v2.22.0)
Recommended for desktop/mobile access; provides secure OAuth 2.0 flow
Automatic token refresh without re-authentication
Requires AWS CLI v2.9.0+ or v1.27.10+; sso-session configuration enables token refresh support
Use SSO with sso-session for human users; use IAM roles for services
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
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
External credential provider
[profile external]
credential_process = /path/to/credential-provider
Integration with 1Password, Vault, or custom providers
OIDC federation for CI/CD (2025 best practice)
Use cases: GitHub Actions, GitLab CI, Azure DevOps with OIDC
.github/workflows/deploy.yml
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
No long-term credentials stored in CI/CD; temporary credentials via STS
Validate OIDC thumbprints and restrict ClientIDList to prevent misconfiguration
Verify current AWS identity
aws sts get-caller-identity
{
"UserId": "AIDAEXAMPLE",
"Account": "123456789012",
"Arn": "arn:aws:iam::123456789012:user/username"
}
Default, machine-readable (--output json)
Tab-delimited, scriptable (--output text)
Human-readable (--output table)
YAML format (--output yaml)
Extract single value from query
aws ec2 describe-instances --query 'Reservations[0].Instances[0].InstanceId' --output text
Extract list of values
aws ec2 describe-instances --query 'Reservations[].Instances[].InstanceId' --output text
Filter results by condition
aws ec2 describe-instances --query 'Reservations[].Instances[?State.Name==`running`].InstanceId' --output text
Project multiple fields with custom formatting
aws ec2 describe-instances --query 'Reservations[].Instances[].[InstanceId,State.Name,Tags[?Key==`Name`].Value|[0]]' --output table
Sort results by field
aws ec2 describe-instances --query 'sort_by(Reservations[].Instances[], &LaunchTime)[].InstanceId'
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'
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
aws secretsmanager get-secret-value --secret-id my-secret --query SecretString --output text
aws secretsmanager create-secret --name my-secret --secret-string '{"key":"value"}'
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
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 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
Batch operations using xargs
aws ec2 describe-instances --query 'Reservations[].Instances[].InstanceId' --output text | \
xargs -I {} aws ec2 create-tags --resources {} --tags Key=Backup,Value=true
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
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
Basic AWS provider configuration
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
Using AWS CLI profile
provider "aws" {
region = "ap-northeast-1"
profile = "dev"
}
Cross-account access with assume role
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"
}
}
Multiple region configuration with aliases
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"
}
Apply default tags to all resources
provider "aws" {
region = "ap-northeast-1"
default_tags {
tags = {
Environment = "dev"
ManagedBy = "terraform"
Project = "my-project"
}
}
}
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"
}
}
DynamoDB table for state locking
resource "aws_dynamodb_table" "terraform_locks" {
name = "terraform-locks"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
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
}
Security group with ingress and egress rules
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"]
}
}
IAM role with policy attachment
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"
}
OIDC provider for GitHub Actions (2025 recommended)
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:*"
}
}
}
]
})
}
Always restrict sub claim to specific repos/branches
STS global endpoint token version (2025 security)
resource "aws_iam_security_token_service_preferences" "main" {
global_endpoint_token_version = "v2Token"
}
v2Token provides regional STS tokens for improved security
S3 bucket with versioning, encryption, and public access block
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
}
Lambda function with environment variables
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"
}
}
}
ECS cluster with Fargate task definition
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
}
]
}
])
}
RDS PostgreSQL instance with encryption and backups
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"
}
}
Get available availability zones
data "aws_availability_zones" "available" {
state = "available"
}
Get current AWS account ID and ARN
data "aws_caller_identity" "current" {}
output "account_id" {
value = data.aws_caller_identity.current.account_id
}
Get current AWS region
data "aws_region" "current" {}
output "region" {
value = data.aws_region.current.name
}
Find latest Amazon Linux AMI
data "aws_ami" "amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
}
Local module reference
module "vpc" {
source = "./modules/vpc"
cidr_block = "10.0.0.0/16"
name = "main"
}
Terraform Registry module
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
}
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
Never hardcode AWS credentials in Terraform files
Use environment variables, AWS CLI profiles, or IAM roles
Never store secrets in terraform.tfvars or state
Use AWS Secrets Manager, SSM Parameter Store, or external secret management
Running Terraform without state locking in teams
Use DynamoDB table for S3 backend locking
Using "*" for resources and actions in IAM policies
Follow least privilege principle with specific resources
Storing state without encryption
Enable encryption for S3 backend state
Not versioning provider and module versions
Pin versions with ~> or exact versions
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
Library ID is already known: /hashicorp/terraform-provider-aws (trust score 9.8, 31100 snippets)
Fetch documentation with specific topic
VPC and networking resources (topic: vpc)
IAM roles and policies (topic: iam)
Lambda function configuration (topic: lambda)
ECS cluster and task definitions (topic: ecs)
S3 bucket configuration (topic: s3)