IAM Admin User Setup Guide
Complete guide for setting up an admin IAM user with appropriate permissions for managing the FishingLog AWS infrastructure.
📋 Overview
This guide covers IAM policies for an admin user who needs to manage:
- ✅ Cognito (user management)
- ✅ ECS (container deployment)
- ✅ ECR (Docker images)
- ✅ RDS (PostgreSQL database)
- ✅ ElastiCache/Valkey (caching)
- ✅ S3 (images/media storage)
- ✅ CloudWatch (logs & monitoring)
- ✅ Load Balancer (traffic distribution)
- ✅ Certificate Manager (SSL certificates)
- ✅ IAM (role management)
🔐 Step 1: Create Admin User
-
AWS Console → IAM → Users → Create user
-
User name:
fishinglog-admin(or your preferred name) -
Access type:
- ✅ Provide user access to the AWS Management Console - Checked (for console access)
- ✅ Access key - Programmatic access - Checked (for CLI/API access)
-
Set permissions → Choose one of the options below
🎯 Option 1: AWS Managed Policies (Quick Setup)
Pros: Easy to set up, AWS-maintained
Cons: May include more permissions than needed
Recommended Managed Policies:
-
PowerUserAccess (Recommended for Admin)
- Full access except IAM user/role management
- Good balance of power and security
- Can manage all services but can't create/delete IAM users/roles
-
Or combine these specific policies:
AmazonEC2FullAccess(for Load Balancer, Security Groups)AmazonECS_FullAccess(for ECS management)AmazonEC2ContainerRegistryFullAccess(for ECR)AmazonRDSFullAccess(for database management)AmazonElastiCacheFullAccess(for Valkey cache)AmazonS3FullAccess(for S3 buckets)AmazonCognitoPowerUser(for Cognito user management)CloudWatchFullAccess(for logs & metrics)AWSCertificateManagerFullAccess(for SSL certificates)
Note: These are broad policies. For better security, use Option 2 (Custom Policy).
🎯 Option 2: Custom Policy (Recommended - More Secure)
Pros: Least privilege, only what you need
Cons: Requires more setup, needs updates as services grow
Create Custom Admin Policy
-
IAM Console → Policies → Create policy → JSON
-
Policy name:
FishingLogAdminPolicy -
Description:
Full admin access to FishingLog AWS resources (staging + production) -
Policy JSON:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CognitoUserManagement",
"Effect": "Allow",
"Action": [
"cognito-idp:AdminCreateUser",
"cognito-idp:AdminDeleteUser",
"cognito-idp:AdminGetUser",
"cognito-idp:AdminSetUserPassword",
"cognito-idp:AdminConfirmSignUp",
"cognito-idp:AdminEnableUser",
"cognito-idp:AdminDisableUser",
"cognito-idp:AdminResetUserPassword",
"cognito-idp:ListUsers",
"cognito-idp:DescribeUserPool",
"cognito-idp:DescribeUserPoolClient"
],
"Resource": [
"arn:aws:cognito-idp:us-east-2:606532921651:userpool/us-east-2_TZtGx1T3X"
]
},
{
"Sid": "ECRManagement",
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:PutImage",
"ecr:InitiateLayerUpload",
"ecr:UploadLayerPart",
"ecr:CompleteLayerUpload",
"ecr:DescribeRepositories",
"ecr:ListImages",
"ecr:CreateRepository",
"ecr:DeleteRepository",
"ecr:TagResource",
"ecr:UntagResource"
],
"Resource": [
"arn:aws:ecr:us-east-2:606532921651:repository/reelog-api-staging",
"arn:aws:ecr:us-east-2:606532921651:repository/reelog-api-prod"
]
},
{
"Sid": "ECSManagement",
"Effect": "Allow",
"Action": [
"ecs:CreateCluster",
"ecs:DeleteCluster",
"ecs:DescribeClusters",
"ecs:ListClusters",
"ecs:CreateService",
"ecs:UpdateService",
"ecs:DeleteService",
"ecs:DescribeServices",
"ecs:ListServices",
"ecs:RegisterTaskDefinition",
"ecs:DeregisterTaskDefinition",
"ecs:DescribeTaskDefinition",
"ecs:ListTaskDefinitions",
"ecs:RunTask",
"ecs:StopTask",
"ecs:DescribeTasks",
"ecs:ListTasks",
"ecs:TagResource",
"ecs:UntagResource"
],
"Resource": "*"
},
{
"Sid": "RDSManagement",
"Effect": "Allow",
"Action": [
"rds:DescribeDBInstances",
"rds:DescribeDBClusters",
"rds:CreateDBInstance",
"rds:ModifyDBInstance",
"rds:DeleteDBInstance",
"rds:RebootDBInstance",
"rds:CreateDBSnapshot",
"rds:DescribeDBSnapshots",
"rds:RestoreDBInstanceFromDBSnapshot",
"rds:StartDBInstance",
"rds:StopDBInstance",
"rds:AddTagsToResource",
"rds:RemoveTagsFromResource",
"rds:ListTagsForResource"
],
"Resource": [
"arn:aws:rds:us-east-2:606532921651:db:reelog-db-staging",
"arn:aws:rds:us-east-2:606532921651:db:reelog-db-prod"
]
},
{
"Sid": "ElastiCacheManagement",
"Effect": "Allow",
"Action": [
"elasticache:DescribeCacheClusters",
"elasticache:DescribeReplicationGroups",
"elasticache:CreateCacheCluster",
"elasticache:ModifyCacheCluster",
"elasticache:DeleteCacheCluster",
"elasticache:RebootCacheCluster",
"elasticache:CreateSnapshot",
"elasticache:DescribeSnapshots",
"elasticache:AddTagsToResource",
"elasticache:RemoveTagsFromResource",
"elasticache:ListTagsForResource"
],
"Resource": "*"
},
{
"Sid": "S3Management",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:ListBucket",
"s3:GetBucketLocation",
"s3:GetBucketAcl",
"s3:PutBucketAcl",
"s3:GetBucketPolicy",
"s3:PutBucketPolicy",
"s3:DeleteBucketPolicy",
"s3:GetBucketTagging",
"s3:PutBucketTagging"
],
"Resource": [
"arn:aws:s3:::reelog-media-staging",
"arn:aws:s3:::reelog-media-staging/*",
"arn:aws:s3:::reelog-media-prod",
"arn:aws:s3:::reelog-media-prod/*"
]
},
{
"Sid": "LoadBalancerManagement",
"Effect": "Allow",
"Action": [
"elasticloadbalancing:CreateLoadBalancer",
"elasticloadbalancing:DeleteLoadBalancer",
"elasticloadbalancing:DescribeLoadBalancers",
"elasticloadbalancing:ModifyLoadBalancerAttributes",
"elasticloadbalancing:CreateTargetGroup",
"elasticloadbalancing:DeleteTargetGroup",
"elasticloadbalancing:DescribeTargetGroups",
"elasticloadbalancing:ModifyTargetGroup",
"elasticloadbalancing:RegisterTargets",
"elasticloadbalancing:DeregisterTargets",
"elasticloadbalancing:DescribeTargetHealth",
"elasticloadbalancing:CreateListener",
"elasticloadbalancing:DeleteListener",
"elasticloadbalancing:DescribeListeners",
"elasticloadbalancing:ModifyListener",
"elasticloadbalancing:AddTags",
"elasticloadbalancing:RemoveTags"
],
"Resource": "*"
},
{
"Sid": "CloudWatchManagement",
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:DeleteLogGroup",
"logs:DescribeLogGroups",
"logs:CreateLogStream",
"logs:DeleteLogStream",
"logs:DescribeLogStreams",
"logs:PutLogEvents",
"logs:GetLogEvents",
"logs:FilterLogEvents",
"logs:TagLogGroup",
"cloudwatch:GetMetricStatistics",
"cloudwatch:ListMetrics",
"cloudwatch:PutMetricAlarm",
"cloudwatch:DeleteAlarms",
"cloudwatch:DescribeAlarms"
],
"Resource": "*"
},
{
"Sid": "CertificateManager",
"Effect": "Allow",
"Action": [
"acm:RequestCertificate",
"acm:DescribeCertificate",
"acm:ListCertificates",
"acm:DeleteCertificate",
"acm:AddTagsToCertificate",
"acm:RemoveTagsFromCertificate"
],
"Resource": "*"
},
{
"Sid": "IAMRolePassThrough",
"Effect": "Allow",
"Action": [
"iam:PassRole"
],
"Resource": [
"arn:aws:iam::606532921651:role/reelog-ecs-task-execution-role",
"arn:aws:iam::606532921651:role/reelog-ecs-task-role"
]
},
{
"Sid": "IAMReadOnly",
"Effect": "Allow",
"Action": [
"iam:GetRole",
"iam:GetRolePolicy",
"iam:ListRolePolicies",
"iam:ListAttachedRolePolicies",
"iam:ListRoles",
"iam:GetPolicy",
"iam:ListPolicies",
"iam:GetUser",
"iam:ListUsers"
],
"Resource": "*"
},
{
"Sid": "EC2SecurityGroups",
"Effect": "Allow",
"Action": [
"ec2:DescribeSecurityGroups",
"ec2:CreateSecurityGroup",
"ec2:DeleteSecurityGroup",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:AuthorizeSecurityGroupEgress",
"ec2:RevokeSecurityGroupIngress",
"ec2:RevokeSecurityGroupEgress",
"ec2:DescribeVpcs",
"ec2:DescribeSubnets",
"ec2:DescribeNetworkInterfaces"
],
"Resource": "*"
},
{
"Sid": "TagManagement",
"Effect": "Allow",
"Action": [
"tag:GetResources",
"tag:TagResources",
"tag:UntagResources"
],
"Resource": "*"
}
]
}
-
Tags (optional):
Environment=AllProject=ReelogPurpose=AdminPolicy
-
Create policy
-
Attach to user:
- Go to your user → Permissions → Add permissions → Attach policies directly
- Select
FishingLogAdminPolicy - Next → Add permissions
🎯 Option 3: Hybrid Approach (Balanced)
Use AWS managed policies for broad access, plus custom policy for specific restrictions:
-
Attach managed policies:
PowerUserAccess(orReadOnlyAccess+ specific service policies)
-
Add custom policy for:
- Cognito user management (if not covered)
- IAM PassRole (for ECS task roles)
- Resource-specific restrictions (S3 buckets, RDS instances)
✅ Step 2: Configure AWS CLI
After creating the user and attaching policies:
-
Create access key:
- IAM → Users →
fishinglog-admin→ Security credentials - Access keys → Create access key
- Choose Command Line Interface (CLI)
- Copy Access key ID and Secret access key
- IAM → Users →
-
Configure AWS CLI:
aws configureEnter:
- AWS Access Key ID: Your access key
- AWS Secret Access Key: Your secret key
- Default region:
us-east-2 - Default output format:
json
-
Test configuration:
aws sts get-caller-identityShould return your account ID and user ARN.
🔒 Security Best Practices
1. Enable MFA (Multi-Factor Authentication)
Highly Recommended:
- IAM Console → Users →
fishinglog-admin - Security credentials tab
- Assigned MFA device → Assign MFA device
- Choose Virtual MFA device (use authenticator app)
- Scan QR code and enter two consecutive codes
Note: Console access will require MFA. CLI access can use session tokens.
2. Use IAM Roles Instead of Users (For Applications)
- For GitHub Actions: Use IAM user (as configured)
- For ECS tasks: Use IAM roles (already configured)
- For admin console access: IAM user with MFA
3. Rotate Access Keys Regularly
- Rotate access keys every 90 days
- IAM → Users → Security credentials → Rotate access keys
4. Use Least Privilege
- Start with minimal permissions
- Add permissions as needed
- Review and remove unused permissions quarterly
5. Enable CloudTrail
- Track all API calls made by admin user
- AWS Console → CloudTrail → Create trail
- Monitor for suspicious activity
📝 Quick Reference: What Each Service Needs
| Service | Admin Needs | Policy Section |
|---|---|---|
| Cognito | Create/delete users, set passwords | CognitoUserManagement |
| ECS | Deploy services, update tasks | ECSManagement |
| ECR | Push/pull Docker images | ECRManagement |
| RDS | Manage database instances | RDSManagement |
| ElastiCache | Manage cache clusters | ElastiCacheManagement |
| S3 | Upload/download files, manage buckets | S3Management |
| Load Balancer | Create/update load balancers | LoadBalancerManagement |
| CloudWatch | View logs, create alarms | CloudWatchManagement |
| ACM | Manage SSL certificates | CertificateManager |
| IAM | Pass roles to ECS tasks | IAMRolePassThrough |
🚨 Common Issues
Issue: "Access Denied" when running AWS CLI commands
Solution:
- Check IAM user has correct policies attached
- Verify access keys are correct:
aws configure list - Test with:
aws sts get-caller-identity
Issue: "Cannot assume role" for ECS tasks
Solution:
- Ensure
iam:PassRolepermission is granted - Verify role ARNs in policy match your actual roles
Issue: "Cannot access S3 bucket"
Solution:
- Check S3 bucket ARNs in policy match your buckets
- Verify bucket names:
reelog-media-staging,reelog-media-prod
📚 Next Steps
- ✅ Create admin user with policies
- ✅ Configure AWS CLI
- ✅ Enable MFA
- ✅ Test Cognito user creation:
aws cognito-idp admin-create-user ... - ✅ Test ECS deployment
- ✅ Review CloudTrail logs
Account ID: 606532921651
Region: us-east-2
Last Updated: December 10, 2025