RepliMap Docs

IAM Policy

Minimum permissions required for RepliMap

RepliMap requires read-only access to scan your AWS resources. We adhere to the principle of least privilege.

This policy allows RepliMap to scan all supported resource types (including the graph-only types listed below):

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RepliMapReadOnly",
            "Effect": "Allow",
            "Action": [
                "ec2:Describe*",
                "rds:Describe*",
                "rds:ListTagsForResource",
                "s3:GetBucket*",
                "s3:GetLifecycleConfiguration",
                "s3:GetEncryptionConfiguration",
                "s3:GetReplicationConfiguration",
                "s3:ListAllMyBuckets",
                "elasticache:Describe*",
                "elasticache:ListTagsForResource",
                "elasticloadbalancing:Describe*",
                "autoscaling:Describe*",
                "route53:ListHostedZones",
                "route53:GetHostedZone",
                "route53:ListResourceRecordSets",
                "route53:ListTagsForResource",
                "acm:ListCertificates",
                "acm:DescribeCertificate",
                "acm:ListTagsForCertificate",
                "cloudfront:ListDistributions",
                "cloudfront:GetDistributionConfig",
                "cloudfront:ListTagsForResource",
                "ecs:ListClusters",
                "ecs:DescribeClusters",
                "ecs:ListServices",
                "ecs:DescribeServices",
                "ecs:ListTaskDefinitionFamilies",
                "ecs:ListTaskDefinitions",
                "ecs:DescribeTaskDefinition",
                "ecs:ListTagsForResource",
                "ecr:DescribeRepositories",
                "ecr:ListTagsForResource",
                "iam:ListRoles",
                "iam:ListPolicies",
                "iam:ListInstanceProfiles",
                "iam:ListInstanceProfilesForRole",
                "iam:ListAttachedRolePolicies",
                "iam:ListRolePolicies",
                "iam:ListRoleTags",
                "iam:ListInstanceProfileTags",
                "iam:ListAccessKeys",
                "iam:GetRole",
                "iam:GetPolicy",
                "iam:GetInstanceProfile",
                "lambda:ListFunctions",
                "lambda:GetFunctionConfiguration",
                "lambda:ListEventSourceMappings",
                "lambda:ListTags",
                "lambda:GetFunctionUrlConfig",
                "lambda:GetPolicy",
                "dynamodb:ListTables",
                "dynamodb:DescribeTable",
                "dynamodb:ListTagsOfResource",
                "dynamodb:DescribeContinuousBackups",
                "dynamodb:DescribeTimeToLive",
                "sqs:GetQueueAttributes",
                "sqs:ListQueues",
                "sqs:ListQueueTags",
                "sns:GetTopicAttributes",
                "sns:ListTopics",
                "sns:ListTagsForResource",
                "logs:DescribeLogGroups",
                "logs:ListTagsLogGroup",
                "cloudwatch:DescribeAlarms",
                "cloudwatch:ListTagsForResource",
                "secretsmanager:ListSecrets",
                "secretsmanager:DescribeSecret",
                "ssm:DescribeParameters",
                "ssm:ListTagsForResource",
                "kms:ListKeys",
                "kms:DescribeKey",
                "kms:ListAliases",
                "kms:ListResourceTags",
                "kms:GetKeyRotationStatus",
                "kms:GetKeyPolicy",
                "tag:GetResources",
                "sts:GetCallerIdentity",
                "sts:GetSessionToken"
            ],
            "Resource": "*"
        },
        {
            "Sid": "RepliMapApiGatewayRead",
            "Effect": "Allow",
            "Action": "apigateway:GET",
            "Resource": [
                "arn:aws:apigateway:*::/restapis",
                "arn:aws:apigateway:*::/restapis/*/resources",
                "arn:aws:apigateway:*::/restapis/*/resources/*/methods/*/integration",
                "arn:aws:apigateway:*::/restapis/*/stages",
                "arn:aws:apigateway:*::/restapis/*/authorizers",
                "arn:aws:apigateway:*::/domainnames",
                "arn:aws:apigateway:*::/domainnames/*/basepathmappings",
                "arn:aws:apigateway:*::/domainnames/*/apimappings",
                "arn:aws:apigateway:*::/vpclinks",
                "arn:aws:apigateway:*::/apis",
                "arn:aws:apigateway:*::/apis/*/integrations",
                "arn:aws:apigateway:*::/apis/*/routes",
                "arn:aws:apigateway:*::/apis/*/stages",
                "arn:aws:apigateway:*::/apis/*/authorizers"
            ]
        }
    ]
}

