From 67e7465578a2a978d7874ada803aba59af334fd4 Mon Sep 17 00:00:00 2001 From: Ernest Mallett Date: Tue, 10 Jun 2025 09:20:56 -0500 Subject: [PATCH 1/6] Base users/groups --- .gitignore | 2 ++ modules/authentik/directory.tf | 18 ++++++++++++++++++ modules/authentik/main.tf | 0 modules/authentik/providers.tf | 13 +++++++++++++ modules/authentik/variables.tf | 15 +++++++++++++++ 5 files changed, 48 insertions(+) create mode 100644 .gitignore create mode 100644 modules/authentik/directory.tf create mode 100644 modules/authentik/main.tf create mode 100644 modules/authentik/providers.tf create mode 100644 modules/authentik/variables.tf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b0e4845 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.terraform +.terraform.lock.hcl \ No newline at end of file diff --git a/modules/authentik/directory.tf b/modules/authentik/directory.tf new file mode 100644 index 0000000..ddb4ce8 --- /dev/null +++ b/modules/authentik/directory.tf @@ -0,0 +1,18 @@ +resource "authentik_user" "dccoder" { + username = "DCCoder" + email = var.dccoder_email +} + +resource "authentik_user" "name" { + for_each = { for user in var.users : user.username => user } + + username = each.value.username + email = each.value.email + password = each.value.password +} + +resource "authentik_group" "group" { + name = "tf_admins" + users = [authentik_user.dccoder.id] + is_superuser = true +} \ No newline at end of file diff --git a/modules/authentik/main.tf b/modules/authentik/main.tf new file mode 100644 index 0000000..e69de29 diff --git a/modules/authentik/providers.tf b/modules/authentik/providers.tf new file mode 100644 index 0000000..27f661b --- /dev/null +++ b/modules/authentik/providers.tf @@ -0,0 +1,13 @@ +terraform { + required_providers { + authentik = { + source = "goauthentik/authentik" + version = "2025.4.0" + } + } +} + +provider "authentik" { +} + +# SEE: https://registry.terraform.io/providers/goauthentik/authentik/latest/docs \ No newline at end of file diff --git a/modules/authentik/variables.tf b/modules/authentik/variables.tf new file mode 100644 index 0000000..ab2e686 --- /dev/null +++ b/modules/authentik/variables.tf @@ -0,0 +1,15 @@ +variable "dccoder_email" { + description = "My email address" + default = "" +} + +variable "users" { + description = "List of users to create in authentik" + type = list(object({ + username = string + email = string + password = string + })) + default = [] + +} \ No newline at end of file From 1dc29797fef3a33afefd62770032868098e4c881 Mon Sep 17 00:00:00 2001 From: Ernest Mallett Date: Tue, 10 Jun 2025 09:49:08 -0500 Subject: [PATCH 2/6] Moving to application-centric approach --- ReadMe.md | 6 ++++ modules/authentik/provider_arr.tf | 0 proxy-application/main.tf | 23 +++++++++++++ proxy-application/providers.tf | 25 ++++++++++++++ proxy-application/proxy.tf | 38 +++++++++++++++++++++ proxy-application/variables.tf | 55 +++++++++++++++++++++++++++++++ 6 files changed, 147 insertions(+) create mode 100644 ReadMe.md create mode 100644 modules/authentik/provider_arr.tf create mode 100644 proxy-application/main.tf create mode 100644 proxy-application/providers.tf create mode 100644 proxy-application/proxy.tf create mode 100644 proxy-application/variables.tf diff --git a/ReadMe.md b/ReadMe.md new file mode 100644 index 0000000..cee6d6e --- /dev/null +++ b/ReadMe.md @@ -0,0 +1,6 @@ +## Providers + +https://registry.terraform.io/providers/goauthentik/authentik/latest/docs +https://registry.terraform.io/providers/Sander0542/nginxproxymanager/latest +https://registry.terraform.io/providers/portainer/portainer/latest +https://registry.terraform.io/providers/kevynb/technitium/latest \ No newline at end of file diff --git a/modules/authentik/provider_arr.tf b/modules/authentik/provider_arr.tf new file mode 100644 index 0000000..e69de29 diff --git a/proxy-application/main.tf b/proxy-application/main.tf new file mode 100644 index 0000000..d9f4ef5 --- /dev/null +++ b/proxy-application/main.tf @@ -0,0 +1,23 @@ +# Create a proxy provider + +data "authentik_flow" "default-authorization-flow" { + slug = "default-provider-authorization-implicit-consent" +} + +resource "authentik_provider_proxy" "name" { + name = lower(var.Application_Name) + internal_host = var.internal_host + external_host = var.external_host + basic_auth_password_attribute= var.Password_Attribute + basic_auth_username_attribute = var.Username_Attribute + basic_auth_enabled = true + authorization_flow = data.authentik_flow.default-authorization-flow.id +} + +resource "authentik_application" "name" { + name = var.Application_Name + slug = lower(replace(var.Application_Name," ", "-")) + protocol_provider = authentik_provider_proxy.name.id + group = var.Application_Group != "" ? var.Application_Group : null + meta_description = var.Application_Description != "" ? var.Application_Description : null +} \ No newline at end of file diff --git a/proxy-application/providers.tf b/proxy-application/providers.tf new file mode 100644 index 0000000..0b472a0 --- /dev/null +++ b/proxy-application/providers.tf @@ -0,0 +1,25 @@ +terraform { + required_providers { + authentik = { + source = "goauthentik/authentik" + version = "2025.4.0" + } + + nginxproxymanager = { + source = "Sander0542/nginxproxymanager" + version = "1.1.1" + } + + portainer = { + source = "portainer/portainer" + version = "1.4.3" + } + } +} + +provider "authentik" { +} + +# SEE: https://registry.terraform.io/providers/goauthentik/authentik/latest/docs +# SEE: https://registry.terraform.io/providers/Sander0542/nginxproxymanager/latest +# SEE: https://registry.terraform.io/providers/portainer/portainer/latest \ No newline at end of file diff --git a/proxy-application/proxy.tf b/proxy-application/proxy.tf new file mode 100644 index 0000000..8dbf2fd --- /dev/null +++ b/proxy-application/proxy.tf @@ -0,0 +1,38 @@ +resource "nginxproxymanager_proxy_host" "host" { + domain_names = [var.External_Host] + + forward_scheme = "https" + forward_host = var.External_Host + forward_port = 443 + + caching_enabled = true + allow_websocket_upgrade = true + block_exploits = true + + access_list_id = 1 + + locations = [ + { + path = "/" + forward_scheme = var.External_Scheme_Host + forward_host = var.External_Host + forward_port = var.Port + } + ] + + certificate_id = 1 + ssl_forced = true + hsts_enabled = false + hsts_subdomains = false + http2_support = true +} + +resource "nginxproxymanager_certificate_letsencrypt" "certificate" { + domain_names = [var.External_Host] + + letsencrypt_email = var.Admin_Email + letsencrypt_agree = true + dns_challenge = true + dns_provider = "cloudflare" + dns_provider_credentials = var.dns_cloudflare_api_token +} \ No newline at end of file diff --git a/proxy-application/variables.tf b/proxy-application/variables.tf new file mode 100644 index 0000000..8106a2f --- /dev/null +++ b/proxy-application/variables.tf @@ -0,0 +1,55 @@ +variable "Internal_Host" { + description = "Internal host for Application" + type = string +} + +variable "External_Host" { + description = "External host for Application" +} + +variable "External_Scheme_Host"{ + description = "value for the external scheme host" + type = string + default = "http" +} + +variable "Application_Name" { + description = "Name of the Application" + type = string +} + +variable "Port"{ + description = "Port for the Application" + type = number + default = 80 +} + +variable "Application_Group" { + description = "Group to assign the application to" + type = string + default = "" +} + +variable "Application_Description"{ + description = "Description of the Application" + type = string + default = "" +} + +variable "Username_Attribute" { + description = "Username attribute for Basic Auth" + type = string + default = "" +} + +variable "Password_Attribute" { + description = "Password attribute for Basic Auth" + type = string + default = "" +} + +variable "Admin_Email" { + description = "Email address for the admin user" + type = string + default = "" +} \ No newline at end of file From 1e378055e251a9a34d30c5ff95bd4c0a2eb20881 Mon Sep 17 00:00:00 2001 From: Ernest Mallett Date: Tue, 10 Jun 2025 11:02:31 -0500 Subject: [PATCH 3/6] Updated dns module and nginx module --- main.tf | 0 modules/dns/cloudflare.tf | 21 ++++++ modules/dns/nginxproxy.tf | 47 ++++++++++++ modules/dns/providers.tf | 18 +++++ modules/dns/technitium.tf | 17 +++++ modules/dns/variables.tf | 87 ++++++++++++++++++++++ modules/nginx_config/main.tf | 127 ++++++++++++++++++++++++++++++++ modules/nginx_config/outputs.tf | 11 +++ proxy-application/main.tf | 23 ------ proxy-application/providers.tf | 25 ------- proxy-application/proxy.tf | 38 ---------- proxy-application/variables.tf | 55 -------------- variables.tf | 0 13 files changed, 328 insertions(+), 141 deletions(-) delete mode 100644 main.tf create mode 100644 modules/dns/cloudflare.tf create mode 100644 modules/dns/nginxproxy.tf create mode 100644 modules/dns/providers.tf create mode 100644 modules/dns/technitium.tf create mode 100644 modules/dns/variables.tf create mode 100644 modules/nginx_config/main.tf create mode 100644 modules/nginx_config/outputs.tf delete mode 100644 proxy-application/main.tf delete mode 100644 proxy-application/providers.tf delete mode 100644 proxy-application/proxy.tf delete mode 100644 proxy-application/variables.tf delete mode 100644 variables.tf diff --git a/main.tf b/main.tf deleted file mode 100644 index e69de29..0000000 diff --git a/modules/dns/cloudflare.tf b/modules/dns/cloudflare.tf new file mode 100644 index 0000000..3425b22 --- /dev/null +++ b/modules/dns/cloudflare.tf @@ -0,0 +1,21 @@ +resource "cloudflare_dns_record" "example_dns_record" { + count = var.internal_only ? 0 : var.enable_ipv4 ? 1 : 0 + zone_id = var.zone_id + comment = "Managed via terraform" + content = var.external_host_ipv4 + name = var.domain_name + proxied = var.proxied_domain + ttl = var.ttl + type = "A" +} + +resource "cloudflare_dns_record" "example_dns_record" { + count = var.internal_only ? 0 : var.enable_ipv6 ? 1 : 0 + zone_id = var.zone_id + comment = "Managed via terraform" + content = var.external_host_ipv6 + name = var.domain_name + proxied = var.proxied_domain + ttl = var.ttl + type = "AAAA" +} \ No newline at end of file diff --git a/modules/dns/nginxproxy.tf b/modules/dns/nginxproxy.tf new file mode 100644 index 0000000..d490df4 --- /dev/null +++ b/modules/dns/nginxproxy.tf @@ -0,0 +1,47 @@ +module "nginx" { + source = "../nginx_config" +} + +resource "nginxproxymanager_certificate_letsencrypt" "certificate" { + domain_names = [var.domain_name] + + letsencrypt_email = var.admin_email + letsencrypt_agree = true + + dns_challenge = true + dns_provider = "cloudflare" + dns_provider_credentials = var.dns_cloudflare_api_token +} + +data "nginxproxymanager_access_list" "access_list" { + id = var.internal_only ? nginxproxymanager_access_list.internal_access.id : nginxproxymanager_access_list.cloudflare_access.id +} + +resource "nginxproxymanager_proxy_host" "host" { + domain_names = [var.domain_name] + + forward_scheme = "https" + forward_host = var.domain_name + forward_port = 443 + + caching_enabled = true + allow_websocket_upgrade = true + block_exploits = true + + access_list_id = data.nginxproxymanager_access_list.access_list.id + + locations = [ + { + path = "/" + forward_scheme = "http" + forward_host = var.internal_host_ipv4 != "" ? var.internal_host_ipv4 : var.internal_host_ipv6 + forward_port = var.service_port + } + ] + + certificate_id = nginxproxymanager_certificate_letsencrypt.certificate.id + ssl_forced = true + hsts_enabled = false + hsts_subdomains = false + http2_support = true +} \ No newline at end of file diff --git a/modules/dns/providers.tf b/modules/dns/providers.tf new file mode 100644 index 0000000..c4e092d --- /dev/null +++ b/modules/dns/providers.tf @@ -0,0 +1,18 @@ +terraform { + required_providers { + nginxproxymanager = { + source = "Sander0542/nginxproxymanager" + version = "1.1.1" + } + + cloudflare = { + source = "cloudflare/cloudflare" + version = "~> 5" + } + + technitium = { + source = "kevynb/technitium" + version = "0.2.0" + } + } +} \ No newline at end of file diff --git a/modules/dns/technitium.tf b/modules/dns/technitium.tf new file mode 100644 index 0000000..19d63d1 --- /dev/null +++ b/modules/dns/technitium.tf @@ -0,0 +1,17 @@ +resource "technitium_record" "my_cname" { + count = var.enable_ipv4 ? 1 : 0 + zone = var.zone_name + domain = var.domain_name + type = "A" + ip_address = var.internal_host_ipv4 + ttl = var.ttl +} + +resource "technitium_record" "my_cname" { + count = var.enable_ipv6 ? 1 : 0 + zone = var.zone_name + domain = var.domain_name + type = "AAAA" + ip_address = var.internal_host_ipv6 + ttl = var.ttl +} \ No newline at end of file diff --git a/modules/dns/variables.tf b/modules/dns/variables.tf new file mode 100644 index 0000000..b52ffe0 --- /dev/null +++ b/modules/dns/variables.tf @@ -0,0 +1,87 @@ +variable "internal_only" { + description = "If true, the application is only accessible internally" + type = bool + default = false +} + +variable "service_port" { + description = "Port on which the service is running" + type = number + default = 80 +} + +variable "dns_cloudflare_api_token" { + description = "Cloudflare API token for DNS updates" + type = string + default = "" + sensitive = true +} + +variable "admin_email" { + description = "Email address for the admin user" + type = string + default = "" +} + +variable "external_host_ipv4" { + description = "External host for the application" + type = string + default = "" +} + +variable "external_host_ipv6" { + description = "External host for the application" + type = string + default = "" +} + +variable "internal_host_ipv4" { + description = "Internal host for the application" + type = string + default = "" +} + +variable "internal_host_ipv6" { + description = "Internal host for the application" + type = string + default = "" +} + +variable "enable_ipv4" { + description = "If true, enable IPv4 for the application" + type = bool + default = true +} + +variable "enable_ipv6" { + description = "If true, enable IPv6 for the application" + type = bool + default = false +} + +variable "zone_name" { + description = "Zone name for the DNS record" + type = string +} + +variable "domain_name" { + description = "Domain name for the application" + type = string +} + +variable "zone_id" { + description = "Cloudflare zone ID for the DNS record" + type = string +} + +variable "proxied_domain"{ + description = "If true, the DNS record is proxied through Cloudflare" + type = bool + default = true +} + +variable "ttl" { + description = "Time to live for the DNS record" + type = number + default = 3600 +} \ No newline at end of file diff --git a/modules/nginx_config/main.tf b/modules/nginx_config/main.tf new file mode 100644 index 0000000..8a86c0c --- /dev/null +++ b/modules/nginx_config/main.tf @@ -0,0 +1,127 @@ +resource "nginxproxymanager_access_list" "internal_access" { + name = "Allow Internal Access Only" + + access = [ + { + directive = "allow" + address = "192.168.1.1/24" + }, + { + directive = "allow" + address = "192.168.2.1/24" + }, + { + directive = "allow" + address = "192.168.3.1/23" + }, + { + directive = "deny" + address = "all" + }, + ] + + pass_auth = false + satisfy_any = true +} + +resource "nginxproxymanager_access_list" "internal_access" { + name = "Allow Cloudflare Access Only" + + access = [ + { + directive = "allow" + address = "103.21.244.0/22" + }, + { + directive = "allow" + address = "103.22.200.0/22" + }, + { + directive = "allow" + address = "103.31.4.0/22" + }, + { + directive = "allow" + address = "104.16.0.0/13" + }, + { + directive = "allow" + address = "104.24.0.0/14" + }, + { + directive = "allow" + address = "108.162.192.0/18" + }, + { + directive = "allow" + address = "131.0.72.0/22" + }, + { + directive = "allow" + address = "141.101.64.0/18" + }, + { + directive = "allow" + address = "162.158.0.0/15" + }, + { + directive = "allow" + address = "172.64.0.0/13" + }, + { + directive = "allow" + address = "173.245.48.0/20" + }, + { + directive = "allow" + address = "188.114.96.0/20" + }, + { + directive = "allow" + address = "190.93.240.0/20" + }, + { + directive = "allow" + address = "197.234.240.0/22" + }, + { + directive = "allow" + address = "198.41.128.0/17" + }, + { + directive = "allow" + address = "2400:cb00::/32" + }, + { + directive = "allow" + address = "2606:4700::/32" + }, + { + directive = "allow" + address = "2803:f800::/32" + }, + { + directive = "allow" + address = "2405:b500::/32" + }, + { + directive = "allow" + address = "2405:8100::/32" + }, + { + directive = "allow" + address = "2a06:98c0::/29" + }, + { + directive = "allow" + address = "2c0f:f248::/32" + }, + { + directive = "deny" + address = "all" + }, + ] + + pass_auth = false + satisfy_any = true +} \ No newline at end of file diff --git a/modules/nginx_config/outputs.tf b/modules/nginx_config/outputs.tf new file mode 100644 index 0000000..daa06ed --- /dev/null +++ b/modules/nginx_config/outputs.tf @@ -0,0 +1,11 @@ +output "internal_access_list_id" { + description = "ID of the internal access list" + value = nginxproxymanager_access_list.internal_access.id + +} + +output "cloudflare_access_list_id" { + description = "ID of the Cloudflare access list" + value = nginxproxymanager_access_list.cloudflare_access.id + +} \ No newline at end of file diff --git a/proxy-application/main.tf b/proxy-application/main.tf deleted file mode 100644 index d9f4ef5..0000000 --- a/proxy-application/main.tf +++ /dev/null @@ -1,23 +0,0 @@ -# Create a proxy provider - -data "authentik_flow" "default-authorization-flow" { - slug = "default-provider-authorization-implicit-consent" -} - -resource "authentik_provider_proxy" "name" { - name = lower(var.Application_Name) - internal_host = var.internal_host - external_host = var.external_host - basic_auth_password_attribute= var.Password_Attribute - basic_auth_username_attribute = var.Username_Attribute - basic_auth_enabled = true - authorization_flow = data.authentik_flow.default-authorization-flow.id -} - -resource "authentik_application" "name" { - name = var.Application_Name - slug = lower(replace(var.Application_Name," ", "-")) - protocol_provider = authentik_provider_proxy.name.id - group = var.Application_Group != "" ? var.Application_Group : null - meta_description = var.Application_Description != "" ? var.Application_Description : null -} \ No newline at end of file diff --git a/proxy-application/providers.tf b/proxy-application/providers.tf deleted file mode 100644 index 0b472a0..0000000 --- a/proxy-application/providers.tf +++ /dev/null @@ -1,25 +0,0 @@ -terraform { - required_providers { - authentik = { - source = "goauthentik/authentik" - version = "2025.4.0" - } - - nginxproxymanager = { - source = "Sander0542/nginxproxymanager" - version = "1.1.1" - } - - portainer = { - source = "portainer/portainer" - version = "1.4.3" - } - } -} - -provider "authentik" { -} - -# SEE: https://registry.terraform.io/providers/goauthentik/authentik/latest/docs -# SEE: https://registry.terraform.io/providers/Sander0542/nginxproxymanager/latest -# SEE: https://registry.terraform.io/providers/portainer/portainer/latest \ No newline at end of file diff --git a/proxy-application/proxy.tf b/proxy-application/proxy.tf deleted file mode 100644 index 8dbf2fd..0000000 --- a/proxy-application/proxy.tf +++ /dev/null @@ -1,38 +0,0 @@ -resource "nginxproxymanager_proxy_host" "host" { - domain_names = [var.External_Host] - - forward_scheme = "https" - forward_host = var.External_Host - forward_port = 443 - - caching_enabled = true - allow_websocket_upgrade = true - block_exploits = true - - access_list_id = 1 - - locations = [ - { - path = "/" - forward_scheme = var.External_Scheme_Host - forward_host = var.External_Host - forward_port = var.Port - } - ] - - certificate_id = 1 - ssl_forced = true - hsts_enabled = false - hsts_subdomains = false - http2_support = true -} - -resource "nginxproxymanager_certificate_letsencrypt" "certificate" { - domain_names = [var.External_Host] - - letsencrypt_email = var.Admin_Email - letsencrypt_agree = true - dns_challenge = true - dns_provider = "cloudflare" - dns_provider_credentials = var.dns_cloudflare_api_token -} \ No newline at end of file diff --git a/proxy-application/variables.tf b/proxy-application/variables.tf deleted file mode 100644 index 8106a2f..0000000 --- a/proxy-application/variables.tf +++ /dev/null @@ -1,55 +0,0 @@ -variable "Internal_Host" { - description = "Internal host for Application" - type = string -} - -variable "External_Host" { - description = "External host for Application" -} - -variable "External_Scheme_Host"{ - description = "value for the external scheme host" - type = string - default = "http" -} - -variable "Application_Name" { - description = "Name of the Application" - type = string -} - -variable "Port"{ - description = "Port for the Application" - type = number - default = 80 -} - -variable "Application_Group" { - description = "Group to assign the application to" - type = string - default = "" -} - -variable "Application_Description"{ - description = "Description of the Application" - type = string - default = "" -} - -variable "Username_Attribute" { - description = "Username attribute for Basic Auth" - type = string - default = "" -} - -variable "Password_Attribute" { - description = "Password attribute for Basic Auth" - type = string - default = "" -} - -variable "Admin_Email" { - description = "Email address for the admin user" - type = string - default = "" -} \ No newline at end of file diff --git a/variables.tf b/variables.tf deleted file mode 100644 index e69de29..0000000 From ddfd4e833d7cdfb9626ea56f4bf07c1ff4934dc8 Mon Sep 17 00:00:00 2001 From: Ernest Mallett Date: Tue, 10 Jun 2025 11:32:28 -0500 Subject: [PATCH 4/6] Formatted files and added two authentication provider modules --- ReadMe.md | 3 +- modules/authentik/provider_arr.tf | 0 modules/dns/cloudflare.tf | 32 +++++------ modules/dns/nginxproxy.tf | 2 +- modules/dns/providers.tf | 4 +- modules/dns/technitium.tf | 24 ++++----- modules/dns/variables.tf | 88 +++++++++++++++---------------- modules/nginx_config/outputs.tf | 4 +- modules/oauth_auth/main.tf | 8 +++ modules/oauth_auth/outputs.tf | 9 ++++ modules/oauth_auth/policy.tf | 18 +++++++ modules/oauth_auth/service.tf | 34 ++++++++++++ modules/oauth_auth/variables.tf | 53 +++++++++++++++++++ modules/proxy_auth/main.tf | 8 +++ modules/proxy_auth/policy.tf | 18 +++++++ modules/proxy_auth/service.tf | 23 ++++++++ modules/proxy_auth/variables.tf | 44 ++++++++++++++++ 17 files changed, 294 insertions(+), 78 deletions(-) delete mode 100644 modules/authentik/provider_arr.tf create mode 100644 modules/oauth_auth/main.tf create mode 100644 modules/oauth_auth/outputs.tf create mode 100644 modules/oauth_auth/policy.tf create mode 100644 modules/oauth_auth/service.tf create mode 100644 modules/oauth_auth/variables.tf create mode 100644 modules/proxy_auth/main.tf create mode 100644 modules/proxy_auth/policy.tf create mode 100644 modules/proxy_auth/service.tf create mode 100644 modules/proxy_auth/variables.tf diff --git a/ReadMe.md b/ReadMe.md index cee6d6e..e356808 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -3,4 +3,5 @@ https://registry.terraform.io/providers/goauthentik/authentik/latest/docs https://registry.terraform.io/providers/Sander0542/nginxproxymanager/latest https://registry.terraform.io/providers/portainer/portainer/latest -https://registry.terraform.io/providers/kevynb/technitium/latest \ No newline at end of file +https://registry.terraform.io/providers/kevynb/technitium/latest +https://registry.terraform.io/providers/cloudflare/cloudflare/5.4.0/docs/resources/dns_record \ No newline at end of file diff --git a/modules/authentik/provider_arr.tf b/modules/authentik/provider_arr.tf deleted file mode 100644 index e69de29..0000000 diff --git a/modules/dns/cloudflare.tf b/modules/dns/cloudflare.tf index 3425b22..f70b208 100644 --- a/modules/dns/cloudflare.tf +++ b/modules/dns/cloudflare.tf @@ -1,21 +1,21 @@ resource "cloudflare_dns_record" "example_dns_record" { - count = var.internal_only ? 0 : var.enable_ipv4 ? 1 : 0 - zone_id = var.zone_id - comment = "Managed via terraform" - content = var.external_host_ipv4 - name = var.domain_name - proxied = var.proxied_domain - ttl = var.ttl - type = "A" + count = var.internal_only ? 0 : var.enable_ipv4 ? 1 : 0 + zone_id = var.zone_id + comment = "Managed via terraform" + content = var.external_host_ipv4 + name = var.domain_name + proxied = var.proxied_domain + ttl = var.ttl + type = "A" } resource "cloudflare_dns_record" "example_dns_record" { - count = var.internal_only ? 0 : var.enable_ipv6 ? 1 : 0 - zone_id = var.zone_id - comment = "Managed via terraform" - content = var.external_host_ipv6 - name = var.domain_name - proxied = var.proxied_domain - ttl = var.ttl - type = "AAAA" + count = var.internal_only ? 0 : var.enable_ipv6 ? 1 : 0 + zone_id = var.zone_id + comment = "Managed via terraform" + content = var.external_host_ipv6 + name = var.domain_name + proxied = var.proxied_domain + ttl = var.ttl + type = "AAAA" } \ No newline at end of file diff --git a/modules/dns/nginxproxy.tf b/modules/dns/nginxproxy.tf index d490df4..399b050 100644 --- a/modules/dns/nginxproxy.tf +++ b/modules/dns/nginxproxy.tf @@ -1,5 +1,5 @@ module "nginx" { - source = "../nginx_config" + source = "../nginx_config" } resource "nginxproxymanager_certificate_letsencrypt" "certificate" { diff --git a/modules/dns/providers.tf b/modules/dns/providers.tf index c4e092d..4d67836 100644 --- a/modules/dns/providers.tf +++ b/modules/dns/providers.tf @@ -1,7 +1,7 @@ terraform { required_providers { nginxproxymanager = { - source = "Sander0542/nginxproxymanager" + source = "Sander0542/nginxproxymanager" version = "1.1.1" } @@ -11,7 +11,7 @@ terraform { } technitium = { - source = "kevynb/technitium" + source = "kevynb/technitium" version = "0.2.0" } } diff --git a/modules/dns/technitium.tf b/modules/dns/technitium.tf index 19d63d1..f048f62 100644 --- a/modules/dns/technitium.tf +++ b/modules/dns/technitium.tf @@ -1,17 +1,17 @@ resource "technitium_record" "my_cname" { - count = var.enable_ipv4 ? 1 : 0 - zone = var.zone_name - domain = var.domain_name - type = "A" - ip_address = var.internal_host_ipv4 - ttl = var.ttl + count = var.enable_ipv4 ? 1 : 0 + zone = var.zone_name + domain = var.domain_name + type = "A" + ip_address = var.internal_host_ipv4 + ttl = var.ttl } resource "technitium_record" "my_cname" { - count = var.enable_ipv6 ? 1 : 0 - zone = var.zone_name - domain = var.domain_name - type = "AAAA" - ip_address = var.internal_host_ipv6 - ttl = var.ttl + count = var.enable_ipv6 ? 1 : 0 + zone = var.zone_name + domain = var.domain_name + type = "AAAA" + ip_address = var.internal_host_ipv6 + ttl = var.ttl } \ No newline at end of file diff --git a/modules/dns/variables.tf b/modules/dns/variables.tf index b52ffe0..1bc603f 100644 --- a/modules/dns/variables.tf +++ b/modules/dns/variables.tf @@ -1,87 +1,87 @@ variable "internal_only" { - description = "If true, the application is only accessible internally" - type = bool - default = false + description = "If true, the application is only accessible internally" + type = bool + default = false } variable "service_port" { - description = "Port on which the service is running" - type = number - default = 80 + description = "Port on which the service is running" + type = number + default = 80 } variable "dns_cloudflare_api_token" { - description = "Cloudflare API token for DNS updates" - type = string - default = "" - sensitive = true + description = "Cloudflare API token for DNS updates" + type = string + default = "" + sensitive = true } variable "admin_email" { - description = "Email address for the admin user" - type = string - default = "" + description = "Email address for the admin user" + type = string + default = "" } variable "external_host_ipv4" { - description = "External host for the application" - type = string - default = "" + description = "External host for the application" + type = string + default = "" } variable "external_host_ipv6" { - description = "External host for the application" - type = string - default = "" + description = "External host for the application" + type = string + default = "" } variable "internal_host_ipv4" { - description = "Internal host for the application" - type = string - default = "" + description = "Internal host for the application" + type = string + default = "" } variable "internal_host_ipv6" { - description = "Internal host for the application" - type = string - default = "" + description = "Internal host for the application" + type = string + default = "" } variable "enable_ipv4" { - description = "If true, enable IPv4 for the application" - type = bool - default = true + description = "If true, enable IPv4 for the application" + type = bool + default = true } variable "enable_ipv6" { - description = "If true, enable IPv6 for the application" - type = bool - default = false + description = "If true, enable IPv6 for the application" + type = bool + default = false } variable "zone_name" { - description = "Zone name for the DNS record" - type = string + description = "Zone name for the DNS record" + type = string } variable "domain_name" { - description = "Domain name for the application" - type = string + description = "Domain name for the application" + type = string } variable "zone_id" { - description = "Cloudflare zone ID for the DNS record" - type = string + description = "Cloudflare zone ID for the DNS record" + type = string } -variable "proxied_domain"{ - description = "If true, the DNS record is proxied through Cloudflare" - type = bool - default = true +variable "proxied_domain" { + description = "If true, the DNS record is proxied through Cloudflare" + type = bool + default = true } variable "ttl" { - description = "Time to live for the DNS record" - type = number - default = 3600 + description = "Time to live for the DNS record" + type = number + default = 3600 } \ No newline at end of file diff --git a/modules/nginx_config/outputs.tf b/modules/nginx_config/outputs.tf index daa06ed..61539a1 100644 --- a/modules/nginx_config/outputs.tf +++ b/modules/nginx_config/outputs.tf @@ -1,11 +1,11 @@ output "internal_access_list_id" { description = "ID of the internal access list" value = nginxproxymanager_access_list.internal_access.id - + } output "cloudflare_access_list_id" { description = "ID of the Cloudflare access list" value = nginxproxymanager_access_list.cloudflare_access.id - + } \ No newline at end of file diff --git a/modules/oauth_auth/main.tf b/modules/oauth_auth/main.tf new file mode 100644 index 0000000..1421074 --- /dev/null +++ b/modules/oauth_auth/main.tf @@ -0,0 +1,8 @@ +terraform { + required_providers { + authentik = { + source = "goauthentik/authentik" + version = "2025.4.0" + } + } +} \ No newline at end of file diff --git a/modules/oauth_auth/outputs.tf b/modules/oauth_auth/outputs.tf new file mode 100644 index 0000000..1e24c03 --- /dev/null +++ b/modules/oauth_auth/outputs.tf @@ -0,0 +1,9 @@ +output "client_id" { + description = "Shared client ID for the OAuth2 provider" + value = authentik_provider_oauth2.name.client_id +} + +output "client_secret" { + description = "Shared client secret for the OAuth2 provider" + value = authentik_provider_oauth2.name.client_secret +} \ No newline at end of file diff --git a/modules/oauth_auth/policy.tf b/modules/oauth_auth/policy.tf new file mode 100644 index 0000000..0dd838a --- /dev/null +++ b/modules/oauth_auth/policy.tf @@ -0,0 +1,18 @@ +data "authentik_group" "access_group" { + count = var.access_group == null ? 0 : 1 + name = var.access_group_name +} + +# Create a policy for the specified group +resource "authentik_policy_group" "access_policy" { + count = var.access_group == null ? 0 : 1 + name = "${var.name}-group-policy" + group = data.authentik_group.access_group[0].id +} + +resource "authentik_policy_binding" "app_binding" { + count = var.access_group == null ? 0 : 1 + target = authentik_application.name.uuid + policy = authentik_policy_group.access_policy[0].id + order = 0 +} \ No newline at end of file diff --git a/modules/oauth_auth/service.tf b/modules/oauth_auth/service.tf new file mode 100644 index 0000000..8afef9f --- /dev/null +++ b/modules/oauth_auth/service.tf @@ -0,0 +1,34 @@ +resource "random_string" "example" { + length = 16 + special = false + upper = true + lower = true + numeric = true + override_special = "!@#$%^&*" +} + +data "authentik_flow" "default-authorization-flow" { + slug = "default-provider-authorization-implicit-consent" +} + +data "authentik_flow" "default-invalidation-flow" { + slug = "default-invalidation-flow" +} + +# Create an OAuth2 Provider + +resource "authentik_provider_oauth2" "name" { + name = lower(replace(var.name, " ", "-")) + client_id = random_string.example.result + authorization_flow = authentik_flow.default-authorization-flow.id + invalidation_flow = authentik_flow.default-invalidation-flow.id + allowed_redirect_uris = var.redirect_uris +} + +resource "authentik_application" "name" { + name = var.name + meta_description = var.description + group = var.group + slug = lower(replace(var.name, " ", "-")) + protocol_provider = authentik_provider_oauth2.name.id +} \ No newline at end of file diff --git a/modules/oauth_auth/variables.tf b/modules/oauth_auth/variables.tf new file mode 100644 index 0000000..5f9a9c4 --- /dev/null +++ b/modules/oauth_auth/variables.tf @@ -0,0 +1,53 @@ +variable "internal_host" { + description = "If true, the application is only accessible internally" + type = bool +} + +variable "external_host" { + description = "If true, the application is only accessible internally" + type = bool +} + +variable "name" { + description = "Name of the application" + type = string +} + +variable "description" { + description = "Description of the application" + type = string + default = "" +} + +variable "group" { + description = "Group to assign the application to" + type = string + default = "" +} + +variable "access_group" { + description = "Group to assign access to the application" + type = string + default = "" +} + +variable "username_attribute" { + description = "The attribute to use for the username in basic auth" + type = string + default = "username" +} + +variable "password_attribute" { + description = "The attribute to use for the password in basic auth" + type = string + default = "password" +} + +variable "redirect_uris" { + description = "List of redirect URIs for the OAuth2 provider" + type = list(map(string)) + default = [ + "https://example.com/callback", + "http://localhost:3000/callback" + ] +} \ No newline at end of file diff --git a/modules/proxy_auth/main.tf b/modules/proxy_auth/main.tf new file mode 100644 index 0000000..1421074 --- /dev/null +++ b/modules/proxy_auth/main.tf @@ -0,0 +1,8 @@ +terraform { + required_providers { + authentik = { + source = "goauthentik/authentik" + version = "2025.4.0" + } + } +} \ No newline at end of file diff --git a/modules/proxy_auth/policy.tf b/modules/proxy_auth/policy.tf new file mode 100644 index 0000000..0dd838a --- /dev/null +++ b/modules/proxy_auth/policy.tf @@ -0,0 +1,18 @@ +data "authentik_group" "access_group" { + count = var.access_group == null ? 0 : 1 + name = var.access_group_name +} + +# Create a policy for the specified group +resource "authentik_policy_group" "access_policy" { + count = var.access_group == null ? 0 : 1 + name = "${var.name}-group-policy" + group = data.authentik_group.access_group[0].id +} + +resource "authentik_policy_binding" "app_binding" { + count = var.access_group == null ? 0 : 1 + target = authentik_application.name.uuid + policy = authentik_policy_group.access_policy[0].id + order = 0 +} \ No newline at end of file diff --git a/modules/proxy_auth/service.tf b/modules/proxy_auth/service.tf new file mode 100644 index 0000000..4b60f50 --- /dev/null +++ b/modules/proxy_auth/service.tf @@ -0,0 +1,23 @@ +# Create a proxy provider + +data "authentik_flow" "default-authorization-flow" { + slug = "default-provider-authorization-implicit-consent" +} + +resource "authentik_provider_proxy" "name" { + name = lower(replace(var.name, " ", "-")) + internal_host = var.internal_host + external_host = var.external_host + basic_auth_password_attribute = var.password_attribute + basic_auth_username_attribute = var.username_attribute + basic_auth_enabled = true + authorization_flow = data.authentik_flow.default-authorization-flow.id +} + +resource "authentik_application" "name" { + name = var.name + meta_description = var.description + group = var.group + slug = lower(replace(var.name, " ", "-")) + protocol_provider = authentik_provider_proxy.name.id +} \ No newline at end of file diff --git a/modules/proxy_auth/variables.tf b/modules/proxy_auth/variables.tf new file mode 100644 index 0000000..a6d6395 --- /dev/null +++ b/modules/proxy_auth/variables.tf @@ -0,0 +1,44 @@ +variable "internal_host" { + description = "If true, the application is only accessible internally" + type = bool +} + +variable "external_host" { + description = "If true, the application is only accessible internally" + type = bool +} + +variable "name" { + description = "Name of the application" + type = string +} + +variable "description" { + description = "Description of the application" + type = string + default = "" +} + +variable "group" { + description = "Group to assign the application to" + type = string + default = "" +} + +variable "access_group" { + description = "Group to assign access to the application" + type = string + default = "" +} + +variable "username_attribute" { + description = "The attribute to use for the username in basic auth" + type = string + default = "username" +} + +variable "password_attribute" { + description = "The attribute to use for the password in basic auth" + type = string + default = "password" +} \ No newline at end of file From d16be723854ec2f088fd7914c19a9207d211743c Mon Sep 17 00:00:00 2001 From: Ernest Mallett Date: Tue, 10 Jun 2025 11:36:15 -0500 Subject: [PATCH 5/6] Updated ReadMe.md --- ReadMe.md | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/ReadMe.md b/ReadMe.md index e356808..c704b5f 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -1,7 +1,62 @@ +# Terraform Providers Repository + +This repository contains configurations and documentation for various Terraform providers. Each provider listed below is used to manage specific resources and services. The repository is structured to help users integrate these providers into their Terraform projects. + ## Providers -https://registry.terraform.io/providers/goauthentik/authentik/latest/docs -https://registry.terraform.io/providers/Sander0542/nginxproxymanager/latest -https://registry.terraform.io/providers/portainer/portainer/latest -https://registry.terraform.io/providers/kevynb/technitium/latest -https://registry.terraform.io/providers/cloudflare/cloudflare/5.4.0/docs/resources/dns_record \ No newline at end of file +Below is a list of the Terraform providers referenced in this repository: + +1. [Authentik Provider](https://registry.terraform.io/providers/goauthentik/authentik/latest/docs) + Manage resources for the Authentik identity provider. + +2. [NGINX Proxy Manager Provider](https://registry.terraform.io/providers/Sander0542/nginxproxymanager/latest) + Manage resources for NGINX Proxy Manager. + +3. [Portainer Provider](https://registry.terraform.io/providers/portainer/portainer/latest) + Manage resources for Portainer, a container management platform. + +4. [Technitium Provider](https://registry.terraform.io/providers/kevynb/technitium/latest) + Manage resources for Technitium DNS Server. + +5. [Cloudflare Provider](https://registry.terraform.io/providers/cloudflare/cloudflare/5.4.0/docs/resources/dns_record) + Manage DNS records and other resources for Cloudflare. + +## Usage + +To use any of the providers listed above, include the corresponding provider block in your Terraform configuration file. Below is an example of how to configure a provider: + +```hcl +provider "cloudflare" { + email = "your-email@example.com" + api_key = "your-api-key" +} +``` + +Refer to the official documentation linked above for detailed usage instructions for each provider. + +### Prerequisites +Before using this repository, ensure you have the following installed: + +- Terraform (latest version recommended) +- Access credentials for the services you intend to manage (e.g., API keys, tokens, etc.) + +### Getting Started +1. Clone this repository: + +```shell +git clone +cd +``` + +2. Initialize Terraform: + +```shell +terraform init +``` + +3. Customize the configuration files to suit your environment. +4. Apply the configuration: + +```shell +terraform apply +``` \ No newline at end of file From 27f44faea1a6604998d676ad46616e67499ab23f Mon Sep 17 00:00:00 2001 From: Ernest Mallett Date: Wed, 11 Jun 2025 01:30:36 -0500 Subject: [PATCH 6/6] Cleanup --- modules/dns/cloudflare.tf | 4 ++-- modules/dns/nginxproxy.tf | 2 +- modules/dns/technitium.tf | 12 ++++++------ modules/nginx_config/main.tf | 2 +- modules/nginx_config/providers.tf | 8 ++++++++ modules/oauth_auth/variables.tf | 2 +- 6 files changed, 19 insertions(+), 11 deletions(-) create mode 100644 modules/nginx_config/providers.tf diff --git a/modules/dns/cloudflare.tf b/modules/dns/cloudflare.tf index f70b208..5974e00 100644 --- a/modules/dns/cloudflare.tf +++ b/modules/dns/cloudflare.tf @@ -1,4 +1,4 @@ -resource "cloudflare_dns_record" "example_dns_record" { +resource "cloudflare_dns_record" "ipv4_dns_record" { count = var.internal_only ? 0 : var.enable_ipv4 ? 1 : 0 zone_id = var.zone_id comment = "Managed via terraform" @@ -9,7 +9,7 @@ resource "cloudflare_dns_record" "example_dns_record" { type = "A" } -resource "cloudflare_dns_record" "example_dns_record" { +resource "cloudflare_dns_record" "ipv6_dns_record" { count = var.internal_only ? 0 : var.enable_ipv6 ? 1 : 0 zone_id = var.zone_id comment = "Managed via terraform" diff --git a/modules/dns/nginxproxy.tf b/modules/dns/nginxproxy.tf index 399b050..d995342 100644 --- a/modules/dns/nginxproxy.tf +++ b/modules/dns/nginxproxy.tf @@ -14,7 +14,7 @@ resource "nginxproxymanager_certificate_letsencrypt" "certificate" { } data "nginxproxymanager_access_list" "access_list" { - id = var.internal_only ? nginxproxymanager_access_list.internal_access.id : nginxproxymanager_access_list.cloudflare_access.id + id = var.internal_only ? module.nginx.outputs.internal_access_list_id : module.nginx.outputs.cloudflare_access_list_id } resource "nginxproxymanager_proxy_host" "host" { diff --git a/modules/dns/technitium.tf b/modules/dns/technitium.tf index f048f62..1be06df 100644 --- a/modules/dns/technitium.tf +++ b/modules/dns/technitium.tf @@ -1,15 +1,15 @@ -resource "technitium_record" "my_cname" { - count = var.enable_ipv4 ? 1 : 0 - zone = var.zone_name +resource "technitium_record" "ipv4_dns_record" { + count = var.enable_ipv4 ? 1 : 0 + #zone = var.zone_name domain = var.domain_name type = "A" ip_address = var.internal_host_ipv4 ttl = var.ttl } -resource "technitium_record" "my_cname" { - count = var.enable_ipv6 ? 1 : 0 - zone = var.zone_name +resource "technitium_record" "ipv6_dns_record" { + count = var.enable_ipv6 ? 1 : 0 + #zone = var.zone_name domain = var.domain_name type = "AAAA" ip_address = var.internal_host_ipv6 diff --git a/modules/nginx_config/main.tf b/modules/nginx_config/main.tf index 8a86c0c..c2c4abd 100644 --- a/modules/nginx_config/main.tf +++ b/modules/nginx_config/main.tf @@ -24,7 +24,7 @@ resource "nginxproxymanager_access_list" "internal_access" { satisfy_any = true } -resource "nginxproxymanager_access_list" "internal_access" { +resource "nginxproxymanager_access_list" "cloudflare_access" { name = "Allow Cloudflare Access Only" access = [ diff --git a/modules/nginx_config/providers.tf b/modules/nginx_config/providers.tf new file mode 100644 index 0000000..7bb4c29 --- /dev/null +++ b/modules/nginx_config/providers.tf @@ -0,0 +1,8 @@ +terraform { + required_providers { + nginxproxymanager = { + source = "Sander0542/nginxproxymanager" + version = "1.1.1" + } + } +} \ No newline at end of file diff --git a/modules/oauth_auth/variables.tf b/modules/oauth_auth/variables.tf index 5f9a9c4..3cad301 100644 --- a/modules/oauth_auth/variables.tf +++ b/modules/oauth_auth/variables.tf @@ -45,7 +45,7 @@ variable "password_attribute" { variable "redirect_uris" { description = "List of redirect URIs for the OAuth2 provider" - type = list(map(string)) + type = list(string) default = [ "https://example.com/callback", "http://localhost:3000/callback"