snyk / driftctl

Detect, track and alert on infrastructure drift
Apache License 2.0
2.45k stars 152 forks source link

AWS IAM role inline policy false positive #1556

Open jcollado opened 2 years ago

jcollado commented 2 years ago

Description

AWS IAM role inline policies reported as not covered by IaC, but they are in both the code and the terraform state file. Possibly related to #892.

Environment

How to reproduce

Define an aws_iam_role resource. For example the one used to execute driftctl itself in CodeBuild:

resource "aws_iam_role" "driftctl_runner" {
  name        = "DriftCtlRunner"
  description = "Detect infrastructure drift by reading state of account resources"

  assume_role_policy = jsonencode(
    {
      Version = "2012-10-17"
      Statement = [
        {
          Action = "sts:AssumeRole"
          Effect = "Allow"
          Principal = {
            AWS = [
              "arn:aws:iam::${local.account_id}:role/CodeBuild",
            ]
          }
        }
      ]
    }
  )

  inline_policy {
    name = "ReadResources"
    policy = jsonencode(
      {
        Version = "2012-10-17",
        Statement = [
          {
            Effect = "Allow"
            Action = [
              "apigateway:GET",
              "application-autoscaling:DescribeScalableTargets",
              "application-autoscaling:DescribeScalingPolicies",
              "application-autoscaling:DescribeScheduledActions",
              "autoscaling:DescribeLaunchConfigurations",
              "cloudformation:DescribeStacks",
              "cloudformation:GetTemplate",
              "cloudfront:GetDistribution",
              "cloudfront:ListDistributions",
              "cloudfront:ListTagsForResource",
              "dynamodb:DescribeContinuousBackups",
              "dynamodb:DescribeGlobalTable",
              "dynamodb:DescribeTable",
              "dynamodb:DescribeTableReplicaAutoScaling",
              "dynamodb:DescribeTimeToLive",
              "dynamodb:ListTables",
              "dynamodb:ListTagsOfResource",
              "ec2:DescribeAccountAttributes",
              "ec2:DescribeAddresses",
              "ec2:DescribeImages",
              "ec2:DescribeInstanceAttribute",
              "ec2:DescribeInstanceCreditSpecifications",
              "ec2:DescribeInstances",
              "ec2:DescribeInternetGateways",
              "ec2:DescribeKeyPairs",
              "ec2:DescribeLaunchTemplates",
              "ec2:DescribeNatGateways",
              "ec2:DescribeNetworkAcls",
              "ec2:DescribeRouteTables",
              "ec2:DescribeSecurityGroups",
              "ec2:DescribeSnapshots",
              "ec2:DescribeSubnets",
              "ec2:DescribeTags",
              "ec2:DescribeVolumes",
              "ec2:DescribeVpcAttribute",
              "ec2:DescribeVpcClassicLink",
              "ec2:DescribeVpcClassicLinkDnsSupport",
              "ec2:DescribeVpcs",
              "ec2:GetEbsEncryptionByDefault",
              "ecr:DescribeRepositories",
              "ecr:GetRepositoryPolicy",
              "ecr:ListTagsForResource",
              "elasticache:DescribeCacheClusters",
              "elasticloadbalancing:DescribeListeners",
              "elasticloadbalancing:DescribeLoadBalancers",
              "iam:GetPolicy",
              "iam:GetPolicyVersion",
              "iam:GetRole",
              "iam:GetRolePolicy",
              "iam:GetUser",
              "iam:GetUserPolicy",
              "iam:ListAccessKeys",
              "iam:ListAttachedGroupPolicies",
              "iam:ListAttachedRolePolicies",
              "iam:ListAttachedUserPolicies",
              "iam:ListGroupPolicies",
              "iam:ListGroups",
              "iam:ListPolicies",
              "iam:ListRolePolicies",
              "iam:ListRoles",
              "iam:ListUserPolicies",
              "iam:ListUsers",
              "kms:DescribeKey",
              "kms:GetKeyPolicy",
              "kms:GetKeyRotationStatus",
              "kms:ListAliases",
              "kms:ListKeys",
              "kms:ListResourceTags",
              "lambda:GetEventSourceMapping",
              "lambda:GetFunction",
              "lambda:GetFunctionCodeSigningConfig",
              "lambda:ListEventSourceMappings",
              "lambda:ListFunctions",
              "lambda:ListVersionsByFunction",
              "rds:DescribeDBClusters",
              "rds:DescribeDBInstances",
              "rds:DescribeDBSubnetGroups",
              "rds:DescribeGlobalClusters",
              "rds:ListTagsForResource",
              "route53:GetHealthCheck",
              "route53:GetHostedZone",
              "route53:ListHealthChecks",
              "route53:ListHostedZones",
              "route53:ListResourceRecordSets",
              "route53:ListTagsForResource",
              "s3:GetAccelerateConfiguration",
              "s3:GetAnalyticsConfiguration",
              "s3:GetBucketAcl",
              "s3:GetBucketCORS",
              "s3:GetBucketLocation",
              "s3:GetBucketLogging",
              "s3:GetBucketNotification",
              "s3:GetBucketObjectLockConfiguration",
              "s3:GetBucketPolicy",
              "s3:GetBucketPublicAccessBlock",
              "s3:GetBucketRequestPayment",
              "s3:GetBucketTagging",
              "s3:GetBucketVersioning",
              "s3:GetBucketWebsite",
              "s3:GetEncryptionConfiguration",
              "s3:GetInventoryConfiguration",
              "s3:GetLifecycleConfiguration",
              "s3:GetMetricsConfiguration",
              "s3:GetReplicationConfiguration",
              "s3:ListAllMyBuckets",
              "s3:ListBucket",
              "sns:GetSubscriptionAttributes",
              "sns:GetTopicAttributes",
              "sns:ListSubscriptions",
              "sns:ListSubscriptionsByTopic",
              "sns:ListTagsForResource",
              "sns:ListTopics",
              "sqs:GetQueueAttributes",
              "sqs:ListQueueTags",
              "sqs:ListQueues",
            ]
            Resource = "*"
          },
        ]
      }
    )
  }

  inline_policy {
    name = "ReadTerraformState"
    policy = jsonencode(
      {
        Version = "2012-10-17",
        Statement = [
          {
            Effect   = "Allow"
            Action   = "s3:GetObject"
            Resource = "${data.aws_s3_bucket.terraform_state.arn}/*"
          },
        ]
      }
    )
  }

  managed_policy_arns = []
}

Run driftctl and get an output similar to this one:

$ driftctl scan --quiet --tf-provider-version 4.11.0 --from 'tfstate+s3://<terraform_state_s3_bucket_name>/*.tfstate'
Found resources not covered by IaC:
  aws_iam_role_policy:
    - DriftCtlRunner:ReadResources
    - DriftCtlRunner:ReadTerraformState
Found 52 resource(s)
 - 96% coverage
 - 50 resource(s) managed by Terraform
 - 2 resource(s) not managed by Terraform
 - 0 resource(s) found in a Terraform state but missing on the cloud provider

Possible Solution

Additional context

In the terraform state file I can see that the inline policies are present, so they shouldn't be considred as infrastructure drift:

...
            "id": "DriftCtlRunner",
            "inline_policy": [
              {
                "name": "ReadResources",
                "policy": "{\"Statement\":...
              },
              {
                "name": "ReadTerraformState",
                "policy": "{\"Statement\":...
              }
            ],
...
moadibfr commented 2 years ago

Hi @jcollado thanks for this. I'll try to reproduce with the terraform you provided and fix that. We probably do not support these of inline declaration for role policy but I need to make sure of that and check if there is an easy fix.