matrix-synapse: add automatic user creation
All checks were successful
buildbot/nix-build .#checks.aarch64-darwin.nixos-test_install_machine Build done.
buildbot/nix-build .#checks.aarch64-darwin.nixos-flash-installer Build done.
buildbot/nix-build .#checks.aarch64-darwin.nixos-iso-installer Build done.
buildbot/nix-build .#checks.aarch64-linux.nixos-test_install_machine Build done.
buildbot/nix-build .#checks.aarch64-linux.nixos-flash-installer Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-app-no-breakpoints Build done.
buildbot/nix-build .#checks.x86_64-linux.check-for-breakpoints Build done.
buildbot/nix-build .#checks.aarch64-darwin.nixos-test-backup Build done.
buildbot/nix-build .#checks.x86_64-linux.package-gui-installer-apk Build done.
buildbot/nix-build .#checks.x86_64-linux.package-gui-installer-archlinux Build done.
buildbot/nix-build .#checks.x86_64-linux.devShell-docs Build done.
buildbot/nix-build .#checks.x86_64-linux.package-gui-installer-rpm Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-age Build done.
buildbot/nix-build .#checks.x86_64-linux.nixos-test-backup Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-bash Build done.
buildbot/nix-build .#checks.x86_64-linux.package-module-docs Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-e2fsprogs Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-fakeroot Build done.
buildbot/nix-build .#checks.x86_64-linux.renderClanOptions Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-git Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-nix Build done.
buildbot/nix-build .#checks.aarch64-linux.nixos-test-backup Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-openssh Build done.
buildbot/nix-build .#checks.x86_64-linux."clan-dep-python3.11-mypy" Build done.
buildbot/nix-build .#checks.x86_64-linux."clan-dep-python3.11-qemu" Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-rsync Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-sops Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-sshpass Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-tor Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-zbar Build done.
buildbot/nix-build .#checks.x86_64-linux.package-gui-installer-deb Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-pytest-without-core Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-app-pytest Build done.
buildbot/nix-build .#checks.aarch64-linux.nixos-iso-installer Build done.
buildbot/nix-build .#checks.x86_64-linux.devShell-clan-cli Build done.
buildbot/nix-build .#checks.x86_64-linux.devShell-clan-app Build done.
buildbot/nix-build .#checks.x86_64-linux.devShell-webview-ui Build done.
buildbot/nix-build .#checks.x86_64-linux.container Build done.
buildbot/nix-build .#checks.x86_64-linux.lib-jsonschema-example-valid Build done.
buildbot/nix-build .#checks.x86_64-linux.devShell-default Build done.
buildbot/nix-build .#checks.x86_64-linux.deltachat Build done.
buildbot/nix-build .#checks.x86_64-linux.borgbackup Build done.
buildbot/nix-build .#checks.x86_64-linux.package-clan-app Build done.
buildbot/nix-build .#checks.x86_64-linux.package-clan-cli-docs Build done.
buildbot/nix-build .#checks.x86_64-linux.package-clan-ts-api Build done.
buildbot/nix-build .#checks.x86_64-linux.package-default Build done.
buildbot/nix-build .#checks.x86_64-linux.treefmt Build done.
buildbot/nix-build .#checks.x86_64-linux.matrix-synapse Build done.
buildbot/nix-build .#checks.x86_64-linux.package-editor Build done.
buildbot/nix-build .#checks.x86_64-linux.package-clan-cli Build done.
buildbot/nix-build .#checks.x86_64-linux.package-impure-checks Build done.
buildbot/nix-build .#checks.x86_64-linux.package-merge-after-ci Build done.
buildbot/nix-build .#checks.x86_64-linux.nixos-test_install_machine Build done.
buildbot/nix-build .#checks.x86_64-linux.module-schema Build done.
buildbot/nix-build .#checks.x86_64-linux.lib-jsonschema-nix-unit-tests Build done.
buildbot/nix-build .#checks.x86_64-linux.package-pending-reviews Build done.
buildbot/nix-build .#checks.x86_64-linux.package-docs Build done.
buildbot/nix-build .#checks.x86_64-linux.package-zerotier-members Build done.
buildbot/nix-build .#checks.x86_64-linux.package-tea-create-pr Build done.
buildbot/nix-build .#checks.x86_64-linux.package-zt-tcp-relay Build done.
buildbot/nix-build .#checks.x86_64-linux.package-zerotierone Build done.
buildbot/nix-build .#checks.x86_64-linux.package-moonlight-sunshine-accept Build done.
buildbot/nix-build .#checks.x86_64-linux.package-function-schema Build done.
buildbot/nix-build .#checks.x86_64-linux.package-webview-ui Build done.
buildbot/nix-build .#checks.x86_64-linux.postgresql Build done.
buildbot/nix-build .#checks.x86_64-linux.package-module-schema Build done.
buildbot/nix-build .#checks.x86_64-linux.nixos-flash-installer Build done.
buildbot/nix-build .#checks.x86_64-linux.nixos-iso-installer Build done.
buildbot/nix-build .#checks.x86_64-linux.secrets Build done.
buildbot/nix-build .#checks.x86_64-linux.package-iso-installer Build done.
buildbot/nix-build .#checks.x86_64-linux.template-minimal Build done.
buildbot/nix-build .#checks.x86_64-linux.wayland-proxy-virtwl Build done.
buildbot/nix-build .#checks.x86_64-linux.zt-tcp-relay Build done.
buildbot/nix-build .#checks.x86_64-linux.syncthing Build done.
buildbot/nix-build .#checks.x86_64-linux.package-deploy-docs Build done.
buildbot/nix-build .#checks.x86_64-linux.package-gui-install-test-ubuntu-22-04 Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-pytest-with-core Build done.
buildbot/nix-build .#checks.x86_64-linux.test-backups Build done.
buildbot/nix-build .#checks.x86_64-linux.flash Build done.
checks / checks-impure (pull_request) Successful in 2m12s
buildbot/nix-build .#checks.x86_64-linux.test-installation Build done.
buildbot/nix-eval Build done.

