Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to specify source directory for Lambda@Edge submodule #260

Merged
merged 22 commits into from
Mar 12, 2023

Conversation

zdmytriv
Copy link
Contributor

@zdmytriv zdmytriv commented Mar 3, 2023

what

  • Ability to specify source directory for Lambda@Edge submodule

why

  • Currently, we can pass the list of files that will be archived and uploaded as Lambda sources. This is not an option if more advanced logic is used and a lot of files should be used.

Example

For example, we have the following file structure for lambda@edge submodule:

lambda_edge_example/
    lib/
        node_modules/
        index.js
        package.json
        package-lock.json
    context.tf
    main.tf
    outputs.tf
    variables.tf

And we want the whole directory lib to be packaged.

With this enhancement path to lib might be specified like this

module "lambda_edge" {
  source  = "cloudposse/cloudfront-s3-cdn/aws//modules/lambda@edge"
  version = "x.xx.x"

  functions = {
    viewer_request = {
      source_dir   = "${path.module}/lib/"
      runtime      = "nodejs12.x"
      handler      = "index.handler"
      event_type   = "viewer-request"
      include_body = false
    }
  }

  // ...
}

Related

Closes #205

@zdmytriv zdmytriv added the minor New features that do not break anything label Mar 3, 2023
@zdmytriv zdmytriv requested review from a team as code owners March 3, 2023 14:35
@zdmytriv zdmytriv requested review from jamengual and joe-niland and removed request for a team March 3, 2023 14:35
@zdmytriv zdmytriv force-pushed the source_dir-support branch from 31dd959 to bf69589 Compare March 9, 2023 16:37
@zdmytriv
Copy link
Contributor Author

/test all

@zdmytriv
Copy link
Contributor Author

/test all

@zdmytriv
Copy link
Contributor Author

/test all

Copy link

@bridgecrew bridgecrew bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bridgecrew has found errors in this PR ⬇️

