From c39c07bf31dc080851377c04352fa06f197f0c1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20Schwarz=C3=A4ugl?= Date: Tue, 4 Nov 2025 12:55:24 +0100 Subject: [PATCH] opkssh: init module --- .../misc/news/2025/11/2025-11-04_13-00-00.nix | 11 ++++ modules/programs/opkssh.nix | 59 +++++++++++++++++++ tests/modules/programs/opkssh/default.nix | 3 + .../programs/opkssh/opkssh-basic-config.nix | 42 +++++++++++++ 4 files changed, 115 insertions(+) create mode 100644 modules/misc/news/2025/11/2025-11-04_13-00-00.nix create mode 100644 modules/programs/opkssh.nix create mode 100644 tests/modules/programs/opkssh/default.nix create mode 100644 tests/modules/programs/opkssh/opkssh-basic-config.nix diff --git a/modules/misc/news/2025/11/2025-11-04_13-00-00.nix b/modules/misc/news/2025/11/2025-11-04_13-00-00.nix new file mode 100644 index 000000000..8ad7e13dd --- /dev/null +++ b/modules/misc/news/2025/11/2025-11-04_13-00-00.nix @@ -0,0 +1,11 @@ +{ + time = "2025-11-04T13:00:00+00:00"; + condition = true; + message = '' + A new module is available: 'programs.opkssh'. + + opkssh is a tool which enables ssh to be used with OpenID Connect allowing SSH access to be managed via identities instead of long-lived SSH keys. It does not replace SSH, but instead generates SSH public keys containing PK Tokens and configures sshd to verify them. These PK Tokens contain standard OpenID Connect ID Tokens. + + This protocol builds on the OpenPubkey which adds user public keys to OpenID Connect without breaking compatibility with existing OpenID Provider. + ''; +} diff --git a/modules/programs/opkssh.nix b/modules/programs/opkssh.nix new file mode 100644 index 000000000..a9d43ea73 --- /dev/null +++ b/modules/programs/opkssh.nix @@ -0,0 +1,59 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + cfg = config.programs.opkssh; + + yamlFormat = pkgs.formats.yaml { }; + +in +{ + meta.maintainers = [ lib.maintainers.swarsel ]; + + options.programs.opkssh = { + enable = lib.mkEnableOption "enable the OpenPubkey SSH client"; + + package = lib.mkPackageOption pkgs "opkssh" { nullable = true; }; + + settings = lib.mkOption { + inherit (yamlFormat) type; + default = { }; + example = lib.literalExpression '' + { + default_provider = "kanidm"; + + providers = [ + { + alias = "kanidm"; + issuer = "https://idm.example.com/oauth2/openid/opkssh"; + client_id = "opkssh"; + scopes = "openid email profile"; + redirect_uris = [ + "http://localhost:3000/login-callback" + "http://localhost:10001/login-callback" + "http://localhost:11110/login-callback" + ]; + }; + ]; + } + ''; + description = '' + Configuration written to {file}`$HOME/.opk/config.yml`. + See . + ''; + }; + }; + + config = lib.mkIf cfg.enable { + home.packages = lib.mkIf (cfg.package != null) [ cfg.package ]; + + home.file."${config.home.homeDirectory}/.opk/config.yml" = lib.mkIf (cfg.settings != { }) { + source = yamlFormat.generate "opkssh-config-${config.home.username}.yml" cfg.settings; + }; + + }; +} diff --git a/tests/modules/programs/opkssh/default.nix b/tests/modules/programs/opkssh/default.nix new file mode 100644 index 000000000..9c6be4912 --- /dev/null +++ b/tests/modules/programs/opkssh/default.nix @@ -0,0 +1,3 @@ +{ + opkssh-basic-config = ./opkssh-basic-config.nix; +} diff --git a/tests/modules/programs/opkssh/opkssh-basic-config.nix b/tests/modules/programs/opkssh/opkssh-basic-config.nix new file mode 100644 index 000000000..a15263b47 --- /dev/null +++ b/tests/modules/programs/opkssh/opkssh-basic-config.nix @@ -0,0 +1,42 @@ +_: { + programs.opkssh = { + enable = true; + settings = { + default_provider = "test-provider"; + providers = [ + { + alias = "test-provider"; + issuer = "https://test.domain/oauth2/openid/opkssh"; + client_id = "opkssh"; + scopes = "openid email profile"; + redirect_uris = [ + "http://localhost:3000/login-callback" + "http://localhost:10001/login-callback" + "http://localhost:11110/login-callback" + ]; + } + ]; + }; + }; + + nmt.script = '' + configFile=home-files/.opk/config.yml + + assertFileExists "$configFile" + + configFileNormalized="$(normalizeStorePaths "$configFile")" + + assertFileContent "$configFileNormalized" ${builtins.toFile "expected.service" '' + default_provider: test-provider + providers: + - alias: test-provider + client_id: opkssh + issuer: https://test.domain/oauth2/openid/opkssh + redirect_uris: + - http://localhost:3000/login-callback + - http://localhost:10001/login-callback + - http://localhost:11110/login-callback + scopes: openid email profile + ''} + ''; +}