Skip to main content

Least Privilege Principle

The GovTech platform implements strict least privilege access control with a three-tier functional hierarchy:
Why Least Privilege is Critical in Cloud:In an on-premise environment, physical access is the primary security barrier. In AWS, any compromised credential (access key, session token) can execute destructive operations from anywhere in the world within seconds. Least privilege limits the blast radius to a single functional domain.

Functional Hierarchy

AWS IAM doesn’t have native group hierarchies. This hierarchy is functional and risk-based, defining who has access to what resources with what level of oversight.
                    [ govtech-admin ]
                    Principal Operator
                    Member of all groups
                            |
        +-------------------+-------------------+
        |                   |                   |
   LEVEL 1             LEVEL 2             LEVEL 3
   Critical            Operational          Read-Only
        |                   |                   |
   Network-Admin       Container-Deploy    Secrets-ReadOnly
   EKS-Admin           ALB-Operator        Monitor-ReadOnly
   Database-Admin      CICD-Operator       Security-Auditor
   Terraform-Operator

Access Requirements by Level

Risk Level: A malicious actor could destroy entire infrastructureGroups:
  • GovTech-Network-Admin
  • GovTech-EKS-Admin
  • GovTech-Database-Admin
  • GovTech-Terraform-Operator
Access Rules:
  • Hardware MFA required (YubiKey recommended)
  • Maximum 8-hour session duration
  • Requires approval from second responsible party
  • All actions generate immediate CloudWatch alerts
  • Weekly access review required

IAM Groups and Policies

Level 1: Critical Access

Managed Policies:
  • AmazonEC2FullAccess
  • AmazonVPCFullAccess
Allows:
  • Create and modify VPCs, subnets, Internet Gateways, NAT Gateways
  • Manage Security Groups and Network ACLs
  • Configure Route Tables
  • Modify EC2 instances and network interfaces
Use Cases:
  • Network architecture changes
  • New subnet creation
  • Security group firewall rules
  • VPC peering configuration
Managed Policies:
  • AmazonEKSClusterPolicy
Custom Policies:
  • GovTech-IAM-EKS-Roles
Allows:
  • Create and manage EKS clusters
  • Configure node groups
  • Upgrade Kubernetes versions
  • Create IAM roles for EKS (prefix eks-* and govtech-*)
  • Manage OIDC providers for IRSA
Use Cases:
  • EKS cluster creation/upgrades
  • Node group scaling
  • Kubernetes version updates
  • IRSA (IAM Roles for Service Accounts) setup
Custom Policies:
  • GovTech-RDS-Admin
Allows:
  • Create and modify RDS instances
  • Configure database parameters
  • Create and restore snapshots
  • Manage DB subnet groups
Protection:
{
  "Sid": "RDSDeletePrevention",
  "Effect": "Deny",
  "Action": ["rds:DeleteDBInstance"],
  "Resource": "*",
  "Condition": {
    "StringLike": {
      "rds:db-tag/Environment": "production"
    }
  }
}
Production databases with tag Environment: production cannot be deleted.Use Cases:
  • Database maintenance
  • Parameter tuning
  • Backup and restore
  • Performance optimization
Custom Policies:
  • GovTech-Terraform-State
  • GovTech-S3-Admin
Allows:
  • Read/write Terraform state in S3 bucket govtech-terraform-state
  • DynamoDB state locking (table: terraform-locks)
  • Manage S3 buckets with prefix govtech-*
State Configuration:
{
  "Sid": "TerraformStateAccess",
  "Effect": "Allow",
  "Action": [
    "s3:ListBucket",
    "s3:GetObject",
    "s3:PutObject"
  ],
  "Resource": [
    "arn:aws:s3:::govtech-terraform-state",
    "arn:aws:s3:::govtech-terraform-state/*"
  ]
}
Use Cases:
  • Execute terraform apply
  • Infrastructure changes
  • Application S3 bucket management

Level 2: Operational Access

Custom Policies:
  • GovTech-ECR-Admin
  • GovTech-EKS-Deploy
ECR Admin Policy:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ECRFullAccess",
      "Effect": "Allow",
      "Action": [
        "ecr:CreateRepository",
        "ecr:DeleteRepository",
        "ecr:DescribeRepositories",
        "ecr:PutImage",
        "ecr:BatchCheckLayerAvailability",
        "ecr:InitiateLayerUpload",
        "ecr:UploadLayerPart",
        "ecr:CompleteLayerUpload",
        "ecr:GetAuthorizationToken"
      ],
      "Resource": "*"
    }
  ]
}
EKS Deploy Policy:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "EKSClusterAccess",
      "Effect": "Allow",
      "Action": [
        "eks:DescribeCluster",
        "eks:ListClusters",
        "eks:AccessKubernetesApi"
      ],
      "Resource": "*"
    },
    {
      "Sid": "EBSVolumeManagement",
      "Effect": "Allow",
      "Action": [
        "ec2:CreateVolume",
        "ec2:AttachVolume",
        "ec2:DetachVolume",
        "ec2:DescribeVolumes"
      ],
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "ec2:ResourceTag/Kubernetes": "owned"
        }
      }
    }
  ]
}
Use Cases:
  • Deploy new application versions
  • Push Docker images to ECR
  • Execute kubectl apply
  • Manage Kubernetes deployments
