AWS Load Balancer Forward action stickiness - amazon-web-services

So, I am using a module based on this AWS LB Module
Now, I'm trying to add stickiness option on the default_action forward. Not sure why it's not working. I've tried all sorts of changes. My last change is this:
dynamic "default_action" {
for_each = contains(["authenticate-oidc", "authenticate-cognito"], lookup(var.https_listeners[count.index], "action_type", {})) ? [var.https_listeners[count.index]] : []
content {
type = "forward"
target_group_arn = aws_lb_target_group.main[lookup(default_action.value, "target_group_index", count.index)].id
stickiness {
enabled = lookup(default_action.value, "stickiness", false)
duration = lookup(default_action.value, "duration", null)
}
}
}
I'm trying to pass this:
https_listeners = [
{
port = 443
protocol = "HTTPS"
certificate_arn = var.certificate_arn
stickiness = true
duration = 3600
},
]
I'm now thinking of trying to just use the default stickiness as enabled, and duration 3600.
Any thoughts on this?
EDIT 1: I've tried changing the module block as #bryan mentioned I am passing an empty map. Just for test purposes, I hardcoded the values for stickiness like below:
dynamic "default_action" {
for_each = contains(["authenticate-oidc", "authenticate-cognito"], lookup(var.https_listeners[count.index], "action_type", {})) ? [var.https_listeners[count.index]] : []
content {
type = "forward"
target_group_arn = aws_lb_target_group.main[lookup(default_action.value, "target_group_index", count.index)].id
stickiness {
enabled = true
duration = 3600
}
}
}
Expectation is for the listener default action to set the group stickiness.. but somehow, it doesn't. I've also raised this issue on the AWS LB Module repo

Related

What are all the things that I need to connect an existing known-good API gateway endpoint to a Route53 subdomain with Terraform?

Here's the code I have so far, hopefully I got everything relevant. The API gateway is deployed and working and has been for a while now. Our app is currently pointing at the xxxyyyzz12.execute-api.us-west-2.amazonaws.com endpoint and working fine. But I need to route it to the subdomain ui-backend.app-name-here-dev.company.services.
data "aws_acm_certificate" "app_name_dev_wildcard_cert" {
domain = "*.app-name-here-dev.company.services"
statuses = ["ISSUED"]
}
// pull in the existing zone (defined by devops) via a data block
data "aws_route53_zone" "myapp_zone" {
name = local.domain
}
resource "aws_route53_record" "ui_backend" {
name = aws_apigatewayv2_domain_name.ui_backend_api_gateway.domain_name
type = "A"
zone_id = data.aws_route53_zone.myapp_zone.zone_id
alias {
name = aws_apigatewayv2_domain_name.ui_backend_api_gateway.domain_name_configuration[0].target_domain_name
zone_id = aws_apigatewayv2_domain_name.ui_backend_api_gateway.domain_name_configuration[0].hosted_zone_id
evaluate_target_health = false
}
}
resource "aws_apigatewayv2_domain_name" "ui_backend_api_gateway" {
domain_name = "${local.subdomain}.${local.domain}"
domain_name_configuration {
certificate_arn = data.aws_acm_certificate.app_name_dev_wildcard_cert.arn
endpoint_type = "REGIONAL"
security_policy = "TLS_1_2"
}
}
locals {
// trimmed
domain = "app-name-here${var.envToZoneName[var.environment]}.company.services"
subdomain = var.deploymentNameModifier == "" ? "ui-backend" : "ui-backend-${var.deploymentNameModifier}"
}
But when I try to use the curl (the one that works for xxxyyyzz12.execute-api.us-west-2.amazonaws.com) I'm getting a 403. I added a x-apigw-api-id: 153utdsv9h header but it didn't help. I must be missing a resource.
Well, 16 hrs have gone by with no answers/comments. Here's the thing that was missing:
resource "aws_apigatewayv2_api_mapping" "ui_backend_to_subdomain" {
api_id = aws_apigatewayv2_api.ui_backend_gateway.id
domain_name = aws_apigatewayv2_domain_name.ui_backend_api_gateway.domain_name
stage = aws_apigatewayv2_stage.ui_backend.id
}

Terraform GCP groups: I am using FQDNs as in the DNS, but still get "The URL is malformed". What kind of URL is it looking for?

