diff --git a/.codecov.yml b/.codecov.yml index d49aea0305..2cfe933050 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -7,7 +7,9 @@ comment: require_changes: false coverage: precision: 2 - range: "80%" + range: + - 70.0 + - 100.0 round: down status: changes: false diff --git a/backend/pycon/middleware.py b/backend/pycon/middleware.py deleted file mode 100644 index 82be50b5c4..0000000000 --- a/backend/pycon/middleware.py +++ /dev/null @@ -1,8 +0,0 @@ -def force_pycon_host(get_response): - def middleware(request): - request.META["HTTP_X_FORWARDED_PROTO"] = "https" - request.META["HTTP_HOST"] = "pycon.it" - - return get_response(request) - - return middleware diff --git a/backend/pycon/settings/prod.py b/backend/pycon/settings/prod.py index e4096d5a65..f567bb5708 100644 --- a/backend/pycon/settings/prod.py +++ b/backend/pycon/settings/prod.py @@ -1,5 +1,5 @@ from .base import * # noqa -from .base import DATABASES, MIDDLEWARE, env +from .base import DATABASES, env SECRET_KEY = env("SECRET_KEY") @@ -19,11 +19,8 @@ "EMAIL_BACKEND", default="django.core.mail.backends.locmem.EmailBackend" ) -FORCE_PYCON_HOST = env("FORCE_PYCON_HOST", bool, default=True) - -if FORCE_PYCON_HOST: # pragma: no cover - SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") - MIDDLEWARE += ["pycon.middleware.force_pycon_host"] +USE_X_FORWARDED_HOST = True +SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") DEFAULT_FROM_EMAIL = "noreply@pycon.it" diff --git a/backend/pycon/tests/test_middleware.py b/backend/pycon/tests/test_middleware.py deleted file mode 100644 index b3cbfa2503..0000000000 --- a/backend/pycon/tests/test_middleware.py +++ /dev/null @@ -1,14 +0,0 @@ -from pycon.middleware import ( - force_pycon_host, -) - - -def test_force_host_middleware(rf): - request = rf.get("/") - - def check_request(r): - assert request.headers["X-Forwarded-Proto"] == "https" - assert request.headers["Host"] == "pycon.it" - - middleware = force_pycon_host(check_request) - middleware(request) diff --git a/backend/pycon/tests/test_settings.py b/backend/pycon/tests/test_settings.py new file mode 100644 index 0000000000..93e00aa9d5 --- /dev/null +++ b/backend/pycon/tests/test_settings.py @@ -0,0 +1,8 @@ +def test_importing_settings(mocker): + # test that importing settings does not raise any exception + mocker.patch("pycon.settings.base.env") + + from pycon.settings import prod # noqa + from pycon.settings import dev # noqa + from pycon.settings import test # noqa + from pycon.settings import base # noqa diff --git a/infrastructure/applications/applications.tf b/infrastructure/applications/applications.tf index 380a5c6791..11bceb06ac 100644 --- a/infrastructure/applications/applications.tf +++ b/infrastructure/applications/applications.tf @@ -1,7 +1,7 @@ locals { - is_prod = terraform.workspace == "production" - deploy_pretix = local.is_prod - enable_proxy = local.is_prod ? false : false + is_prod = terraform.workspace == "production" + deploy_pretix = local.is_prod + enable_proxy = local.is_prod ? false : false } # Applications @@ -13,8 +13,8 @@ module "pretix" { } module "pycon_backend" { - source = "./pycon_backend" - enable_proxy = local.enable_proxy + source = "./pycon_backend" + enable_proxy = local.enable_proxy providers = { aws = aws diff --git a/infrastructure/applications/pycon_backend/main.tf b/infrastructure/applications/pycon_backend/main.tf index 64b0f37b27..256097c6de 100644 --- a/infrastructure/applications/pycon_backend/main.tf +++ b/infrastructure/applications/pycon_backend/main.tf @@ -51,6 +51,11 @@ data "aws_acm_certificate" "cert" { provider = aws.us } +data "aws_lambda_function" "forward_host_header" { + function_name = "forward_host_header" + provider = aws.us +} + data "aws_elasticache_cluster" "redis" { cluster_id = "production-pretix" } @@ -71,7 +76,7 @@ module "lambda" { SENTRY_DSN = module.secrets.value.sentry_dsn VOLUNTEERS_PUSH_NOTIFICATIONS_IOS_ARN = module.secrets.value.volunteers_push_notifications_ios_arn VOLUNTEERS_PUSH_NOTIFICATIONS_ANDROID_ARN = module.secrets.value.volunteers_push_notifications_android_arn - ALLOWED_HOSTS = "*" + ALLOWED_HOSTS = "admin.pycon.it" DJANGO_SETTINGS_MODULE = "pycon.settings.prod" ASSOCIATION_FRONTEND_URL = "https://associazione.python.it" AWS_MEDIA_BUCKET = aws_s3_bucket.backend_media.id @@ -84,7 +89,6 @@ module "lambda" { AWS_S3_CUSTOM_DOMAIN = local.cdn_url PRETIX_API_TOKEN = module.common_secrets.value.pretix_api_token PINPOINT_APPLICATION_ID = module.secrets.value.pinpoint_application_id - FORCE_PYCON_HOST = local.is_prod SQS_QUEUE_URL = aws_sqs_queue.queue.id MAILCHIMP_SECRET_KEY = module.common_secrets.value.mailchimp_secret_key MAILCHIMP_DC = module.common_secrets.value.mailchimp_dc @@ -123,9 +127,10 @@ module "api" { module "admin_distribution" { source = "../../components/cloudfront" - application = local.application - zone_name = "pycon.it" - domain = local.full_admin_domain - certificate_arn = data.aws_acm_certificate.cert.arn - origin_url = module.api.cloudfront_friendly_endpoint + application = local.application + zone_name = "pycon.it" + domain = local.full_admin_domain + certificate_arn = data.aws_acm_certificate.cert.arn + origin_url = module.api.cloudfront_friendly_endpoint + forward_host_header_lambda_arn = data.aws_lambda_function.forward_host_header.qualified_arn } diff --git a/infrastructure/applications/pycon_backend/worker.tf b/infrastructure/applications/pycon_backend/worker.tf index 5c630b41aa..3c81d43e14 100644 --- a/infrastructure/applications/pycon_backend/worker.tf +++ b/infrastructure/applications/pycon_backend/worker.tf @@ -30,7 +30,7 @@ locals { }, { name = "ALLOWED_HOSTS", - value = "*" + value = "admin.pycon.it" }, { name = "DJANGO_SETTINGS_MODULE", @@ -49,7 +49,7 @@ locals { value = aws_s3_bucket.backend_media.region }, { - name = "AWS_DEFAULT_REGION", + name = "AWS_DEFAULT_REGION", value = "eu-central-1" }, { @@ -84,10 +84,6 @@ locals { name = "PINPOINT_APPLICATION_ID", value = module.secrets.value.pinpoint_application_id }, - { - name = "FORCE_PYCON_HOST", - value = local.is_prod ? "true" : "false" - }, { name = "SQS_QUEUE_URL", value = aws_sqs_queue.queue.id @@ -173,7 +169,7 @@ locals { value = data.external.githash.result.githash }, { - name = "PLAIN_INTEGRATION_TOKEN" + name = "PLAIN_INTEGRATION_TOKEN" value = module.secrets.value.plain_integration_token }, { diff --git a/infrastructure/azure-applications/components/container_app/variables.tf b/infrastructure/azure-applications/components/container_app/variables.tf index 53bf30bc23..345308d3a3 100644 --- a/infrastructure/azure-applications/components/container_app/variables.tf +++ b/infrastructure/azure-applications/components/container_app/variables.tf @@ -7,7 +7,7 @@ variable "service_name" { } variable "service_resource_name" { - type = string + type = string default = null } diff --git a/infrastructure/azure-applications/users_backend/app.tf b/infrastructure/azure-applications/users_backend/app.tf index 7573a534f8..82d78e43ef 100644 --- a/infrastructure/azure-applications/users_backend/app.tf +++ b/infrastructure/azure-applications/users_backend/app.tf @@ -16,17 +16,17 @@ data "azurerm_postgresql_flexible_server" "db" { } module "app" { - source = "../components/container_app" - service_name = "users-backend" + source = "../components/container_app" + service_name = "users-backend" service_resource_name = "users" - resource_group_name = var.resource_group_name - workspace = var.workspace - githash = var.githash - environment_name = "pythonit-${var.workspace}-env" - healthcheck_path = "/graphql" - port = 8000 - domain = local.domain - command = ["/home/app/.venv/bin/python", "-m", "gunicorn", "main:wrapped_app"] + resource_group_name = var.resource_group_name + workspace = var.workspace + githash = var.githash + environment_name = "pythonit-${var.workspace}-env" + healthcheck_path = "/graphql" + port = 8000 + domain = local.domain + command = ["/home/app/.venv/bin/python", "-m", "gunicorn", "main:wrapped_app"] env_vars = [ { name = "DEBUG", value = "false", secret = false }, { name = "SECRET_KEY", value = random_password.secret_key.result, secret = true }, diff --git a/infrastructure/components/application_lambda/main.tf b/infrastructure/components/application_lambda/main.tf index b95e502557..04813393e1 100644 --- a/infrastructure/components/application_lambda/main.tf +++ b/infrastructure/components/application_lambda/main.tf @@ -1,7 +1,7 @@ locals { lambda_name = "${terraform.workspace}-${var.application}" base_env_vars = { - ENV = terraform.workspace, + ENV = terraform.workspace, GITHASH = data.external.githash.result.githash, } env_vars = merge(var.env_vars, local.base_env_vars) diff --git a/infrastructure/components/cloudfront/main.tf b/infrastructure/components/cloudfront/main.tf index 4a8d9946eb..bc0c0fd391 100644 --- a/infrastructure/components/cloudfront/main.tf +++ b/infrastructure/components/cloudfront/main.tf @@ -1,3 +1,11 @@ +data "aws_cloudfront_cache_policy" "caching_disabled" { + name = "Managed-CachingDisabled" +} + +data "aws_cloudfront_origin_request_policy" "all_viewer_except_host_header" { + name = "Managed-AllViewerExceptHostHeader" +} + resource "aws_cloudfront_distribution" "application" { enabled = true is_ipv6_enabled = true @@ -29,28 +37,20 @@ resource "aws_cloudfront_distribution" "application" { cached_methods = ["GET", "HEAD"] target_origin_id = "default" - forwarded_values { - query_string = true - headers = [ - "Access-Control-Request-Headers", - "Access-Control-Request-Method", - "Origin", - "Authorization", - "Referer", - "Accept", - "Accept-Language" - ] - - cookies { - forward = "all" - } - } + cache_policy_id = data.aws_cloudfront_cache_policy.caching_disabled.id + origin_request_policy_id = data.aws_cloudfront_origin_request_policy.all_viewer_except_host_header.id viewer_protocol_policy = "redirect-to-https" compress = true min_ttl = 0 default_ttl = 604800 max_ttl = 31536000 + + lambda_function_association { + event_type = "viewer-request" + lambda_arn = var.forward_host_header_lambda_arn + include_body = false + } } restrictions { diff --git a/infrastructure/components/cloudfront/variables.tf b/infrastructure/components/cloudfront/variables.tf index 6649c0d95d..2713c97095 100644 --- a/infrastructure/components/cloudfront/variables.tf +++ b/infrastructure/components/cloudfront/variables.tf @@ -3,3 +3,4 @@ variable "origin_url" {} variable "domain" {} variable "certificate_arn" {} variable "zone_name" {} +variable "forward_host_header_lambda_arn" {} diff --git a/infrastructure/global/.terraform.lock.hcl b/infrastructure/global/.terraform.lock.hcl index 276b877d9a..3442243d2f 100644 --- a/infrastructure/global/.terraform.lock.hcl +++ b/infrastructure/global/.terraform.lock.hcl @@ -1,37 +1,44 @@ # This file is maintained automatically by "terraform init". # Manual edits may be lost in future updates. -provider "registry.terraform.io/hashicorp/aws" { - version = "3.29.0" - constraints = "3.29.0" +provider "registry.terraform.io/hashicorp/archive" { + version = "2.4.2" hashes = [ - "h1:euXiL7Q/8CZ7eFO8ktcDVNEV51tJpicreQGazmNSGCg=", - "zh:0e3ec82025efcfed94180858240a1be147bc3eabb24a755f8c58970173b71e54", - "zh:22897ef5b00317ffa2495a5582c567a4ceca09e9071e0888b18c8364bab6d31b", - "zh:2e98fc511787045e5ef6f0e76d92ea8de27cd168b20902f9e57d75c96dcb80d8", - "zh:4e86f7f25c27c139ae17e3ad2a82a154b115d83f16bf8d8fee2aba9f00c80437", - "zh:71ba0b2b10a5e83b276ebca1d8559354c12656310bfd2554591ac6f0f5541bd0", - "zh:771989dadb5921bf4586c749a537116eaafdd854e542c5890c9dac55d7b2f8ac", - "zh:7aa3095c12174b6f8f525ba6007312df6b95de4b4137d25414144e7731ac202c", - "zh:a1c6f9a6f1abee0cc9c4a3a912c0e6571e7cc439701f03172de44b4187e66769", - "zh:bd50937e68e9434fc482817e9acfe486b95c69494194627884091a0581a0dffd", - "zh:e035fd1df86f709374a8547ac141edd1bd899cc7d979b7b28da3ad62fa6ff47b", + "h1:G4v6F6Lhqlo3EKGBKEK/kJRhNcQiRrhEdUiVpBHKHOA=", + "zh:08faed7c9f42d82bc3d406d0d9d4971e2d1c2d34eae268ad211b8aca57b7f758", + "zh:3564112ed2d097d7e0672378044a69b06642c326f6f1584d81c7cdd32ebf3a08", + "zh:53cd9afd223c15828c1916e68cb728d2be1cbccb9545568d6c2b122d0bac5102", + "zh:5ae4e41e3a1ce9d40b6458218a85bbde44f21723943982bca4a3b8bb7c103670", + "zh:5b65499218b315b96e95c5d3463ea6d7c66245b59461217c99eaa1611891cd2c", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:7f45b35a8330bebd184c2545a41782ff58240ed6ba947274d9881dd5da44b02e", + "zh:87e67891033214e55cfead1391d68e6a3bf37993b7607753237e82aa3250bb71", + "zh:de3590d14037ad81fc5cedf7cfa44614a92452d7b39676289b704a962050bc5e", + "zh:e7e6f2ea567f2dbb3baa81c6203be69f9cd6aeeb01204fd93e3cf181e099b610", + "zh:fd24d03c89a7702628c2e5a3c732c0dede56fa75a08da4a1efe17b5f881c88e2", + "zh:febf4b7b5f3ff2adff0573ef6361f09b6638105111644bdebc0e4f575373935f", ] } -provider "registry.terraform.io/hashicorp/template" { - version = "2.2.0" +provider "registry.terraform.io/hashicorp/aws" { + version = "5.42.0" + constraints = "5.42.0" hashes = [ - "h1:94qn780bi1qjrbC3uQtjJh3Wkfwd5+tTtJHOb7KTg9w=", - "zh:01702196f0a0492ec07917db7aaa595843d8f171dc195f4c988d2ffca2a06386", - "zh:09aae3da826ba3d7df69efeb25d146a1de0d03e951d35019a0f80e4f58c89b53", - "zh:09ba83c0625b6fe0a954da6fbd0c355ac0b7f07f86c91a2a97849140fea49603", - "zh:0e3a6c8e16f17f19010accd0844187d524580d9fdb0731f675ffcf4afba03d16", - "zh:45f2c594b6f2f34ea663704cc72048b212fe7d16fb4cfd959365fa997228a776", - "zh:77ea3e5a0446784d77114b5e851c970a3dde1e08fa6de38210b8385d7605d451", - "zh:8a154388f3708e3df5a69122a23bdfaf760a523788a5081976b3d5616f7d30ae", - "zh:992843002f2db5a11e626b3fc23dc0c87ad3729b3b3cff08e32ffb3df97edbde", - "zh:ad906f4cebd3ec5e43d5cd6dc8f4c5c9cc3b33d2243c89c5fc18f97f7277b51d", - "zh:c979425ddb256511137ecd093e23283234da0154b7fa8b21c2687182d9aea8b2", + "h1:Gwe5HXZYD/3M5j6LwKhp8amb1SraCR9p+G96d381RVc=", + "zh:0fb12bd56a3ad777b29f957c56dd2119776dbc01b6074458f597990e368c82de", + "zh:16e99c13bef6e3777f67c240c916f57c01c9c142254cfb2720e08281ff906447", + "zh:218268f5fe73bcb19e9a996f781ab66df0da9e333d1c60612e3c51ad28a5105f", + "zh:220b17f7053d11548f35136669687d30ef1f1036e15393275325fd2b9654c715", + "zh:2256cfd74988ce05eada76b42efffc6fe2bf4d60b61f57e4db4fcf65ced4c666", + "zh:52da19f531e0cb9828f73bca620e30264e63a494bd7f9ce826aabcf010d3a241", + "zh:56069ce08d720280ba39aaf2fdd40c4357ffb54262c80e4d39c4e540a38e76af", + "zh:82c81398e68324029167f813fbb7c54fa3d233e99fa05001d85cbce8bdd08bb3", + "zh:82d6eaa87f5ab318959064e6c89adc2baabaf70b13f2f7de866f62416de05352", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:ade8490cfdd8de8b9a82986588595b67e0ad1048d9e2d3a6f5164320179c2cd0", + "zh:b094ef56ae9bfffd586f46d4f7fb0097798738df758a8f3c51578ee163495c7e", + "zh:bd5e68e1e454bae0f8d73cff8448e814a35855a561c33b745e1b8b525fb06c9f", + "zh:c111c6a854bf121facca1642d528bfa80fb4214554ac6c33e4a59c86bc605b71", + "zh:e04df69a557adbcdf8efc77eb45be748f0acbe800ccede1e0895393c87722a0f", ] } diff --git a/infrastructure/global/archives/pycon-2022.tf b/infrastructure/global/archives/pycon-2022.tf new file mode 100644 index 0000000000..f5a863e0de --- /dev/null +++ b/infrastructure/global/archives/pycon-2022.tf @@ -0,0 +1,8 @@ +resource "aws_s3_bucket" "archive_2022" { + bucket = "2022.pycon.it" + acl = "private" + + website { + index_document = "index.html" + } +} diff --git a/infrastructure/global/lambdas/main.tf b/infrastructure/global/lambdas/main.tf new file mode 100644 index 0000000000..6aad0b112b --- /dev/null +++ b/infrastructure/global/lambdas/main.tf @@ -0,0 +1,49 @@ +resource "aws_iam_role" "lambda_edge_exec" { + assume_role_policy = <