Custom Policies:
  • GovTech-ALB-Controller
  • GovTech-AutoScaling
ALB Controller Permissions:
  • Create/modify Application Load Balancers
  • Manage Target Groups and Listeners
  • Configure SSL/TLS certificates (ACM)
  • Integrate WAF with ALB
  • Security group management for ALBs
Key Actions:
{
  "Sid": "LoadBalancerManagement",
  "Effect": "Allow",
  "Action": [
    "elasticloadbalancing:CreateLoadBalancer",
    "elasticloadbalancing:DeleteLoadBalancer",
    "elasticloadbalancing:CreateTargetGroup",
    "elasticloadbalancing:CreateListener",
    "elasticloadbalancing:ModifyLoadBalancerAttributes"
  ],
  "Resource": "*"
}
WAF Integration:
{
  "Sid": "WAFIntegration",
  "Effect": "Allow",
  "Action": [
    "wafv2:GetWebACL",
    "wafv2:AssociateWebACL",
    "wafv2:DisassociateWebACL"
  ],
  "Resource": "*"
}
Use Cases:
  • Configure Kubernetes Ingress resources
  • Manage TLS certificates
  • Configure HPA (Horizontal Pod Autoscaler)
  • Auto-scaling group management
Custom Policies:
  • GovTech-CICD-Access
  • GovTech-ECR-ReadOnly
GitHub Actions OIDC:
{
  "Sid": "GitHubActionsOIDC",
  "Effect": "Allow",
  "Action": [
    "iam:CreateOpenIDConnectProvider",
    "iam:GetOpenIDConnectProvider",
    "iam:TagOpenIDConnectProvider"
  ],
  "Resource": "arn:aws:iam::835960996869:oidc-provider/token.actions.githubusercontent.com"
}
CI/CD Secrets:
{
  "Sid": "SecretsForCICD",
  "Effect": "Allow",
  "Action": [
    "secretsmanager:GetSecretValue",
    "secretsmanager:CreateSecret",
    "secretsmanager:UpdateSecret"
  ],
  "Resource": "arn:aws:secretsmanager:us-east-1:*:secret:govtech/cicd/*"
}
Use Cases:
  • Configure GitHub Actions workflows
  • Manage CI/CD pipeline credentials
  • Pull container images for testing

Level 3: Read-Only Access

Custom Policies:
  • GovTech-Secrets-Read
Environment-Based Access:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "SecretsReadDev",
      "Effect": "Allow",
      "Action": [
        "secretsmanager:GetSecretValue",
        "secretsmanager:DescribeSecret"
      ],
      "Resource": "arn:aws:secretsmanager:us-east-1:*:secret:govtech/dev/*"
    },
    {
      "Sid": "SecretsReadStaging",
      "Effect": "Allow",
      "Action": [
        "secretsmanager:GetSecretValue",
        "secretsmanager:DescribeSecret"
      ],
      "Resource": "arn:aws:secretsmanager:us-east-1:*:secret:govtech/staging/*"
    },
    {
      "Sid": "DenyProdSecrets",
      "Effect": "Deny",
      "Action": ["secretsmanager:*"],
      "Resource": "arn:aws:secretsmanager:us-east-1:*:secret:govtech/prod/*"
    }
  ]
}
Production secrets are explicitly denied even if AWS account permissions would otherwise allow access.
Use Cases:
  • Deployment scripts needing credentials
  • Troubleshooting configuration issues
  • Development environment setup
Managed Policies:
  • CloudWatchReadOnlyAccess
Custom Policies:
  • GovTech-Monitoring
Monitoring Policy:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "CloudWatchReadAccess",
      "Effect": "Allow",
      "Action": [
        "cloudwatch:GetMetricData",
        "cloudwatch:ListMetrics",
        "cloudwatch:DescribeAlarms",
        "logs:DescribeLogGroups",
        "logs:GetLogEvents",
        "logs:FilterLogEvents"
      ],
      "Resource": "*"
    },
    {
      "Sid": "GuardDutyReadAccess",
      "Effect": "Allow",
      "Action": [
        "guardduty:GetDetector",
        "guardduty:GetFindings",
        "guardduty:ListFindings"
      ],
      "Resource": "*"
    }
  ]
}
Use Cases:
  • SRE/on-call monitoring
  • Performance troubleshooting
  • Log analysis
  • GuardDuty threat review