I'm using Terraform with GCP ... I have the groups variable that I have not been able to get to work. Here's the definitions:
resource "google_compute_instance_group" "vm_group" {
name = "vm-group"
zone = "us-central1-c"
project = "myproject-dev"
instances = [google_compute_instance.east_vm.id, google_compute_instance.west_vm.id]
named_port {
name = "http"
port = "8080"
}
named_port {
name = "https"
port = "8443"
}
lifecycle {
create_before_destroy = true
}
}
data "google_compute_image" "debian_image" {
family = "debian-9"
project = "debian-cloud"
}
resource "google_compute_instance" "west_vm" {
name = "west-vm"
project = "myproject-dev"
machine_type = "e2-micro"
zone = "us-central1-c"
boot_disk {
initialize_params {
image = data.google_compute_image.debian_image.self_link
}
}
network_interface {
network = "default"
}
}
resource "google_compute_instance" "east_vm" {
name = "east-vm"
project = "myproject-dev"
machine_type = "e2-micro"
zone = "us-central1-c"
boot_disk {
initialize_params {
image = data.google_compute_image.debian_image.self_link
}
}
network_interface {
network = "default"
}
}
And here are the variables:
http_forward = true
https_redirect = true
create_address = true
project = "myproject-dev"
backends = {
"yobaby" = {
description = "my app"
enable_cdn = false
security_policy = ""
custom_request_headers = null
custom_response_headers = null
iap_config = {
enable = false
oauth2_client_id = ""
oauth2_client_secret = ""
}
log_config = {
enable = false
sample_rate = 0
}
groups = [{group = "google_compute_instance_group.vm_group.id"}]
}
}
... this is my latest attempt to get a group value that works, but this one won't work for me either; I still get
Error 400: Invalid value for field 'resource.backends[0].group': 'google_compute_instance_group.vm_group.id'. The URL is malformed., invalid
I've tried this with DNS FQDNs and variations on the syntax above; still no go.
Thanks much for any advice whatsoever!
There are couple clues that can lead in this direction based from the error message reported by Terraform Error 400: Invalid value for field 'resource.backends[0].group': 'google_compute_instance_group.vm_group.id'. The URL is malformed., invalid:
Error code 400 means the request was actually sent to the server, who rejected it as malformed (HTTP error code 400 is for client-side errors); this implies that Terraform itself has no problem with the syntax, i.e., the configuration file is correct and actionable from TF's PoV
Value of field resource.backends[0].group is reported as being literally 'google_compute_instance_group.vm_group.id' which strongly suggests that a variable substitution did not take place.
The quotes around the code block makes it into a literal value instead of a variable reference. The solution is to change this:
groups = [{group = "google_compute_instance_group.vm_group.id"}]
To this:
groups = [{group = google_compute_instance_group.vm_group.id}]
I gave up on Terraform and used gcloud scripts to do what I needed to do, based on this posting.

Terraform aws_elastic_beanstalk_environment redirect HTTP traffic to HTTPS

