-
Notifications
You must be signed in to change notification settings - Fork 1
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
ECS infrastructure with the Flagsmith task definition #4
Conversation
This is awesome, @deltacodepl, thank you so much for your contribution! Bonus points for the docs 🔥 There are formatting issues detected in CI, any chance you could look into it? |
Sure thing, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to be careful about what is being promised with this code.
If it is intended to be something that a user - a beginner with Terraform and AWS - could pick up and use to deploy their production environment, then I think the bar is very high. We'd need to accommodate lots of different options (things like the database sizing, database snapshotting, fargate resource allocation options and autoscaling, VPC and CIDR options etc) and absolutely need to be very careful with the IAM policies to reduce them to be least privilege.
Or, we could make very clear that this is a prove-to-yourself-and-your-boss-that-it-works example, but nothing more. Remove all references to "production" from this code and put a big warning at the top of the README to explain that this is not production ready, and that a user who is familiar with Terraform and AWS should use this as a reference to build their own solution.
# Listener (redirects traffic from the load balancer to the target group) | ||
resource "aws_alb_listener" "ecs-alb-http-listener" { | ||
load_balancer_arn = aws_lb.production.id | ||
port = "443" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that the load balancer SG allows 443 and 80, but there's only a 443 listener.
Suggest either:
- 443 only on the listener, 443 only on the load balancer SG
- 443 on the listener that forwards to the workload, 80 on the listener that redirects to 443, 443 and 80 on the load balancer SG (probably with a comment to say that 80 is only used for redirecting to 443)
default_action { | ||
type = "forward" | ||
target_group_arn = aws_alb_target_group.default-target-group.arn | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We've seen issues on ALB+ECS workloads, where requests like curl -k https://[load balancer ip]
get to the load balancer and are forwarded, and generate lots of DisallowedHost
errors from Django.
For this reason, think it is preferable here to have an action that matches on the expected host name, and forward that to the ALB target group. Then the default action is 404. As it happens, here is me suggesting this as an improvement in the CDK: aws/aws-cdk#25434.
load_balancer_arn = aws_lb.production.id | ||
port = "443" | ||
protocol = "HTTPS" | ||
ssl_policy = "ELBSecurityPolicy-2016-08" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be ELBSecurityPolicy-TLS13-1-0-2021-06
, with a comment to say that the user should ensure it is appropriate for their usage, and use a newer one if available when they are deploying, see https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html#describe-ssl-policies.
"ssmmessages:OpenControlChannel", | ||
"ssmmessages:OpenDataChannel" | ||
], | ||
"Resource" : "*" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this have to be *
?
Action = ["secretsmanager:GetSecretValue", "ssm:GetParameters"], | ||
Resource = ["arn:aws:ssm:${var.region}:${local.AWS_ACCOUNT_ID}:parameter/${var.app_name}/"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has a secretsmanager:...
permission action, but the resource is arn:aws:ssm:...
, which looks wrong to me.
resource "aws_route53_record" "subdomain" { | ||
zone_id = data.aws_route53_zone.selected.zone_id | ||
name = "${var.app_name}.${data.aws_route53_zone.selected.name}" | ||
type = "CNAME" | ||
ttl = "300" | ||
records = [aws_lb.production.dns_name] | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason not to use an Alias record here?
|
||
resource "aws_db_subnet_group" "production" { | ||
name = "main" | ||
# subnet_ids = module.vpc.public_subnets |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this line should probably go away, as I think we'd always want to encourage using private subnets for a database.
password = aws_ssm_parameter.db_password.value | ||
port = "5432" | ||
engine = "postgres" | ||
engine_version = "11.12" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason not to use a newer Postgres?
@@ -0,0 +1 @@ | |||
## Fargate autoscaling |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this to be removed, or should there be some resources here?
"Action": [ | ||
"ecs:*", | ||
"elasticloadbalancing:Describe*", | ||
"elasticloadbalancing:DeregisterInstancesFromLoadBalancer", | ||
"elasticloadbalancing:RegisterInstancesWithLoadBalancer", | ||
"elasticloadbalancing:RegisterTargets", | ||
"elasticloadbalancing:DeregisterTargets", | ||
"cloudwatch:*", | ||
"s3:*", | ||
"rds:*", | ||
"logs:*", | ||
"elasticache:*", | ||
"secretsmanager:*", | ||
"ssm:*" | ||
], | ||
"Resource": "*" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is very permissive. Could this be pruned?
2655235
to
4586796
Compare
4586796
to
9721911
Compare
Hi @plumdog |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍
Thanks for applying the changes, this looks great, thanks for the hard work.
I must confess I haven't run it though (I feel like someone Flagsmith-side should actually run this code at least once before we merge... [looks around for volunteers...])
It works, with some minor comments I've added. @deltacodepl I'll leave those for a bit of time in case you want to address them. Otherwise, I'll merge the PR and fix those myself. Again, many thanks for your work! Great job! 👍 |
Yep thanks again for this @deltacodepl |
Thanks for submitting a PR! Please check the boxes below:
Changes
Added "flagsmith-on-ecs" subproject with Terraform code that spins up ECS Fargate test cluster with the Flagsmith basic task definition.
The project provides instant access to the Flagsmith instance under specified domain by adding the flagsmith prefix such as
flagsmith.yourdomain.com
How did you test this code?
How to test this project
Register AWS Route53 Hosted Zone
for example
yourdomain.com
Generate certificate with AWS Certificate Manager
with
*.yourdomain.com
patternDefine your variables such as certificate arn, hosted zone domain, and other desired settings in terraform.tfvars file
Generate plan for infrastructure
terraform plan -out flagsmith.tfplan
Apply infrastructure by running
terraform apply flagsmith.tfplan