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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Security Headers not returning: Cloudfront Trigger is not being added to Lambda Function #2

Open
marcellodesales opened this issue Aug 28, 2021 · 7 comments
Assignees
Labels
question Further information is requested

Comments

@marcellodesales
Copy link

馃悰 Describe the bug

  • The Cloudfront Trigger should be added for the lambda...
    • It's missing, nonetheless...
  • When calling endpoints, the security headers don't show up

Screen Shot 2021-08-28 at 1 36 36 AM

馃┖ To Reproduce

  1. Create a file with the module
variable "aws_region" { default = "us-east-1" }

terraform {
  required_version = ">= 0.12"

  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "3.52.0"
    }
  }
}

provider "aws" {
  region = var.aws_region
}

module "cloudfront-security-headers" {
  source  = "Lupus-Metallum/cloudfront-security-headers/aws"
  version = "1.0.2"
  name = "xxxx-web-apps-web-security"
}

Expected behavior

  • I was expecting

馃帹 Screenshots

  • The function was created, but the trigger was not set to CloudFront

Desktop (please complete the following information):

  • OS: iOS
  • Version: BigSur 11.5.2
  • TF Version: 1.0.5

馃捇 Possible Solution

resource "aws_cloudfront_distribution" "cloudfront-distribution" {
    # This is how we associate the Lambda@Edge function for a cache behavior
    # and we repeat this for the other "ordered_cache_behavior" configurations
    lambda_function_association {
      event_type = "origin-response"

      lambda_arn = "${aws_lambda_function.edge_security_headers_lambda.qualified_arn}"
    }
  }
}

Screen Shot 2021-08-28 at 1 51 19 AM

  • It should result in:

Screen Shot 2021-08-28 at 1 54 48 AM

馃攭 Full Logs

$ terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # module.cloudfront-security-headers.aws_iam_policy.execution_role will be created
  + resource "aws_iam_policy" "execution_role" {
      + arn       = (known after apply)
      + id        = (known after apply)
      + name      = "xxxxx-web-apps-web-security-policy"
      + path      = "/"
      + policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action   = [
                          + "logs:PutLogEvents",
                          + "logs:CreateLogStream",
                          + "logs:CreateLogGroup",
                        ]
                      + Effect   = "Allow"
                      + Resource = "arn:aws:logs:*::log-group:/aws/lambda/*:*:*"
                      + Sid      = "AllowCloudWatchLogs"
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + policy_id = (known after apply)
      + tags_all  = (known after apply)
    }

  # module.cloudfront-security-headers.aws_iam_role.execution_role will be created
  + resource "aws_iam_role" "execution_role" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = [
                              + "lambda.amazonaws.com",
                              + "edgelambda.amazonaws.com",
                            ]
                        }
                      + Sid       = ""
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "xxxxxx-web-apps-web-security-execution-role"
      + path                  = "/"
      + tags_all              = (known after apply)
      + unique_id             = (known after apply)

      + inline_policy {
          + name   = (known after apply)
          + policy = (known after apply)
        }
    }

  # module.cloudfront-security-headers.aws_iam_role_policy_attachment.execution_role will be created
  + resource "aws_iam_role_policy_attachment" "execution_role" {
      + id         = (known after apply)
      + policy_arn = (known after apply)
      + role       = "xxxxxxx-web-apps-web-security-execution-role"
    }

  # module.cloudfront-security-headers.aws_lambda_function.this will be created
  + resource "aws_lambda_function" "this" {
      + arn                            = (known after apply)
      + description                    = "Adds security headers for Cloudfront"
      + filename                       = ".terraform/modules/cloudfront-security-headers/deploy.zip"
      + function_name                  = "xxxxx-web-apps-web-security"
      + handler                        = "index.handler"
      + id                             = (known after apply)
      + invoke_arn                     = (known after apply)
      + last_modified                  = (known after apply)
      + memory_size                    = 128
      + package_type                   = "Zip"
      + publish                        = true
      + qualified_arn                  = (known after apply)
      + reserved_concurrent_executions = -1
      + role                           = (known after apply)
      + runtime                        = "nodejs12.x"
      + signing_job_arn                = (known after apply)
      + signing_profile_version_arn    = (known after apply)
      + source_code_hash               = "39fHlKdi4PoGgyuRgsaPJahkp3nxApzVUPAxERN2FiU="
      + source_code_size               = (known after apply)
      + tags_all                       = (known after apply)
      + timeout                        = 1
      + version                        = (known after apply)

      + tracing_config {
          + mode = (known after apply)
        }
    }

Plan: 4 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

