Skip to content

Commit

Permalink
feat!: authenticate ALBs for ingresses (#1021)
Browse files Browse the repository at this point in the history
* feat: authenticate ALBs for ingresses

* commit from ci -- ran terraform-docs and pushed

* commit from ci -- ran terraform-docs and pushed

* commit from ci -- ran terraform fmt and pushed

* new opsgenie provider

* pin opsgenie provider

* commit from ci -- ran terraform-docs and pushed

* commit from ci -- ran terraform fmt and pushed

* data source teams

* commit from ci -- ran terraform-docs and pushed

* commit from ci -- ran terraform fmt and pushed

* add oidc config

* commit from ci -- ran terraform-docs and pushed

* https

* tls

* commit from ci -- ran terraform fmt and pushed

* tls

* remove dynamic

* commit from ci -- ran terraform fmt and pushed

* remove content

* unused variables

* commit from ci -- ran terraform-docs and pushed

* commit from ci -- ran terraform fmt and pushed

* remove the multidomain proxy

* update integration secret

* commit from ci -- ran terraform-docs and pushed

* remove certs

* commit from ci -- ran terraform-docs and pushed

* update tfe-okta-app for wildcard redirects

* commit from ci -- ran terraform-docs and pushed

* commit from ci -- ran terraform fmt and pushed

* no more forked okta

* commit from ci -- ran terraform-docs and pushed

* unused vars

* commit from ci -- ran terraform-docs and pushed

* commit from ci -- ran terraform-docs and pushed

* upgrade provider interface

* commit from ci -- ran terraform fmt and pushed

* go

* dyamic

* dynamic fix

* unused vars

* stale comment

* commit from ci -- ran terraform fmt and pushed

* add certificate back in, we need it

* acm back into int secret

* commit from ci -- ran terraform-docs and pushed

* external zone name back in

* release

* commit from ci -- ran terraform fmt and pushed

* commit from ci -- ran terraform-docs and pushed

* local

* only project

* revert to czi

* commit from ci -- ran terraform-docs and pushed

* test

* commit from ci -- ran terraform-docs and pushed

* remove unused providers

* commit from ci -- ran terraform-docs and pushed

* go

* remove AWS version requirement

* commit from ci -- ran terraform-docs and pushed

* commit from ci -- ran terraform-docs and pushed

* wrong redirect

* overwrite with the basedomain

* commit from ci -- ran terraform-docs and pushed

* commit from ci -- ran terraform fmt and pushed

* commit from ci -- ran terraform fmt and pushed

* typo

* okta groups not okta group

* commit from ci -- ran terraform-docs and pushed

* commit from ci -- ran terraform fmt and pushed

* typo

* commit from ci -- ran terraform fmt and pushed

* merge

* commit from ci -- ran terraform fmt and pushed

* merge

* commit from ci -- ran terraform fmt and pushed

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: czi-github-helper[bot] <czi-github-helper[bot]@users.noreply.github.com>
Co-authored-by: jakeyheath <[email protected]>
  • Loading branch information
4 people authored Jan 31, 2023
1 parent 7b2a146 commit 7cd9375
Show file tree
Hide file tree
Showing 22 changed files with 141 additions and 173 deletions.
6 changes: 0 additions & 6 deletions terraform/modules/happy-env-eks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ https://docs.google.com/drawings/d/1AsJts2qCmw7685A6WZPDb5ApkXyuPRc27Lg3zzWuPaA/
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 4.45 |
| <a name="requirement_kubernetes"></a> [kubernetes](#requirement\_kubernetes) | >= 2.16 |
| <a name="requirement_okta"></a> [okta](#requirement\_okta) | ~> 3.10 |
| <a name="requirement_random"></a> [random](#requirement\_random) | >= 3.4 |

## Providers
Expand All @@ -24,21 +23,17 @@ https://docs.google.com/drawings/d/1AsJts2qCmw7685A6WZPDb5ApkXyuPRc27Lg3zzWuPaA/
| Name | Source | Version |
|------|--------|---------|
| <a name="module_cert"></a> [cert](#module\_cert) | github.com/chanzuckerberg/cztack//aws-acm-certificate | v0.43.1 |
| <a name="module_cert_oauth"></a> [cert\_oauth](#module\_cert\_oauth) | github.com/chanzuckerberg/cztack//aws-acm-certificate | v0.43.1 |
| <a name="module_dbs"></a> [dbs](#module\_dbs) | github.com/chanzuckerberg/cztack//aws-aurora-postgres | v0.49.0 |
| <a name="module_ecrs"></a> [ecrs](#module\_ecrs) | [email protected]:chanzuckerberg/shared-infra//terraform/modules/ecr-repository | main |
| <a name="module_happy_github_ci_role"></a> [happy\_github\_ci\_role](#module\_happy\_github\_ci\_role) | ../happy-github-ci-role | n/a |
| <a name="module_happy_okta_app"></a> [happy\_okta\_app](#module\_happy\_okta\_app) | ../happy-tfe-okta-app | n/a |
| <a name="module_ops-genie"></a> [ops-genie](#module\_ops-genie) | [email protected]:chanzuckerberg/shared-infra//terraform/modules/ops-genie-service | main |
| <a name="module_proxy"></a> [proxy](#module\_proxy) | [email protected]:chanzuckerberg/shared-infra//terraform/modules/eks-multi-domain-oauth-proxy | eks-multi-domain-oauth-proxy-v1.3.0 |
| <a name="module_s3_buckets"></a> [s3\_buckets](#module\_s3\_buckets) | github.com/chanzuckerberg/cztack//aws-s3-private-bucket | v0.43.1 |

## Resources

| Name | Type |
|------|------|
| [aws_route53_record.happy_prefixed](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource |
| [aws_route53_zone.happy_prefixed](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_zone) | resource |
| [kubernetes_namespace.happy](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace) | resource |
| [kubernetes_secret.happy_env_secret](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret) | resource |
| [random_password.db_secret](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource |
Expand All @@ -58,7 +53,6 @@ https://docs.google.com/drawings/d/1AsJts2qCmw7685A6WZPDb5ApkXyuPRc27Lg3zzWuPaA/
| <a name="input_extra_proxy_args"></a> [extra\_proxy\_args](#input\_extra\_proxy\_args) | Add to the proxy's default arguments. | `set(string)` | `[]` | no |
| <a name="input_k8s-core"></a> [k8s-core](#input\_k8s-core) | K8s core. Typically the outputs of the remote state for the corresponding k8s-core component. | <pre>object({<br> default_namespace : string,<br> aws_ssm_iam_role_name : string,<br> })</pre> | n/a | yes |
| <a name="input_oauth_bypass_paths"></a> [oauth\_bypass\_paths](#input\_oauth\_bypass\_paths) | Bypass these paths in the oauth proxy | `list(string)` | `[]` | no |
| <a name="input_oauth_dns_prefix"></a> [oauth\_dns\_prefix](#input\_oauth\_dns\_prefix) | DNS prefix for oauth-proxied stacks. Leave this empty if we don't need a prefix! | `string` | `""` | no |
| <a name="input_oidc_issuer_host"></a> [oidc\_issuer\_host](#input\_oidc\_issuer\_host) | The OIDC issuer host for the OIDC provider to use for happy authentication | `string` | `"czi-prod.okta.com"` | no |
| <a name="input_okta_teams"></a> [okta\_teams](#input\_okta\_teams) | The set of Okta teams to give access to the Okta app | `set(string)` | n/a | yes |
| <a name="input_ops_genie_owner_team"></a> [ops\_genie\_owner\_team](#input\_ops\_genie\_owner\_team) | The name of the Opsgenie team that will own the alerts for this happy environment | `string` | `"Core Infra Eng"` | no |
Expand Down
19 changes: 6 additions & 13 deletions terraform/modules/happy-env-eks/acm.tf
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
module "cert" {
source = "github.com/chanzuckerberg/cztack//aws-acm-certificate?ref=v0.43.1"

cert_domain_name = local.base_domain
cert_subject_alternative_names = {
"*.${local.base_domain}" = var.base_zone_id
}

aws_route53_zone_id = var.base_zone_id
tags = merge(var.tags, { "managedBy" : "terraform" })
data "aws_route53_zone" "base_zone" {
zone_id = var.base_zone_id
private_zone = true
}

module "cert_oauth" {
module "cert" {
source = "github.com/chanzuckerberg/cztack//aws-acm-certificate?ref=v0.43.1"
count = length(var.oauth_dns_prefix) == 0 ? 0 : 1

cert_domain_name = local.env_domain
cert_domain_name = data.aws_route53_zone.base_zone.name
cert_subject_alternative_names = {
"*.${local.env_domain}" = var.base_zone_id
"*.${data.aws_route53_zone.base_zone.name}" = var.base_zone_id
}

aws_route53_zone_id = var.base_zone_id
Expand Down
8 changes: 2 additions & 6 deletions terraform/modules/happy-env-eks/integration_secret.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,12 @@ locals {
kind = "k8s"
vpc_id = var.cloud-env.vpc_id
zone_id = var.base_zone_id
external_zone_name = local.base_domain
internal_zone_name = local.env_domain
external_zone_name = data.aws_route53_zone.base_zone.name

cloud_env = var.cloud-env
eks_cluster = var.eks-cluster
certificate_arn = module.cert.arn
tags = var.tags

proxy_service_name = module.proxy.proxy_service_name
certificate_arn = module.cert.arn

ecrs = { for name, ecr in module.ecrs : name => { "url" : ecr.repository_url } }
dbs = {
Expand All @@ -27,7 +24,6 @@ locals {
oidc_config = module.happy_okta_app.oidc_config
}

# TODO: this only works if all additional_secrets values are maps!
merged_secrets = { for key, value in var.additional_secrets : key => merge(lookup(local.standard_secrets, key, {}), value) }
secret_string = merge(
local.standard_secrets,
Expand Down
8 changes: 4 additions & 4 deletions terraform/modules/happy-env-eks/oidc.tf
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@

module "happy_okta_app" {
source = "../happy-tfe-okta-app"

app_name = "${var.tags.project}-${var.tags.env}-${var.tags.service}"
env = var.tags.env
teams = var.okta_teams
app_name = var.tags.project
env = var.tags.env
teams = var.okta_teams
base_domain = data.aws_route53_zone.base_zone.name
}
42 changes: 0 additions & 42 deletions terraform/modules/happy-env-eks/proxy.tf

This file was deleted.

6 changes: 0 additions & 6 deletions terraform/modules/happy-env-eks/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,6 @@ variable "additional_secrets" {
default = {}
}

variable "oauth_dns_prefix" {
description = "DNS prefix for oauth-proxied stacks. Leave this empty if we don't need a prefix!"
type = string
default = ""
}

variable "oauth_bypass_paths" {
description = "Bypass these paths in the oauth proxy"
type = list(string)
Expand Down
4 changes: 0 additions & 4 deletions terraform/modules/happy-env-eks/versions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@ terraform {
source = "hashicorp/kubernetes"
version = ">= 2.16"
}
okta = {
source = "chanzuckerberg/okta"
version = "~> 3.10"
}
}
required_version = ">= 1.3"
}
3 changes: 1 addition & 2 deletions terraform/modules/happy-ingress-eks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ No modules.
| <a name="input_health_check_path"></a> [health\_check\_path](#input\_health\_check\_path) | path to use for health checks | `string` | `"/"` | no |
| <a name="input_ingress_name"></a> [ingress\_name](#input\_ingress\_name) | Name of the ingress resource | `string` | n/a | yes |
| <a name="input_k8s_namespace"></a> [k8s\_namespace](#input\_k8s\_namespace) | K8S namespace for this service | `string` | n/a | yes |
| <a name="input_routing"></a> [routing](#input\_routing) | Routing configuration for the ingress | <pre>object({<br> method : optional(string, "DOMAIN")<br> host_match : string<br> group_name : string<br> priority : number<br> path : optional(string, "/*")<br> service_name : string<br> service_port : number<br> success_codes : optional(string, "200-499")<br> })</pre> | n/a | yes |
| <a name="input_service_type"></a> [service\_type](#input\_service\_type) | The type of the service to deploy. Supported types include 'EXTERNAL', 'INTERNAL', and 'PRIVATE' | `string` | n/a | yes |
| <a name="input_routing"></a> [routing](#input\_routing) | Routing configuration for the ingress | <pre>object({<br> method : optional(string, "DOMAIN")<br> host_match : string<br> group_name : string<br> priority : number<br> path : optional(string, "/*")<br> service_name : string<br> service_port : number<br> service_type : string<br> oidc_config : optional(object({<br> issuer : string<br> authorizationEndpoint : string<br> tokenEndpoint : string<br> userInfoEndpoint : string<br> secretName : string<br> }), {<br> issuer = ""<br> authorizationEndpoint = ""<br> tokenEndpoint = ""<br> userInfoEndpoint = ""<br> secretName = ""<br> })<br> success_codes : optional(string, "200-499")<br> })</pre> | n/a | yes |
| <a name="input_tags_string"></a> [tags\_string](#input\_tags\_string) | Tags to apply to ingress resource, comma delimited key=value pairs | `string` | `""` | no |

## Outputs
Expand Down
49 changes: 28 additions & 21 deletions terraform/modules/happy-ingress-eks/main.tf
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
locals {
create_ingress = (var.service_type == "EXTERNAL" || var.service_type == "INTERNAL")
scheme = var.service_type == "EXTERNAL" ? "internet-facing" : "internal"
create_ingress = (var.routing.service_type == "EXTERNAL" || var.routing.service_type == "INTERNAL")
listen_ports_base = [{ "HTTP" : 80 }]
listen_ports_tls = [merge(local.listen_ports_base[0], { "HTTPS" : 443 })]
ingress_base_annotations = {
"alb.ingress.kubernetes.io/backend-protocol" = "HTTP"
"alb.ingress.kubernetes.io/healthcheck-path" = var.health_check_path
"alb.ingress.kubernetes.io/healthcheck-protocol" = "HTTP"
"alb.ingress.kubernetes.io/listen-ports" = var.service_type == "EXTERNAL" ? jsonencode(local.listen_ports_tls) : jsonencode(local.listen_ports_base)
"alb.ingress.kubernetes.io/scheme" = local.scheme
"alb.ingress.kubernetes.io/backend-protocol" = "HTTP"
"alb.ingress.kubernetes.io/healthcheck-path" = var.health_check_path
"alb.ingress.kubernetes.io/healthcheck-protocol" = "HTTP"
# All ingresses are "internet-facing" so we need them all to listen on TLS
"alb.ingress.kubernetes.io/listen-ports" = jsonencode(local.listen_ports_tls)
# All ingresses are "internet-facing". If a service_type was marked "INTERNAL", it will be protected using OIDC.
"alb.ingress.kubernetes.io/scheme" = "internet-facing"
"alb.ingress.kubernetes.io/subnets" = join(",", var.cloud_env.public_subnets)
"alb.ingress.kubernetes.io/success-codes" = var.routing.success_codes
"alb.ingress.kubernetes.io/tags" = var.tags_string
Expand All @@ -25,7 +26,16 @@ locals {
"alb.ingress.kubernetes.io/certificate-arn" = var.certificate_arn
"alb.ingress.kubernetes.io/ssl-policy" = "ELBSecurityPolicy-TLS-1-2-2017-01"
}
ingress_annotations = var.service_type == "EXTERNAL" ? merge(local.ingress_tls_annotations, local.ingress_base_annotations) : local.ingress_base_annotations
ingress_auth_annotations = {
"alb.ingress.kubernetes.io/auth-type" = "oidc"
"alb.ingress.kubernetes.io/auth-on-unauthenticated-request" = "authenticate"
"alb.ingress.kubernetes.io/auth-idp-oidc" = jsonencode(var.routing.oidc_config)
}
ingress_annotations = (
var.routing.service_type == "EXTERNAL" ?
merge(local.ingress_tls_annotations, local.ingress_base_annotations) :
merge(local.ingress_tls_annotations, local.ingress_auth_annotations, local.ingress_base_annotations)
)
}

resource "kubernetes_ingress_v1" "ingress" {
Expand All @@ -41,22 +51,19 @@ resource "kubernetes_ingress_v1" "ingress" {
}

spec {
dynamic "rule" {
for_each = var.service_type == "EXTERNAL" ? [0] : []
content {
http {
path {
backend {
service {
name = "redirect"
port {
name = "use-annotation"
}
rule {
http {
path {
backend {
service {
name = "redirect"
port {
name = "use-annotation"
}
}

path = "/*"
}

path = "/*"
}
}
}
Expand Down
22 changes: 15 additions & 7 deletions terraform/modules/happy-ingress-eks/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,6 @@ variable "certificate_arn" {
description = "ACM certificate ARN to attach to the load balancer listener"
}


variable "service_type" {
type = string
description = "The type of the service to deploy. Supported types include 'EXTERNAL', 'INTERNAL', and 'PRIVATE'"
}

variable "tags_string" {
type = string
description = "Tags to apply to ingress resource, comma delimited key=value pairs"
Expand All @@ -52,7 +46,21 @@ variable "routing" {
path : optional(string, "/*")
service_name : string
service_port : number
service_type : string
oidc_config : optional(object({
issuer : string
authorizationEndpoint : string
tokenEndpoint : string
userInfoEndpoint : string
secretName : string
}), {
issuer = ""
authorizationEndpoint = ""
tokenEndpoint = ""
userInfoEndpoint = ""
secretName = ""
})
success_codes : optional(string, "200-499")
})
description = "Routing configuration for the ingress"
}
}
3 changes: 1 addition & 2 deletions terraform/modules/happy-service-eks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,8 @@
| <a name="input_k8s_namespace"></a> [k8s\_namespace](#input\_k8s\_namespace) | K8S namespace for this service | `string` | n/a | yes |
| <a name="input_memory"></a> [memory](#input\_memory) | Memory in megabits per pod | `string` | `"100Mi"` | no |
| <a name="input_period_seconds"></a> [period\_seconds](#input\_period\_seconds) | The period in seconds used for the liveness and readiness probes. | `number` | `3` | no |
| <a name="input_routing"></a> [routing](#input\_routing) | Routing configuration for the ingress | <pre>object({<br> method : optional(string, "DOMAIN")<br> host_match : string<br> group_name : string<br> priority : number<br> path : optional(string, "/*")<br> service_name : string<br> service_port : number<br> success_codes : optional(string, "200-499")<br> })</pre> | n/a | yes |
| <a name="input_routing"></a> [routing](#input\_routing) | Routing configuration for the ingress | <pre>object({<br> method : optional(string, "DOMAIN")<br> host_match : string<br> group_name : string<br> priority : number<br> path : optional(string, "/*")<br> service_name : string<br> service_port : number<br> success_codes : optional(string, "200-499")<br> service_type : string<br> oidc_config : optional(object({<br> issuer : string<br> authorizationEndpoint : string<br> tokenEndpoint : string<br> userInfoEndpoint : string<br> secretName : string<br> }), {<br> issuer = ""<br> authorizationEndpoint = ""<br> tokenEndpoint = ""<br> userInfoEndpoint = ""<br> secretName = ""<br> })<br> })</pre> | n/a | yes |
| <a name="input_service_endpoints"></a> [service\_endpoints](#input\_service\_endpoints) | Service endpoints to be injected for service discovery | `map(string)` | `{}` | no |
| <a name="input_service_type"></a> [service\_type](#input\_service\_type) | The type of the service to deploy. Supported types include 'EXTERNAL', 'INTERNAL', and 'PRIVATE' | `string` | n/a | yes |
| <a name="input_stack_name"></a> [stack\_name](#input\_stack\_name) | Happy Path stack name | `string` | n/a | yes |
| <a name="input_tags"></a> [tags](#input\_tags) | Standard tags to attach to all happy services | <pre>object({<br> env : string,<br> owner : string,<br> project : string,<br> service : string,<br> managedBy : string,<br> })</pre> | <pre>{<br> "env": "ADDTAGS",<br> "managedBy": "ADDTAGS",<br> "owner": "ADDTAGS",<br> "project": "ADDTAGS",<br> "service": "ADDTAGS"<br>}</pre> | no |
| <a name="input_wait_for_steady_state"></a> [wait\_for\_steady\_state](#input\_wait\_for\_steady\_state) | Whether Terraform should block until the service is in a steady state before exiting | `bool` | `true` | no |
Expand Down
3 changes: 1 addition & 2 deletions terraform/modules/happy-service-eks/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ data "aws_region" "current" {}

locals {
tags_string = join(",", [for key, val in local.routing_tags : "${key}=${val}"])
service_type = var.service_type == "PRIVATE" ? "ClusterIP" : "NodePort"
service_type = var.routing.service_type == "PRIVATE" ? "ClusterIP" : "NodePort"
}

resource "kubernetes_deployment" "deployment" {
Expand Down Expand Up @@ -165,7 +165,6 @@ module "ingress" {
ingress_name = var.routing.service_name
cloud_env = var.cloud_env
k8s_namespace = var.k8s_namespace
service_type = var.service_type
certificate_arn = var.certificate_arn
tags_string = local.tags_string
routing = var.routing
Expand Down
2 changes: 1 addition & 1 deletion terraform/modules/happy-service-eks/tags.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ locals {
happy_service_name = var.routing.service_name,
happy_region = data.aws_region.current.name,
happy_image = var.image,
happy_service_type = var.service_type,
happy_service_type = var.routing.service_type,
happy_last_applied = timestamp(),
})

Expand Down
20 changes: 14 additions & 6 deletions terraform/modules/happy-service-eks/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,6 @@ variable "service_endpoints" {
description = "Service endpoints to be injected for service discovery"
}

variable "service_type" {
type = string
description = "The type of the service to deploy. Supported types include 'EXTERNAL', 'INTERNAL', and 'PRIVATE'"
}

variable "period_seconds" {
type = number
default = 3
Expand All @@ -100,7 +95,6 @@ variable "aws_iam_policy_json" {
description = "The AWS IAM policy to give to the pod."
}


variable "eks_cluster" {
type = object({
cluster_id : string,
Expand Down Expand Up @@ -135,6 +129,20 @@ variable "routing" {
service_name : string
service_port : number
success_codes : optional(string, "200-499")
service_type : string
oidc_config : optional(object({
issuer : string
authorizationEndpoint : string
tokenEndpoint : string
userInfoEndpoint : string
secretName : string
}), {
issuer = ""
authorizationEndpoint = ""
tokenEndpoint = ""
userInfoEndpoint = ""
secretName = ""
})
})
description = "Routing configuration for the ingress"
}
Expand Down
Loading

0 comments on commit 7cd9375

Please sign in to comment.