A minimal policy for scanning VPCs only:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RepliMapVPCRead",
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeVpcs",
                "ec2:DescribeSubnets",
                "ec2:DescribeSecurityGroups",
                "ec2:DescribeInstances",
                "ec2:DescribeTags",
                "sts:GetCallerIdentity"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "ec2:Region": "us-east-1"
                }
            }
        }
    ]
}

Notes on Specific Services

API Gateway (graph only): apigateway:GET is scoped to the specific list endpoints RepliMap calls (REST APIs, resources/integrations, stages, authorizers, custom domains and their mappings, VPC links, and the v2 equivalents). It deliberately excludes API keys, usage plans, exports and SDK generation, so API key values can never be read.

Lambda and DynamoDB: RepliMap scans Lambda functions and event source mappings, and DynamoDB table definitions, so serverless chains (API Gateway -> Lambda -> DynamoDB/SQS) appear in the dependency graph. Lambda functions are graph-only (no Terraform is generated for them, because that would need the code package); event source mappings and DynamoDB tables are generated. Lambda environment variable values are never stored: only the variable names are kept, redacted at ingestion.

RepliMap never calls lambda:GetFunction (it returns a presigned code download URL), lambda:InvokeFunction, lambda:GetLayerVersion, or any DynamoDB data-plane action (Scan, Query, GetItem, BatchGetItem, ExportTableToPointInTime). Table items and function code are never read, so none of those permissions are needed.

replimap deps (Pro+) also uses the IAM-policy actions above to resolve cross-service dependencies (e.g. which policies are attached to an IAM role), read-only. sts:GetSessionToken is used only by the optional MFA session-refresh path.

DNS / certificate / CDN actions (route53:*, acm:*, cloudfront:*) are all List*/Get*/Describe*. route53:GetHostedZone is only called for private hosted zones, to read their VPC associations. RepliMap never calls acm:ExportCertificate (it returns private keys) or acm:GetCertificate. CloudFront certificates live in us-east-1, so when you scan another region the ACM calls are also made against us-east-1 (restricted to certificates a CloudFront distribution uses); if an SCP blocks that region the scan continues without them. ECS / ECR: the ecs:* / ecr:* actions above are metadata reads only. RepliMap never calls ecr:GetAuthorizationToken, ecr:BatchGetImage, ecr:GetDownloadUrlForLayer or ecs:ExecuteCommand, so image contents and container shells are unreachable. Task definition environment variable values are redacted before storage; only the variable names are kept. ecs:ListTagsForResource backs the include=TAGS option on the ECS Describe* calls.

EC2 user data

Launch template UserData is returned by ec2:DescribeLaunchTemplateVersions (covered by ec2:Describe*). RepliMap reads it in memory and redacts it before anything is stored. RepliMap does not call ec2:DescribeInstanceAttribute, so instance user data is never read. codify does not emit user_data for instances or launch templates (it adds ignore_changes); see the generated comment for how to read it yourself.

Secrets Manager, SSM Parameter Store and KMS: metadata only

RepliMap maps where credentials and config live and which key encrypts them, never the credentials themselves. The secretsmanager:*, ssm:* and kms:* actions above return names, descriptions, key ids, rotation settings, tags and key policy documents only.

RepliMap never needs (and the code never calls) any of these, so do not grant them:

  • secretsmanager:GetSecretValue
  • ssm:GetParameter, ssm:GetParameters, ssm:GetParametersByPath (these return values even for plain String parameters)
  • kms:Decrypt (and kms:Encrypt, kms:GenerateDataKey*)

kms:GetKeyPolicy reads the key policy document (never key material) so codify can emit it and the first plan shows no policy change; a key whose policy cannot be read is still scanned, without a policy. Keys in other accounts, or keys you cannot describe, are skipped without failing the scan.

