diff --git a/kubenix-modules/custom/default.nix b/kubenix-modules/custom/default.nix index a1dc536..f5cc500 100644 --- a/kubenix-modules/custom/default.nix +++ b/kubenix-modules/custom/default.nix @@ -2,5 +2,6 @@ imports = [ ./ingress.nix ./longhorn-volume.nix + ./tailscale.nix ]; } diff --git a/kubenix-modules/custom/tailscale.nix b/kubenix-modules/custom/tailscale.nix new file mode 100644 index 0000000..e5b1142 --- /dev/null +++ b/kubenix-modules/custom/tailscale.nix @@ -0,0 +1,91 @@ +{ lib, config, ... }: +let + cfg = config.lab.tailscale; + secretName = "tailscale-auth"; + roleName = "tailscale"; + sidecarContainername = "tailscale-sidecar"; +in +{ + options = with lib.types; { + lab.tailscale = { + enable = lib.mkEnableOption "tailscale"; + + allowedServiceAccounts = lib.mkOption { + type = listOf str; + + description = '' + Allow specified service accounts to manage Tailscale authentication. + ''; + }; + + deploymentsWithSidecarContainers = lib.mkOption { + type = attrsOf (submodule ({ name, ... }: { + options.hostName = lib.mkOption { type = str; }; + })); + }; + }; + }; + + config = + let + mkRoleBinding = name: { + name = "${name}-${roleName}"; + value = { + subjects = [{ + inherit name; + kind = "ServiceAccount"; + }]; + + roleRef = { + kind = "Role"; + name = roleName; + apiGroup = "rbac.authorization.k8s.io"; + }; + }; + }; + + mkSidecarContainer = name: { hostName, ... }: { + spec.template.spec.containers.${sidecarContainername} = { + imagePullPolicy = "Always"; + image = "ghcr.io/tailscale/tailscale:latest"; + + env = { + TS_HOSTNAME.value = hostName; + TS_KUBE_SECRET.value = secretName; + TS_USERSPACE.value = "false"; + TS_DEBUG_FIREWALL_MODE.value = "auto"; + TS_AUTHKEY.valueFrom.secretKeyRef = { + name = secretName; + key = "TS_AUTHKEY"; + optional = true; + }; + }; + + securityContext.capabilities.add = [ "NET_ADMIN" ]; + }; + }; + in + { + kubernetes.resources = lib.mkIf cfg.enable { + secrets.${secretName}.stringData.TS_AUTHKEY = "ref+sops://secrets/kubernetes.yaml#/tailscale/authKey"; + + roles.${roleName}.rules = [ + { + apiGroups = [ "" ]; + resources = [ "secrets" ]; + verbs = [ "create" ]; + } + { + apiGroups = [ "" ]; + resourceNames = [ secretName ]; + resources = [ "secrets" ]; + verbs = [ "get" "update" "patch" ]; + } + ]; + + roleBindings = builtins.listToAttrs (map mkRoleBinding cfg.allowedServiceAccounts); + + deployments = builtins.mapAttrs mkSidecarContainer cfg.deploymentsWithSidecarContainers; + }; + }; +} diff --git a/kubenix-modules/inbucket.nix b/kubenix-modules/inbucket.nix index 5e5b2b3..26676ea 100644 --- a/kubenix-modules/inbucket.nix +++ b/kubenix-modules/inbucket.nix @@ -1,41 +1,6 @@ -{ myLib, ... }: -let - # TODO: make module of this. - tailscaleSecretName = "tailscale-auth"; - inbucketSAName = "inbucket"; -in -{ +{ myLib, ... }: { kubernetes.resources = { - secrets.${tailscaleSecretName}.stringData.TS_AUTHKEY = "ref+sops://secrets/kubernetes.yaml#/tailscale/authKey"; - - roles.tailscale.rules = [ - { - apiGroups = [ "" ]; - resources = [ "secrets" ]; - verbs = [ "create" ]; - } - { - apiGroups = [ "" ]; - resourceNames = [ tailscaleSecretName ]; - resources = [ "secrets" ]; - verbs = [ "get" "update" "patch" ]; - } - ]; - - roleBindings.inbucket-tailscale = { - subjects = [{ - kind = "ServiceAccount"; - name = inbucketSAName; - }]; - - roleRef = { - kind = "Role"; - name = "tailscale"; - apiGroup = "rbac.authorization.k8s.io"; - }; - }; - - serviceAccounts.${inbucketSAName} = { }; + serviceAccounts.inbucket = { }; deployments.inbucket.spec = { selector.matchLabels.app = "inbucket"; @@ -44,7 +9,7 @@ in metadata.labels.app = "inbucket"; spec = { - serviceAccountName = inbucketSAName; + serviceAccountName = "inbucket"; containers = { inbucket = { @@ -57,25 +22,6 @@ in smtp.containerPort = 2500; }; }; - - tailscale-sidecar = { - imagePullPolicy = "Always"; - image = "ghcr.io/tailscale/tailscale:latest"; - - env = { - TS_HOSTNAME.value = "inbucket"; - TS_KUBE_SECRET.value = tailscaleSecretName; - TS_USERSPACE.value = "false"; - TS_DEBUG_FIREWALL_MODE.value = "auto"; - TS_AUTHKEY.valueFrom.secretKeyRef = { - name = tailscaleSecretName; - key = "TS_AUTHKEY"; - optional = true; - }; - }; - - securityContext.capabilities.add = [ "NET_ADMIN" ]; - }; }; }; }; @@ -105,4 +51,10 @@ in }; }; }; + + lab.tailscale = { + enable = true; + allowedServiceAccounts = [ "inbucket" ]; + deploymentsWithSidecarContainers.inbucket.hostName = "inbucket"; + }; }