I'm using terraform to provision an elasticbeanstalk environment. I want redirect all HTTP traffic to HTTPS. Here is my current configuration:
resource "aws_elastic_beanstalk_environment" "env" {
...
# Configure the default listener (port 80) on a classic load balancer.
setting {
namespace = "aws:elb:listener:80"
name = "InstancePort"
value = "80"
}
setting {
namespace = "aws:elb:listener:80"
name = "ListenerEnabled"
value = "true"
}
# Configure additional listeners on a classic load balancer.
setting {
namespace = "aws:elb:listener:443"
name = "ListenerProtocol"
value = "HTTPS"
}
setting {
namespace = "aws:elb:listener:443"
name = "InstancePort"
value = "80"
}
setting {
namespace = "aws:elb:listener:443"
name = "ListenerEnabled"
value = "true"
}
# Modify the default stickiness and global load balancer policies for a classic load balancer.
setting {
namespace = "aws:elb:policies"
name = "ConnectionSettingIdleTimeout"
value = "60"
}
setting {
namespace = "aws:elbv2:listener:443"
name = "SSLCertificateArns"
value = "${aws_acm_certificate.cert.arn}"
}
setting {
namespace = "aws:elb:listener:443"
name = "SSLCertificateId"
value = "${aws_acm_certificate.cert.arn}"
}
I've tried various solutions posted online, none will actually work though. Any idea what is wrong with my current configuration? Thanks in advance.
edit: entire config (stackoverflow would not allow posting it all for some reason) https://pastebin.com/aMHgSiXr

Allowing traffic to a certain path in AWS WAF

The way that AWS WAF works to be very unclear, at the moment, I'm trying to allow all traffic to a certain path.
Lets say everything to /admin should be allowed and not go through the xss or sql filters that I've added from the "common attacks" to my setup via their official guide: https://docs.aws.amazon.com/waf/latest/developerguide/tutorials-common-attacks.html
But the UI and docs makes it really unclear how to do this. Any help or resources would be very useful.
Is /admin part of the URL? If so, can you write a simple string-match rule on URL to whitelist it?
FYI, rules are triggered based on order you put in so put the whitelist rules need to be at top.
# waf using rate-based rule
resource "aws_wafv2_web_acl" "example" {
name = "example"
description = "Example of a regional rate based statement."
scope = "REGIONAL"
default_action {
allow {}
}
rule {
name = "LoginRateLimit"
priority = 0
action {
count {}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "Metric-Limit"
sampled_requests_enabled = true
}
statement {
rate_based_statement {
limit = 500
aggregate_key_type = "IP"
scope_down_statement {
byte_match_statement {
field_to_match {
uri_path {}
}
positional_constraint = "CONTAINS"
search_string = "login"
text_transformation {
priority = 0
type = "NONE"
}
}
}
}
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "any-name"
sampled_requests_enabled = true
}
}
You can filter and add different rules to different paths using String Match Conditions.
Configure it to filter on part of the URI (URL that identifies a resource).

is there any way I associate aws ELB/ALB with WAF ACL using terraform?

I created the following AWS WAF ACL and I want to associate it with my ALB using terraform. is there any way I can do it using terraform?
I want to block all requests except the ones that have secret key using amazon web service web application firewalls, aws waf. For that purpose, I created byte_set, aws rule and access control lists, ACL
resource "aws_alb" "app" {
............
}
#waf
resource "aws_waf_byte_match_set" "byte_set" {
name = "tf_waf_byte_match_set"
byte_match_tuples {
text_transformation = "NONE"
target_string = "${var.secret_key}"
positional_constraint = "EXACTLY"
field_to_match {
type = "HEADER"
data = "referer"
}
}
}
resource "aws_waf_rule" "wafrule" {
depends_on = ["aws_waf_byte_match_set.byte_set"]
name = "tfWAFRule"
metric_name = "tfWAFRule"
predicates {
data_id = "${aws_waf_byte_match_set.byte_set.id}"
negated = false
type = "ByteMatch"
}
}
resource "aws_waf_web_acl" "waf_acl" {
depends_on = ["aws_waf_byte_match_set.byte_set", "aws_waf_rule.wafrule"]
name = "tfWebACL"
metric_name = "tfWebACL"
default_action {
type = "BLOCK"
}
rules {
action {
type = "ALLOW"
}
priority = 1
rule_id = "${aws_waf_rule.wafrule.id}"
}
}
Sure, here is an example of the resource for the WAFv2 (I recommend to use this one) with a rate limit example rule and the association with an ALB:
########### This is the creation of an WAFv2 (Web ACL) and a example rate limit rule
resource "aws_wafv2_web_acl" "my_web_acl" {
name = "my-web-acl"
scope = "REGIONAL"
default_action {
allow {}
}
rule {
name = "RateLimit"
priority = 1
action {
block {}
}
statement {
rate_based_statement {
aggregate_key_type = "IP"
limit = 500
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "RateLimit"
sampled_requests_enabled = true
}
}
visibility_config {
cloudwatch_metrics_enabled = false
metric_name = "my-web-acl"
sampled_requests_enabled = false
}
}
########### This is the association code
resource "aws_wafv2_web_acl_association" "web_acl_association_my_lb" {
resource_arn = aws_lb.my_lb.arn
web_acl_arn = aws_wafv2_web_acl.my_web_acl.arn
}
You can associate a WAF with ALB (Application Load Balancer) and with CloudFront, you cannot associate with an ELB (Classic Elastic Load Balancer).
To associate with ALB this is the piece of code
resource "aws_wafregional_web_acl_association" "foo" {
resource_arn = "${aws_alb.foo.arn}"
web_acl_id = "${aws_wafregional_web_acl.foo.id}"
}
taken from the official documentation
This feature has been proposed but not merged yet.
https://github.com/hashicorp/terraform/issues/10713
https://github.com/hashicorp/terraform/pull/11263