Optional: remote Terraform state for drift --state-bucket

The policy above grants no access to S3 object contents. Only if you run replimap drift --state-bucket, add a separate statement scoped to the single state object RepliMap should read (replace the bucket and key):

{
    "Sid": "RepliMapReadTerraformState",
    "Effect": "Allow",
    "Action": "s3:GetObject",
    "Resource": "arn:aws:s3:::YOUR-STATE-BUCKET/path/to/terraform.tfstate"
}

If your state bucket uses SSE-KMS, the principal also needs kms:Decrypt on that bucket's key.


Setup Instructions

Option 1: Create Dedicated IAM User

  1. Go to IAM Console → Users → Add User
  2. Name: replimap-scanner
  3. Access type: Programmatic access
  4. Attach the policy above
  5. Save the access keys
# Configure AWS CLI
aws configure --profile replimap
# Enter the access key ID and secret
  1. Go to IAM Console → Roles → Create Role
  2. Select AWS service → EC2/ECS
  3. Attach the policy above
  4. Name: replimap-scanner-role

Verify Permissions

# Verify identity
aws sts get-caller-identity --profile replimap

# Test VPC access
aws ec2 describe-vpcs --profile replimap --region us-east-1

# Test with RepliMap
replimap scan --profile replimap --region us-east-1

Permissions by Resource Type

ResourceActions RequiredPurpose
VPCec2:DescribeVpcsScan VPC configurations
Subnetec2:DescribeSubnetsScan subnet configurations
Security Groupec2:DescribeSecurityGroupsScan security rules
EC2 Instanceec2:DescribeInstancesScan instance configurations
RDS Instancerds:DescribeDBInstancesScan database configurations
S3 Buckets3:ListAllMyBuckets, s3:GetBucket*Scan bucket configurations
ELB/ALBelasticloadbalancing:Describe*Scan load balancers, listeners, target groups
IAMiam:ListRoles, iam:ListPolicies, iam:ListRoleTagsScan roles, policies, instance profiles
SQS / SNSsqs:ListQueues, sns:ListTopicsScan messaging resources
CloudWatchlogs:DescribeLogGroups, cloudwatch:DescribeAlarmsScan log groups and alarms
DNS / CDN / Certificatesroute53:List*, route53:GetHostedZone, acm:ListCertificates, acm:DescribeCertificate, cloudfront:ListDistributions, cloudfront:GetDistributionConfigScan Route53 zones and records, ACM certificates, CloudFront distributions
ECS / ECRecs:List*, ecs:Describe*, ecr:DescribeRepositoriesScan clusters, services, task definitions and repositories (metadata only)
API Gatewayapigateway:GET (scoped list endpoints)Dependency graph only
Lambda / DynamoDBlambda:ListFunctions, lambda:GetFunctionConfiguration, dynamodb:ListTables, dynamodb:DescribeTableScan function configuration (never code) and table definitions (never items)
Secrets Manager / SSM / KMSsecretsmanager:ListSecrets, secretsmanager:DescribeSecret, ssm:DescribeParameters, kms:ListKeys, kms:DescribeKey, kms:GetKeyPolicyScan metadata only, never secret or parameter values
STSsts:GetCallerIdentityVerify authentication

What RepliMap Does NOT Do

RepliMap never:

  • ❌ Creates, modifies, or deletes any AWS resources
  • ❌ Accesses S3 bucket contents (only metadata)
  • ❌ Reads database contents
  • ❌ Accesses secrets or credentials
  • ❌ Makes cross-account API calls
  • ❌ Uploads any data to external services

Troubleshooting

"Access Denied" Error

AccessDeniedException: User: arn:aws:iam::123456789012:user/replimap
is not authorized to perform: ec2:DescribeVpcs

Solution: Ensure the IAM policy is correctly attached to your user/role.

"InvalidClientTokenId" Error

InvalidClientTokenId: The security token included in the request is invalid.

Solution: Check your AWS credentials are correctly configured:

aws configure list --profile replimap

Region-Specific Issues

If you only have access to specific regions:

# Specify the region explicitly
replimap scan --profile replimap --region eu-west-1

On this page