DEV Community

Michael Wahl for AWS Community Builders

Posted on

Finding and Fixing Cloud Misconfigurations with open source

The IaC scanner called Checkov, helps prevent misconfigured and insecure configurations prior to being released in the wild, leveraging a policy as code for everyone approach.

Challenges, what you may be looking for

  • Default values, settings, configurations

  • Logging which has been removed or disabled

  • Unencrypted data, which may include RDS databases, S3 buckets, or EC2 volumes to name just a few.

  • The use of insecure protocols such as http, or ftp for example.

  • Vulnerable native, or other third-party services

  • Vulnerable containers, or other microservices.

The Installation

pip3 install checkov
Enter fullscreen mode Exit fullscreen mode
brew install checkov
Enter fullscreen mode Exit fullscreen mode

Usage

checkov -d .
Enter fullscreen mode Exit fullscreen mode

VSCode Plugin

For those who use Visual Studio Code, there is a nice plugin available. If you integrate VSCode with bridgecrew, you will have an entire fix library available to you within VSCode. This is extremely powerful, as you review the failed checks and findings, the fix library will help you to see the various items which needed to be addressed, with quick fixes, displayed and presented in a more concise, easily consumable view.

Demo-Example Terraform scan Results

Passed

Image description

Failed

Check: CKV_AWS_21: "Ensure all data stored in the S3 bucket have versioning enabled"
    FAILED for resource: aws_s3_bucket.bucket
    File: /terraform-aws-s3-bucket-master/main.tf:36-146
    Guide: https://docs.bridgecrew.io/docs/s3_16-enable-versioning

        36  | resource "aws_s3_bucket" "bucket" {
        37  |   count = var.module_enabled ? 1 : 0
        38  | 
        39  |   bucket              = var.bucket
        40  |   bucket_prefix       = var.bucket_prefix
        41  |   acl                 = var.acl
        42  |   tags                = local.bucket_tags
        43  |   force_destroy       = var.force_destroy
        44  |   acceleration_status = var.acceleration_status
        45  |   request_payer       = var.request_payer
        46  | 
        47  |   dynamic "cors_rule" {
        48  |     for_each = local.cors
        49  | 
        50  |     content {
        51  |       allowed_headers = lookup(cors_rule.value, "allowed_headers", null)
        52  |       allowed_methods = cors_rule.value.allowed_methods
        53  |       allowed_origins = cors_rule.value.allowed_origins
        54  |       expose_headers  = lookup(cors_rule.value, "expose_headers", null)
        55  |       max_age_seconds = lookup(cors_rule.value, "max_age_seconds", null)
        56  |     }
        57  |   }
        58  | 
        59  |   dynamic "versioning" {
        60  |     for_each = local.versioning
        61  | 
        62  |     content {
        63  |       enabled    = lookup(versioning.value, "enabled", null)
        64  |       mfa_delete = lookup(versioning.value, "mfa_delete", false)
        65  |     }
        66  |   }
        67  | 
        68  |   dynamic "logging" {
        69  |     for_each = local.logging
        70  | 
        71  |     content {
        72  |       target_bucket = logging.value.target_bucket
        73  |       target_prefix = lookup(logging.value, "target_prefix", null)
        74  |     }
        75  |   }
        76  | 
        77  |   dynamic "server_side_encryption_configuration" {
        78  |     for_each = local.encryption
        79  |     iterator = sse
        80  | 
        81  |     content {
        82  |       rule {
        83  |         apply_server_side_encryption_by_default {
        84  |           kms_master_key_id = lookup(sse.value, "kms_master_key_id", null)
        85  |           sse_algorithm = lookup(sse.value, "sse_algorithm",
        86  |             lookup(sse.value, "kms_master_key_id", null) == null ? "AES256" : "aws:kms"
        87  |           )
        88  |         }
        89  |       }
        90  |     }
        91  |   }
        92  | 
        93  |   dynamic "lifecycle_rule" {
        94  |     for_each = var.lifecycle_rules
        95  |     iterator = rule
        96  | 
        97  |     content {
        98  |       id                                     = lookup(rule.value, "id", null)
        99  |       prefix                                 = lookup(rule.value, "prefix", null)
        100 |       tags                                   = lookup(rule.value, "tags", null)
        101 |       abort_incomplete_multipart_upload_days = lookup(rule.value, "abort_incomplete_multipart_upload_days", null)
        102 |       enabled                                = rule.value.enabled
        103 | 
        104 |       dynamic "expiration" {
        105 |         for_each = length(keys(lookup(rule.value, "expiration", {}))) == 0 ? [] : [rule.value.expiration]
        106 | 
        107 |         content {
        108 |           date                         = lookup(expiration.value, "date", null)
        109 |           days                         = lookup(expiration.value, "days", null)
        110 |           expired_object_delete_marker = lookup(expiration.value, "expired_object_delete_marker", null)
        111 |         }
        112 |       }
        113 | 
        114 |       dynamic "transition" {
        115 |         for_each = lookup(rule.value, "transition", [])
        116 | 
        117 |         content {
        118 |           date          = lookup(transition.value, "date", null)
        119 |           days          = lookup(transition.value, "days", null)
        120 |           storage_class = transition.value.storage_class
        121 |         }
        122 |       }
        123 | 
        124 |       dynamic "noncurrent_version_expiration" {
        125 |         for_each = length(keys(lookup(rule.value, "noncurrent_version_expiration", {}))) == 0 ? [] : [rule.value.noncurrent_version_expiration]
        126 |         iterator = expiration
        127 | 
        128 |         content {
        129 |           days = lookup(expiration.value, "days", null)
        130 |         }
        131 |       }
        132 | 
        133 |       dynamic "noncurrent_version_transition" {
        134 |         for_each = lookup(rule.value, "noncurrent_version_transition", [])
        135 |         iterator = transition
        136 | 
        137 |         content {
        138 |           days          = lookup(transition.value, "days", null)
        139 |           storage_class = transition.value.storage_class
        140 |         }
        141 |       }
        142 |     }
        143 |   }
        144 | 
        145 |   depends_on = [var.module_depends_on]
        146 | }

Enter fullscreen mode Exit fullscreen mode

Support for the major cloud providers and frameworks including:

-AWS
-CloudFormation
-AWS CDK
-Terraform
-Serverless

Integration, CI/CD workflow support with many including:

  • Jenkins
  • Github
  • Bitbucket

Policy-as-code Features:

  • Attribute-based policies: scan cloud resources, looking for misconfigurations, uses simple Python framework.

  • Graph-based policies: Evaluates cloud resources against checkov's policies.

  • Extensible policy management: Allowing for the use of your own custom policies for example.

Top comments (0)