Managed Policies:
  • SecurityAudit
Custom Policies:
  • GovTech-Security-Auditor
Auditor Policy:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "CloudTrailReadOnly",
      "Effect": "Allow",
      "Action": [
        "cloudtrail:GetTrail",
        "cloudtrail:ListTrails",
        "cloudtrail:LookupEvents",
        "cloudtrail:DescribeTrails"
      ],
      "Resource": "*"
    },
    {
      "Sid": "SecurityHubReadOnly",
      "Effect": "Allow",
      "Action": [
        "securityhub:GetFindings",
        "securityhub:ListFindings",
        "securityhub:DescribeStandardsControls"
      ],
      "Resource": "*"
    },
    {
      "Sid": "IAMAccessAnalyzerReadOnly",
      "Effect": "Allow",
      "Action": [
        "access-analyzer:ListAnalyzers",
        "access-analyzer:ListFindings"
      ],
      "Resource": "*"
    }
  ]
}
Use Cases:
  • Security audits
  • Compliance reviews
  • Incident investigation
  • Access pattern analysis

Permission Boundaries

All roles use a permission boundary to enforce hard limits:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowedServices",
      "Effect": "Allow",
      "Action": [
        "ec2:*",
        "eks:*",
        "ecr:*",
        "rds:*",
        "s3:*",
        "cloudwatch:*",
        "secretsmanager:*"
      ],
      "Resource": "*"
    },
    {
      "Sid": "DenyDangerousActions",
      "Effect": "Deny",
      "Action": [
        "iam:CreateUser",
        "iam:DeleteUser",
        "iam:CreateAccessKey",
        "organizations:*",
        "account:*"
      ],
      "Resource": "*"
    },
    {
      "Sid": "DenyRegionOutsideUSEast1",
      "Effect": "Deny",
      "Action": "*",
      "Resource": "*",
      "Condition": {
        "StringNotEquals": {
          "aws:RequestedRegion": "us-east-1"
        }
      }
    }
  ]
}
Permission boundaries act as a maximum permission set. Even if a user’s policy grants access, the permission boundary can still deny it.

User Management

Adding a New User

# 1. Create the user
aws iam create-user --user-name john.doe

# 2. Assign to appropriate groups based on role
aws iam add-user-to-group \
  --user-name john.doe \
  --group-name GovTech-Container-Deploy

aws iam add-user-to-group \
  --user-name john.doe \
  --group-name GovTech-Monitor-ReadOnly

# 3. Create console access with temporary password
aws iam create-login-profile \
  --user-name john.doe \
  --password "TempPass2026!" \
  --password-reset-required

# 4. Enable MFA (user must complete via console)
echo "User must enable MFA at first login"
RoleRecommended Groups
Cloud ArchitectNetwork-Admin, EKS-Admin, Terraform-Operator (temporary)
DevOps EngineerContainer-Deploy, CICD-Operator
SRE / On-CallMonitor-ReadOnly, Secrets-ReadOnly
Database AdministratorDatabase-Admin (temporary for maintenance)
Security AnalystSecurity-Auditor
DeveloperContainer-Deploy (if responsible for own deployments)

Rotating Access Keys

1

Create New Key

aws iam create-access-key --user-name govtech-admin
Save the new AccessKeyId and SecretAccessKey.
2

Test New Key

Configure new key in AWS CLI and verify it works:
aws configure --profile govtech-new
aws sts get-caller-identity --profile govtech-new
3

Deactivate Old Key

aws iam update-access-key \
  --user-name govtech-admin \
  --access-key-id AKIA_OLD_KEY \
  --status Inactive
4

Delete Old Key

After confirming new key works everywhere:
aws iam delete-access-key \
  --user-name govtech-admin \
  --access-key-id AKIA_OLD_KEY

Audit Commands

# View all groups for a user
aws iam list-groups-for-user --user-name govtech-admin

# List all policies attached to a group
aws iam list-attached-group-policies --group-name GovTech-EKS-Admin

# Check active access keys and their age
aws iam list-access-keys --user-name govtech-admin

# View recent CloudTrail events for a user
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=Username,AttributeValue=govtech-admin \
  --max-results 20

# Find all "delete" operations in last 7 days
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=DeleteDBInstance

Monthly Security Checklist

  • Review CloudTrail for unusual actions or off-hours access
  • Verify no access keys older than 90 days
  • Confirm MFA is enabled for all users
  • Review active GuardDuty and Security Hub findings
  • Validate no users with direct permissions (must use groups)
  • Check for IAM roles with excessive permissions
  • Verify permission boundaries are attached to all roles
  • Review temporary access grants (should be revoked after use)

Next Steps

Network Policies

Learn about Kubernetes network segmentation

Secrets Management

Secure credential management with AWS Secrets Manager

Build docs developers (and LLMs) love