This commit is contained in:
Jörg Thalheim 2024-06-11 13:15:30 +02:00
parent a6a9f763db
commit bc0e0088a0
3 changed files with 250 additions and 19 deletions

View File

@ -4,7 +4,12 @@
name = "matrix-synapse";
nodes.machine =
{ self, lib, ... }:
{
config,
self,
lib,
...
}:
{
imports = [
self.clanModules.matrix-synapse
@ -12,17 +17,48 @@
{
clanCore.machineName = "machine";
clanCore.clanDir = ./.;
clan.matrix-synapse = {
domain = "clan.test";
};
}
{
# secret override
clanCore.facts.services.matrix-synapse.secret.synapse-registration_shared_secret.path = "${./synapse-registration_shared_secret}";
services.nginx.virtualHosts."matrix.clan.test" = {
enableACME = lib.mkForce false;
forceSSL = lib.mkForce false;
};
clan.matrix-synapse.domain = "clan.test";
clan.matrix-synapse.users.admin.admin = true;
clan.matrix-synapse.users.someuser = { };
clanCore.facts.secretStore = "vm";
# because we use systemd-tmpfiles to copy the secrets, we need to a seperate systemd-tmpfiles call to provison them.
boot.postBootCommands = "${config.systemd.package}/bin/systemd-tmpfiles --create /etc/tmpfiles.d/00-vmsecrets.conf";
systemd.tmpfiles.settings."00-vmsecrets" = {
# run before 00-nixos.conf
"/etc/secrets" = {
d.mode = "0700";
z.mode = "0700";
};
"/etc/secrets/synapse-registration_shared_secret" = {
f.argument = "registration_shared_secret: supersecret";
z = {
mode = "0400";
user = "root";
};
};
"/etc/secrets/matrix-password-admin" = {
f.argument = "matrix-password1";
z = {
mode = "0400";
user = "root";
};
};
"/etc/secrets/matrix-password-someuser" = {
f.argument = "matrix-password2";
z = {
mode = "0400";
user = "root";
};
};
};
}
];
};
@ -31,6 +67,12 @@
machine.wait_for_unit("matrix-synapse")
machine.succeed("${pkgs.netcat}/bin/nc -z -v ::1 8008")
machine.succeed("${pkgs.curl}/bin/curl -Ssf -L http://localhost/_matrix/static/ -H 'Host: matrix.clan.test'")
machine.systemctl("restart matrix-synapse >&2") # check if user creation is idempotent
machine.execute("journalctl -u matrix-synapse --no-pager >&2")
machine.wait_for_unit("matrix-synapse")
machine.succeed("${pkgs.netcat}/bin/nc -z -v ::1 8008")
machine.succeed("${pkgs.curl}/bin/curl -Ssf -L http://localhost/_matrix/static/ -H 'Host: matrix.clan.test'")
'';
}
)