@@ -418,7 +418,7 @@ resource "aws_cloudfront_distribution" "default" {
origin_path = var.origin_path

dynamic "s3_origin_config" {
for_each = ! var.website_enabled ? [1] : []
for_each = !var.website_enabled ? [1] : []
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MEDIUM  Ensure AWS CloudFront attached WAFv2 WebACL is configured with AMR for Log4j Vulnerability
    Resource: aws_cloudfront_distribution.default | Bridgecrew ID: BC_AWS_GENERAL_186 | Checkov ID: CKV2_AWS_47

How to Fix

resource "aws_cloudfront_distribution" "pass" {
  origin {
    domain_name              = aws_s3_bucket.b.bucket_regional_domain_name
    origin_access_control_id = aws_cloudfront_origin_access_control.default.id
    origin_id                = local.s3_origin_id
  }

  enabled             = true
  is_ipv6_enabled     = true
  comment             = "Some comment"
  default_root_object = "index.html"

  aliases = ["mysite.example.com", "yoursite.example.com"]

  default_cache_behavior {
    allowed_methods  = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
    cached_methods   = ["GET", "HEAD"]
    target_origin_id = local.s3_origin_id

    forwarded_values {
      query_string = false

      cookies {
        forward = "none"
      }
    }

    viewer_protocol_policy = "allow-all"
    min_ttl                = 0
    default_ttl            = 3600
    max_ttl                = 86400
  }

  # Cache behavior with precedence 0
  ordered_cache_behavior {
    path_pattern     = "/content/immutable/*"
    allowed_methods  = ["GET", "HEAD", "OPTIONS"]
    cached_methods   = ["GET", "HEAD", "OPTIONS"]
    target_origin_id = local.s3_origin_id

    forwarded_values {
      query_string = false
      headers      = ["Origin"]

      cookies {
        forward = "none"
      }
    }

    min_ttl                = 0
    default_ttl            = 86400
    max_ttl                = 31536000
    compress               = true
    viewer_protocol_policy = "redirect-to-https"
  }

  price_class = "PriceClass_200"

  restrictions {
    geo_restriction {
      restriction_type = "whitelist"
      locations        = ["US", "CA", "GB", "DE"]
    }
  }

  tags = {
    Environment = "production"
  }

  viewer_certificate {
    cloudfront_default_certificate = true
  }
  web_acl_id = aws_wafv2_web_acl.pass_acl.arn
}

resource "aws_wafv2_web_acl" "pass_acl" {
  name        = "managed-rule-example"
  description = "Example of a managed rule."
  scope       = "REGIONAL"

  default_action {
    allow {}
  }

  rule {
    name     = "rule-1"
    priority = 1

    override_action {
      count {}
    }

    statement {
      managed_rule_group_statement {
        name        = "AWSManagedRulesAnonymousIpList"
        vendor_name = "AWS"

        excluded_rule {
          name = "SizeRestrictions_QUERYSTRING"
        }

        scope_down_statement {
          geo_match_statement {
            country_codes = ["US", "NL"]
          }
        }
      }
    }

    visibility_config {
      cloudwatch_metrics_enabled = false
      metric_name                = "friendly-rule-metric-name"
      sampled_requests_enabled   = false
    }
  }

  rule {
    name     = "rule-2"
    priority = 2

    override_action {
      count {}
    }

    statement {
      managed_rule_group_statement {
        name        = "AWSManagedRulesKnownBadInputsRuleSet"
        vendor_name = "AWS"

        excluded_rule {
          name = "SizeRestrictions_QUERYSTRING"
        }

        scope_down_statement {
          geo_match_statement {
            country_codes = ["US", "NL"]
          }
        }
      }
    }

    visibility_config {
      cloudwatch_metrics_enabled = false
      metric_name                = "friendly-rule-metric-name"
      sampled_requests_enabled   = false
    }
  }


  tags = {
    Tag1 = "Value1"
    Tag2 = "Value2"
  }

  visibility_config {
    cloudwatch_metrics_enabled = false
    metric_name                = "friendly-metric-name"
    sampled_requests_enabled   = false
  }
}

Description

This policy identifies AWS CloudFront attached with WAFv2 WebACL which is not configured with AWS Managed Rules (AMR) for Log4j Vulnerability. As per the guidelines given by AWS, CloudFront attached with WAFv2 WebACL should be configured with AWS Managed Rules (AMR) AWSManagedRulesKnownBadInputsRuleSet and AWSManagedRulesAnonymousIpList to protect from Log4j Vulnerability (CVE-2021-44228).\n\nFor more information please refer below URL,\nhttps://aws.amazon.com/security/security-bulletins/AWS-2021-006/

@zdmytriv
Copy link
Contributor Author

/test all

@@ -418,7 +418,7 @@ resource "aws_cloudfront_distribution" "default" {
origin_path = var.origin_path

dynamic "s3_origin_config" {
for_each = ! var.website_enabled ? [1] : []
for_each = !var.website_enabled ? [1] : []
Copy link

@bridgecrew bridgecrew bot Mar 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MEDIUM  Ensure AWS CloudFront attached WAFv2 WebACL is configured with AMR for Log4j Vulnerability
    Resource: module.cloudfront_s3_cdn.aws_cloudfront_distribution.default | Bridgecrew ID: BC_AWS_GENERAL_186 | Checkov ID: CKV2_AWS_47

How to Fix

resource "aws_cloudfront_distribution" "pass" {
  origin {
    domain_name              = aws_s3_bucket.b.bucket_regional_domain_name
    origin_access_control_id = aws_cloudfront_origin_access_control.default.id
    origin_id                = local.s3_origin_id
  }

  enabled             = true
  is_ipv6_enabled     = true
  comment             = "Some comment"
  default_root_object = "index.html"

  aliases = ["mysite.example.com", "yoursite.example.com"]

  default_cache_behavior {
    allowed_methods  = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
    cached_methods   = ["GET", "HEAD"]
    target_origin_id = local.s3_origin_id

    forwarded_values {
      query_string = false

      cookies {
        forward = "none"
      }
    }

    viewer_protocol_policy = "allow-all"
    min_ttl                = 0
    default_ttl            = 3600
    max_ttl                = 86400
  }

  # Cache behavior with precedence 0
  ordered_cache_behavior {
    path_pattern     = "/content/immutable/*"
    allowed_methods  = ["GET", "HEAD", "OPTIONS"]
    cached_methods   = ["GET", "HEAD", "OPTIONS"]
    target_origin_id = local.s3_origin_id

    forwarded_values {
      query_string = false
      headers      = ["Origin"]

      cookies {
        forward = "none"
      }
    }

    min_ttl                = 0
    default_ttl            = 86400
    max_ttl                = 31536000
    compress               = true
    viewer_protocol_policy = "redirect-to-https"
  }

  price_class = "PriceClass_200"

  restrictions {
    geo_restriction {
      restriction_type = "whitelist"
      locations        = ["US", "CA", "GB", "DE"]
    }
  }

  tags = {
    Environment = "production"
  }

  viewer_certificate {
    cloudfront_default_certificate = true
  }
  web_acl_id = aws_wafv2_web_acl.pass_acl.arn
}

resource "aws_wafv2_web_acl" "pass_acl" {
  name        = "managed-rule-example"
  description = "Example of a managed rule."
  scope       = "REGIONAL"

  default_action {
    allow {}
  }

  rule {
    name     = "rule-1"
    priority = 1

    override_action {
      count {}
    }

    statement {
      managed_rule_group_statement {
        name        = "AWSManagedRulesAnonymousIpList"
        vendor_name = "AWS"

        excluded_rule {
          name = "SizeRestrictions_QUERYSTRING"
        }

        scope_down_statement {
          geo_match_statement {
            country_codes = ["US", "NL"]
          }
        }
      }
    }

    visibility_config {
      cloudwatch_metrics_enabled = false
      metric_name                = "friendly-rule-metric-name"
      sampled_requests_enabled   = false
    }
  }

  rule {
    name     = "rule-2"
    priority = 2

    override_action {
      count {}
    }

    statement {
      managed_rule_group_statement {
        name        = "AWSManagedRulesKnownBadInputsRuleSet"
        vendor_name = "AWS"

        excluded_rule {
          name = "SizeRestrictions_QUERYSTRING"
        }

        scope_down_statement {
          geo_match_statement {
            country_codes = ["US", "NL"]
          }
        }
      }
    }

    visibility_config {
      cloudwatch_metrics_enabled = false
      metric_name                = "friendly-rule-metric-name"
      sampled_requests_enabled   = false
    }
  }


  tags = {
    Tag1 = "Value1"
    Tag2 = "Value2"
  }

  visibility_config {
    cloudwatch_metrics_enabled = false
    metric_name                = "friendly-metric-name"
    sampled_requests_enabled   = false
  }
}

Description

This policy identifies AWS CloudFront attached with WAFv2 WebACL which is not configured with AWS Managed Rules (AMR) for Log4j Vulnerability. As per the guidelines given by AWS, CloudFront attached with WAFv2 WebACL should be configured with AWS Managed Rules (AMR) AWSManagedRulesKnownBadInputsRuleSet and AWSManagedRulesAnonymousIpList to protect from Log4j Vulnerability (CVE-2021-44228).\n\nFor more information please refer below URL,\nhttps://aws.amazon.com/security/security-bulletins/AWS-2021-006/
     🎉   Fixed by commit 814dc66 - update

Zinovii Dmytriv and others added 2 commits March 10, 2023 16:58
@zdmytriv
Copy link
Contributor Author

/test all

@zdmytriv
Copy link
Contributor Author

/test all

@zdmytriv
Copy link
Contributor Author

/test all

@@ -2,14 +2,15 @@ data "archive_file" "lambda_zip" {
for_each = local.functions

dynamic "source" {
for_each = each.value.source
for_each = coalesce(each.value.source, [])
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

source might be empty list now because we source_dir as well

filename = string
content = string
}))
})))
source_dir = optional(string)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