module.cloudfront-security-headers.aws_iam_policy.execution_role: Creating...
module.cloudfront-security-headers.aws_iam_role.execution_role: Creating...
module.cloudfront-security-headers.aws_iam_policy.execution_role: Creation complete after 1s [id=arn:aws:iam::806101772216:policy/xxxxxxx-web-apps-web-security-policy]
module.cloudfront-security-headers.aws_iam_role.execution_role: Creation complete after 1s [id=xxxxxx-web-apps-web-security-execution-role]
module.cloudfront-security-headers.aws_iam_role_policy_attachment.execution_role: Creating...
module.cloudfront-security-headers.aws_lambda_function.this: Creating...
module.cloudfront-security-headers.aws_iam_role_policy_attachment.execution_role: Creation complete after 1s [id=xxxxxxx-web-apps-web-security-execution-role-20210828081654748000000001]
module.cloudfront-security-headers.aws_lambda_function.this: Still creating... [10s elapsed]
module.cloudfront-security-headers.aws_lambda_function.this: Creation complete after 16s [id=xxxxxxxx-web-apps-web-security]

Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
@marcellodesales marcellodesales added the bug Something isn't working label Aug 28, 2021
@skyfox675
Copy link
Member

skyfox675 commented Sep 17, 2021

@marcellodesales So this is interesting that your seeing this as well. Initially when writing the first version of this module, I noticed the same thing. That the Lambda was missing the Cloudfront trigger in the Lambda UI. However, as long as the lambda function is configured as an association on the Cloudfront Distribution, the headers are there:

Screen Shot 2021-09-17 at 08 42 02

I did attempt adding the trigger last night, but this only resulted in 503's being thrown to Cloudfront.

@marcellodesales
Copy link
Author

@skyfox675 Any workaround for that then? I want to incorporate this module and this was my last resort :(

@skyfox675
Copy link
Member

skyfox675 commented Oct 7, 2021

This is the way I configure Cloudfront triggered lambdas you shouldn't need to make any changes in the lambda console:

module "cloudfront_security_headers" {
  source  = "Lupus-Metallum/cloudfront-security-headers/aws"
  version = "2.0.0"

  name = "AddSecurityHeaders"
  access_control_allow_methods = "POST, GET, OPTIONS"
  access_control_allow_origin  = "https://example.com"
  referrer_policy              = "same-origin"
  strict_transport_security    = "max-age=63072000; includeSubdomains; preload"
  x_content_type_options       = "nosniff"
  x_frame_options              = "DENY"
  x_xss_protection             = "1; mode=block"
  feature_policy               = ""
}

resource "aws_cloudfront_distribution" "s3_site" {

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

  default_cache_behavior {
    allowed_methods  = ["GET", "HEAD"]
    cached_methods   = ["GET", "HEAD"]

    viewer_protocol_policy = "redirect-to-https"
    cache_policy_id        = "658327ea-f89d-4fab-a63d-7e88639e58f6"
    min_ttl                = 0
    default_ttl            = 0
    max_ttl                = 0
    compress               = true
    lambda_function_association {
      event_type   = "viewer-response"
      include_body = false
      lambda_arn   = module.cloudfront_security_headers.lambda_arn
    }
  }
... additional cloudfront options
}

@marcellodesales
Copy link
Author

marcellodesales commented Oct 7, 2021

@skyfox675 Is there a way to specify custom headers too?

@skyfox675
Copy link
Member

skyfox675 commented Oct 17, 2021

@skyfox675 Is there a way to specify custom headers too?

Not at this time, curious were the headers you're looking to add more security like headers such as CORS, XSS... or custom for your specific implementation?

Happy to add more options on the security front.

As for specific headers for your implementation, you can copy the code in src/index.js.tpl and modify for your needs and deploy a published Lambda with a Cloudfront viewer response to add your custom headers as well.

@skyfox675 skyfox675 added question Further information is requested and removed bug Something isn't working labels Oct 17, 2021
@marcellodesales
Copy link
Author

@skyfox675 In order to validate a deployment, I inject HTTP response headers for Metrics and from the Build system. That way, my automated validators can just do an HTTP HEAD request to the object and retrieve these other HTTP Response headers to be validated...

Requirement & Design

I was thinking in something like the following:

 variable "luppus_metallum_additional_headers" {
    description = "Additional headers to be injected by the lambda cloudfront"
    type        = map
    default = [
      {
        key = "X-App-Build-Version"
        value = "1.2.0-adf349e"
      },
      {
        key = "X-App-env"
        attribute = "stg"
      },
      {
        id = "X-App-segment"
        attribute = "ppd"
      },
      {
        id = "X-App-type"
        attribute = "blc"
      }
  ]

@marcellodesales
Copy link
Author

@skyfox675 Is there a way to specify custom headers too?

Not at this time, curious were the headers you're looking to add more security like headers such as CORS, XSS... or custom for your specific implementation?

Happy to add more options on the security front.

As for specific headers for your implementation, you can copy the code in src/index.js.tpl and modify for your needs and deploy a published Lambda with a Cloudfront viewer response to add your custom headers as well.

I hesitate to copy code from libraries as they tend to evolve and impose changes on my seide as well... I just wanted something more concise....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Development

No branches or pull requests

2 participants