{ lib, config, ... }: with lib; let # { ldapApps = { appName = { name = str?; group = str?; meta_desc = str?; meta_icon = str?; meta_launch_url = str?; meta_publisher = str?; }; }; oauthApps = { appName = {}; ] }; proxyApps = { appName = { externalHost = ""; }; }; } authorizationFlow = tfRef "data.authentik_flow.default-authorization-flow.id"; authenticationFlow = tfRef "data.authentik_flow.default-authentication-flow.id"; invalidationFlow = tfRef "data.authentik_flow.default-provider-invalidation-flow.id"; genApp = provider: n: v: { protocol_provider = provider; slug = n; inherit (v) name group meta_description meta_icon meta_launch_url meta_publisher ; }; in { options = { stateFile = mkOption { type = types.str; }; oauthApps = mkOption { type = types.attrs; }; proxyApps = mkOption { type = types.attrs; }; ldapApps = mkOption { type = types.attrs; }; url = mkOption { type = types.str; }; insecure = mkOption { type = types.bool; }; }; config = { terraform.backend.local.path = config.stateFile; terraform.required_providers.authentik.source = "goauthentik/authentik"; data.authentik_flow."default-authorization-flow" = { slug = "default-provider-authorization-implicit-consent"; }; data."authentik_flow"."default-authentication-flow" = { slug = "default-authentication-flow"; }; data."authentik_flow"."default-provider-invalidation-flow" = { slug = "default-provider-invalidation-flow"; }; resource.authentik_outpost.proxy = { name = "proxy"; type = "proxy"; protocol_providers = mapAttrsToList ( n: v: (tfRef "resource.authentik_provider_proxy.${n}.id") ) config.proxyApps; }; resource.authentik_outpost.ldap = { name = "ldap"; type = "ldap"; protocol_providers = mapAttrsToList ( n: v: (tfRef "resource.authentik_provider_ldap.${n}.id") ) config.ldapApps; }; resource.authentik_provider_oauth2 = mapAttrs (n: v: { name = n; client_id = n; authorization_flow = authorizationFlow; invalidation_flow = invalidationFlow; }) config.oauthApps; data.authentik_provider_oauth2_config = mapAttrs (n: v: { provider_id = tfRef "resource.authentik_provider_oauth2.${n}.id"; }) config.oauthApps; resource.authentik_provider_proxy = mapAttrs (n: v: { name = n; mode = "forward_single"; external_host = v.externalHost; authorization_flow = authorizationFlow; invalidation_flow = invalidationFlow; }) config.proxyApps; resource.authentik_provider_ldap = mapAttrs (n: v: { name = n; base_dn = "dc=ldap,dc=goauthentik,dc=io"; bind_flow = authenticationFlow; unbind_flow = invalidationFlow; }) config.ldapApps; output = (mapAttrs' ( n: v: nameValuePair ("${n}_environment") ({ sensitive = true; value = let val = val: tfRef "resource.authentik_provider_oauth2.${n}.${val}"; cfgVal = val: tfRef "data.authentik_provider_oauth2_config.${n}.${val}"; in '' CLIENT_ID=${val "client_id"} CLIENT_SECRET=${val "client_secret"} USER_INFO_URL=${cfgVal "user_info_url"} TOKEN_URL=${cfgVal "token_url"} AUTHORIZE_URL=${cfgVal "authorize_url"} ''; }) ) config.oauthApps) // { proxy_config.sensitive = true; proxy_config.value = '' AUTHENTIK_HOST=http://localhost:9000 AUTHENTIK_HOST_BROWSER=${config.url} AUTHENTIK_TOKEN=${tfRef "resource.authentik_token.proxy_outpost.key"} ''; ldap_config.sensitive = true; ldap_config.value = '' AUTHENTIK_HOST=http://localhost:9000 AUTHENTIK_HOST_BROWSER=${config.url} AUTHENTIK_TOKEN=${tfRef "resource.authentik_token.ldap_outpost.key"} ''; }; data.authentik_user."proxy" = { username = "ak-outpost-${tfRef ''replace(resource.authentik_outpost.proxy.id,"-","")''}"; }; data.authentik_user."ldap" = { username = "ak-outpost-${tfRef ''replace(resource.authentik_outpost.ldap.id,"-","")''}"; }; resource.authentik_token."proxy_outpost" = { identifier = "proxy-outpost-token"; user = tfRef "data.authentik_user.proxy.id"; expiring = false; retrieve_key = true; }; resource.authentik_token."ldap_outpost" = { identifier = "ldap-outpost-token"; user = tfRef "data.authentik_user.ldap.id"; expiring = false; retrieve_key = true; }; resource.authentik_application = mkMerge [ (mapAttrs (n: v: genApp (tfRef "authentik_provider_oauth2.${n}.id") n v) config.oauthApps) (mapAttrs (n: v: genApp (tfRef "authentik_provider_proxy.${n}.id") n v) config.proxyApps) (mapAttrs (n: v: genApp (tfRef "authentik_provider_ldap.${n}.id") n v) config.ldapApps) ]; # group stuff resource.authentik_group.admin = { name = "admin"; }; resource.authentik_application_entitlement = let genEnts = apps: mapAttrs (n: v: { name = "${n}-ent"; application = tfRef "authentik_application.${n}.uuid"; }) (filterAttrs (n: v: (builtins.length v.groups) > 0) apps); in mkMerge [ (genEnts config.oauthApps) (genEnts config.proxyApps) (genEnts config.ldapApps) ]; resource.authentik_policy_binding = let genEnts = apps: flatten ( mapAttrsToList ( n: v: (map (g: { "${n}-${g}-access" = { target = tfRef "authentik_application_entitlement.${n}.uuid"; group = tfRef "authentik_group.${g}.id"; order = 0; }; }) v.groups) ) apps ); in mkMerge ((genEnts config.oauthApps) ++ (genEnts config.proxyApps) ++ (genEnts config.ldapApps)); }; }