both source and source_dir are optional

@@ -1,5 +1,5 @@
terraform {
required_version = ">= 0.13.0"
required_version = ">= 1.3"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bumped version in order to support optional() function

@@ -1,5 +1,5 @@
terraform {
required_version = ">= 0.13.0"
required_version = ">= 1.3"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bumped version in order to support optional() function

}
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exporting role arn so policy attachment can be added to lambda.

@@ -52,7 +52,7 @@ locals {

override_origin_bucket_policy = local.enabled && var.override_origin_bucket_policy

lookup_cf_log_bucket = local.cloudfront_access_logging_enabled && ! local.cloudfront_access_log_create_bucket
lookup_cf_log_bucket = local.cloudfront_access_logging_enabled && !local.cloudfront_access_log_create_bucket
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bridgecrew insisted

@@ -4,7 +4,7 @@ locals {
# Encapsulate logic here so that it is not lost/scattered among the configuration
website_enabled = local.enabled && var.website_enabled
website_password_enabled = local.website_enabled && var.s3_website_password_enabled
s3_origin_enabled = local.enabled && ! var.website_enabled
s3_origin_enabled = local.enabled && !var.website_enabled
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bridgecrew insisted

@@ -1,5 +1,5 @@
terraform {
required_version = ">= 0.13.0"
required_version = ">= 1.3"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bumped version in order to support optional() function

headers['x-custom-header'] = [{ key: 'X-Custom-Header', value: 'My custom value' }];

callback(null, response);
};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sample index.js for the example/complete test

handler = "index.handler"
event_type = "viewer-response"
include_body = false
},
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more type of lambda@edge cloudfront function. Needed to test source_dir

@zdmytriv zdmytriv merged commit 5ea3df7 into master Mar 12, 2023
@zdmytriv zdmytriv deleted the source_dir-support branch March 12, 2023 13:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
minor New features that do not break anything
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Lambda@Edge with pre-provided zips
4 participants