View File

@ -0,0 +1,84 @@
From df45634a92944dcab4edb02fb5e478911c58fdd6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= <joerg@thalheim.io>
Date: Tue, 11 Jun 2024 11:40:47 +0200
Subject: [PATCH] register_new_matrix_user: add password-file flag
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
getpass in python exist on stdin to be a tty, hence we cannot just pipe
into register_new_matrix_user. --password-file instead works better and
it would also allow the use of stdin if /dev/stdin is passed.
Signed-off-by: Jörg Thalheim <joerg@thalheim.io>
---
debian/register_new_matrix_user.ronn | 6 +++++-
synapse/_scripts/register_new_matrix_user.py | 16 ++++++++++++++--
2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/debian/register_new_matrix_user.ronn b/debian/register_new_matrix_user.ronn
index 0410b1f4c..e39bef448 100644
--- a/debian/register_new_matrix_user.ronn
+++ b/debian/register_new_matrix_user.ronn
@@ -32,7 +32,11 @@ A sample YAML file accepted by `register_new_matrix_user` is described below:
* `-p`, `--password`:
New password for user. Will prompt if omitted. Supplying the password
- on the command line is not recommended. Use the STDIN instead.
+ on the command line is not recommended. Use password-file if possible.
+
+ * `--password-file`:
+ File containing the new password for user. Will prompt if omitted.
+ This is a more secure alternative to specifying the password on the command line.
* `-a`, `--admin`:
Register new user as an admin. Will prompt if omitted.
diff --git a/synapse/_scripts/register_new_matrix_user.py b/synapse/_scripts/register_new_matrix_user.py
index 77a7129ee..f067e6832 100644
--- a/synapse/_scripts/register_new_matrix_user.py
+++ b/synapse/_scripts/register_new_matrix_user.py
@@ -173,12 +173,18 @@ def main() -> None:
default=None,
help="Local part of the new user. Will prompt if omitted.",
)
- parser.add_argument(
+ password_group = parser.add_mutually_exclusive_group()
+ password_group.add_argument(
"-p",
"--password",
default=None,
help="New password for user. Will prompt if omitted.",
)
+ password_group.add_argument(
+ "--password-file",
+ default=None,
+ help="File containing the new password for user. Will prompt if omitted.",
+ )
parser.add_argument(
"-t",
"--user_type",
@@ -247,6 +253,12 @@ def main() -> None:
print(_NO_SHARED_SECRET_OPTS_ERROR, file=sys.stderr)
sys.exit(1)
+ password = ""
+ if args.password_file:
+ password = _read_file(args.password_file, "password-file").strip()
+ else:
+ password = args.password
+
if args.server_url:
server_url = args.server_url
elif config is not None:
@@ -270,7 +282,7 @@ def main() -> None:
admin = args.admin
register_new_user(
- args.user, args.password, server_url, secret, admin, args.user_type
+ args.user, password, server_url, secret, admin, args.user_type
)
--
2.44.1

View File

@ -16,16 +16,58 @@ let
> $out/config.json < ${pkgs.element-web}/config.json
ln -s $out/config.json $out/config.${nginx-vhost}.json
'';
# FIXME: This was taken from upstream. Drop this when our patch is upstream
synapseCfg = config.services.matrix-synapse;
wantedExtras =
synapseCfg.extras
++ lib.optional (synapseCfg.settings ? oidc_providers) "oidc"
++ lib.optional (synapseCfg.settings ? jwt_config) "jwt"
++ lib.optional (synapseCfg.settings ? saml2_config) "saml2"
++ lib.optional (synapseCfg.settings ? redis) "redis"
++ lib.optional (synapseCfg.settings ? sentry) "sentry"
++ lib.optional (synapseCfg.settings ? user_directory) "user-search"
++ lib.optional (synapseCfg.settings.url_preview_enabled) "url-preview"
++ lib.optional (synapseCfg.settings.database.name == "psycopg2") "postgres";
in
{
options.services.matrix-synapse.package = lib.mkOption { readOnly = false; };
options.clan.matrix-synapse = {
domain = lib.mkOption {
type = lib.types.str;
description = "The domain name of the matrix server";
example = "example.com";
};
users = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule (
{ name, ... }:
{
options = {
name = lib.mkOption {
type = lib.types.str;
default = name;
description = "The name of the user";
};
admin = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Whether the user should be an admin";
};
};
}
)
);
description = "A list of users. Not that only new users will be created and existing ones are not modified.";
example.alice = {
admin = true;
};
};
};
imports = [
../postgresql
(lib.mkRemovedOptionModule [
"clan"
"matrix-synapse"
@ -36,6 +78,18 @@ in
];
config = {
services.matrix-synapse = {
package = lib.mkForce (
pkgs.matrix-synapse.override {
matrix-synapse-unwrapped = pkgs.matrix-synapse.unwrapped.overrideAttrs (_old: {
doInstallCheck = false; # too slow, nixpkgs maintainer already run this.
# see: https://github.com/element-hq/synapse/pull/17294
patches = [ ./0001-register_new_matrix_user-add-password-file-flag.patch ];
});
extras = wantedExtras;
plugins = synapseCfg.plugins;
}
);
enable = true;
settings = {
server_name = cfg.domain;
@ -70,7 +124,10 @@ in
};
extraConfigFiles = [ "/run/synapse-registration-shared-secret.yaml" ];
};
systemd.tmpfiles.settings."synapse" = {
security.wrappers = lib.mkForce { }; # unsupported in unprivileged containers
systemd.tmpfiles.settings."01-matrix" = {
"/run/synapse-registration-shared-secret.yaml" = {
C.argument =
config.clanCore.facts.services.matrix-synapse.secret.synapse-registration_shared_secret.path;
@ -90,16 +147,64 @@ in
OWNER = "matrix-synapse";
};
clanCore.facts.services."matrix-synapse" = {
secret."synapse-registration_shared_secret" = { };
generator.path = with pkgs; [
coreutils
pwgen
];
generator.script = ''
echo "registration_shared_secret: $(pwgen -s 32 1)" > "$secrets"/synapse-registration_shared_secret
'';
};
clanCore.facts.services =
{
"matrix-synapse" = {
secret."synapse-registration_shared_secret" = { };
generator.path = with pkgs; [
coreutils
pwgen
];
generator.script = ''
echo "registration_shared_secret: $(pwgen -s 32 1)" > "$secrets"/synapse-registration_shared_secret
'';
};
}
// lib.mapAttrs' (
name: user:
lib.nameValuePair "matrix-password-${user.name}" {
secret."matrix-password-${user.name}" = { };
generator.path = with pkgs; [
coreutils
pwgen
];
generator.script = ''
xkcdpass -n 4 -d - > "$secrets"/${lib.escapeShellArg "matrix-password-${user.name}"}
'';
}
) cfg.users;
systemd.services.matrix-synapse =
let
usersScript =
''
while ! ${pkgs.netcat}/bin/nc -z -v ::1 8008; do
if ! kill -0 "$MAINPID"; then exit 1; fi
sleep 1;
done
headers=$(mktemp)
trap 'rm -f "$headers"' EXIT
cat > "$headers" <<EOF
Authorization: Bearer $(cat /run/synapse-registration-shared-secret.yaml| sed -n 's/registration_shared_secret: //p')
EOF
''
+ lib.concatMapStringsSep "\n" (user: ''
# only create user if it doesn't exist
if ! curl --header "$headers" "http://localhost:8008/_synapse/admin/v1/whois/${user.name}@${cfg.domain}" >&2; then
/run/current-system/sw/bin/matrix-synapse-register_new_matrix_user --password-file ${
config.clanCore.facts.services."matrix-password-${user.name}".secret."matrix-password-${user.name}".path
} --user "${user.name}" ${if user.admin then "--admin" else "--no-admin"}
fi
'') (lib.attrValues cfg.users);
in
{
path = [ pkgs.curl ];
serviceConfig.ExecStartPost = [
(''+${pkgs.writeShellScript "matrix-synapse-create-users" usersScript}'')
];
};
services.nginx = {
enable = true;