nixos/mautrix-discord: Fix registration token generation (#451500)
This commit is contained in:
@@ -13,6 +13,7 @@ let
|
||||
|
||||
settingsFile = "${dataDir}/config.yaml";
|
||||
settingsFileUnformatted = format.generate "discord-config-unsubstituted.yaml" cfg.settings;
|
||||
default_token = "This value is generated when generating the registration";
|
||||
in
|
||||
{
|
||||
options = {
|
||||
@@ -415,66 +416,61 @@ in
|
||||
rm -f '${settingsFile}'
|
||||
old_umask=$(umask)
|
||||
umask 0177
|
||||
envsubst \
|
||||
-o '${settingsFile}' \
|
||||
-i '${settingsFileUnformatted}'
|
||||
config_has_tokens=$(yq '.appservice | has("as_token") and has("hs_token")' '${settingsFile}')
|
||||
registration_already_exists=$([[ -f '${registrationFile}' ]] && echo "true" || echo "false")
|
||||
echo "There are tokens in the config: $config_has_tokens"
|
||||
echo "Registration already existed: $registration_already_exists"
|
||||
# tokens not configured from config/environment file, and registration file
|
||||
# is already generated, override tokens in config to make sure they are not lost
|
||||
if [[ $config_has_tokens == "false" && $registration_already_exists == "true" ]]; then
|
||||
echo "Copying as_token, hs_token from registration into configuration"
|
||||
yq -sY '.[0].appservice.as_token = .[1].as_token
|
||||
| .[0].appservice.hs_token = .[1].hs_token
|
||||
| .[0]' '${settingsFile}' '${registrationFile}' \
|
||||
> '${settingsFile}.tmp'
|
||||
|
||||
envsubst -o '${settingsFile}' -i '${settingsFileUnformatted}'
|
||||
|
||||
# Check if config has tokens or uses defaults
|
||||
as_token=$(yq -r '.appservice.as_token' '${settingsFile}')
|
||||
hs_token=$(yq -r '.appservice.hs_token' '${settingsFile}')
|
||||
config_has_tokens=$([[ "$as_token" != "${default_token}" && "$as_token" != "null" && "$hs_token" != "${default_token}" && "$hs_token" != "null" ]] && echo "true" || echo "false")
|
||||
|
||||
if [[ -f '${registrationFile}' ]]; then
|
||||
registration_exists="true"
|
||||
else
|
||||
registration_exists="false"
|
||||
fi
|
||||
|
||||
echo "Config has tokens: $config_has_tokens, Registration exists: $registration_exists"
|
||||
|
||||
# If config has default tokens but registration exists, restore tokens from registration
|
||||
if [[ $config_has_tokens == "false" && $registration_exists == "true" ]]; then
|
||||
echo "Restoring tokens from existing registration"
|
||||
yq -sY '.[0].appservice.as_token = .[1].as_token | .[0].appservice.hs_token = .[1].hs_token | .[0]' \
|
||||
'${settingsFile}' '${registrationFile}' > '${settingsFile}.tmp'
|
||||
mv '${settingsFile}.tmp' '${settingsFile}'
|
||||
fi
|
||||
# make sure --generate-registration does not affect config.yaml
|
||||
|
||||
# If config has default tokens and no registration exists, generate new tokens
|
||||
if [[ $config_has_tokens == "false" && $registration_exists == "false" ]]; then
|
||||
echo "Generating new tokens for first-time setup"
|
||||
# Generate random tokens (64 character alphanumeric strings)
|
||||
new_as_token=$(LC_ALL=C tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 64)
|
||||
new_hs_token=$(LC_ALL=C tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 64)
|
||||
|
||||
# Save generated tokens to config
|
||||
yq -Y ".appservice.as_token = \"$new_as_token\" | .appservice.hs_token = \"$new_hs_token\"" \
|
||||
'${settingsFile}' > '${settingsFile}.tmp'
|
||||
mv '${settingsFile}.tmp' '${settingsFile}'
|
||||
|
||||
# Verify tokens were replaced
|
||||
if [[ $(yq -r '.appservice.as_token' '${settingsFile}') == "${default_token}" ]]; then
|
||||
echo "ERROR: Failed to replace default tokens"
|
||||
exit 1
|
||||
fi
|
||||
echo "Successfully generated and saved new tokens"
|
||||
fi
|
||||
|
||||
# Generate registration file with tokens from config
|
||||
cp '${settingsFile}' '${settingsFile}.tmp'
|
||||
echo "Generating registration file"
|
||||
mautrix-discord \
|
||||
--generate-registration \
|
||||
--config='${settingsFile}.tmp' \
|
||||
--registration='${registrationFile}'
|
||||
mautrix-discord --generate-registration --config='${settingsFile}.tmp' --registration='${registrationFile}'
|
||||
rm '${settingsFile}.tmp'
|
||||
# no tokens configured, and new were just generated by generate registration for first time
|
||||
if [[ $config_has_tokens == "false" && $registration_already_exists == "false" ]]; then
|
||||
echo "Copying newly generated as_token, hs_token from registration into configuration"
|
||||
yq -sY '.[0].appservice.as_token = .[1].as_token
|
||||
| .[0].appservice.hs_token = .[1].hs_token
|
||||
| .[0]' '${settingsFile}' '${registrationFile}' \
|
||||
> '${settingsFile}.tmp'
|
||||
mv '${settingsFile}.tmp' '${settingsFile}'
|
||||
fi
|
||||
# make sure --generate-registration does not affect config.yaml
|
||||
cp '${settingsFile}' '${settingsFile}.tmp'
|
||||
echo "Generating registration file"
|
||||
mautrix-discord \
|
||||
--generate-registration \
|
||||
--config='${settingsFile}.tmp' \
|
||||
--registration='${registrationFile}'
|
||||
rm '${settingsFile}.tmp'
|
||||
# no tokens configured, and new were just generated by generate registration for first time
|
||||
if [[ $config_has_tokens == "false" && $registration_already_exists == "false" ]]; then
|
||||
echo "Copying newly generated as_token, hs_token from registration into configuration"
|
||||
yq -sY '.[0].appservice.as_token = .[1].as_token
|
||||
| .[0].appservice.hs_token = .[1].hs_token
|
||||
| .[0]' '${settingsFile}' '${registrationFile}' \
|
||||
> '${settingsFile}.tmp'
|
||||
mv '${settingsFile}.tmp' '${settingsFile}'
|
||||
fi
|
||||
# Make sure correct tokens are in the registration file
|
||||
if [[ $config_has_tokens == "true" || $registration_already_exists == "true" ]]; then
|
||||
echo "Copying as_token, hs_token from configuration to the registration file"
|
||||
yq -sY '.[1].as_token = .[0].appservice.as_token
|
||||
| .[1].hs_token = .[0].appservice.hs_token
|
||||
| .[1]' '${settingsFile}' '${registrationFile}' \
|
||||
> '${registrationFile}.tmp'
|
||||
mv '${registrationFile}.tmp' '${registrationFile}'
|
||||
fi
|
||||
|
||||
# Ensure registration file has the same tokens as config (mautrix-discord may regenerate them)
|
||||
yq -sY '.[1].as_token = .[0].appservice.as_token | .[1].hs_token = .[0].appservice.hs_token | .[1]' \
|
||||
'${settingsFile}' '${registrationFile}' > '${registrationFile}.tmp'
|
||||
mv '${registrationFile}.tmp' '${registrationFile}'
|
||||
|
||||
umask $old_umask
|
||||
chown :mautrix-discord-registration '${registrationFile}'
|
||||
chmod 640 '${registrationFile}'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{ pkgs, ... }:
|
||||
{ pkgs, lib, ... }:
|
||||
let
|
||||
homeserverUrl = "http://homeserver:8008";
|
||||
in
|
||||
@@ -60,9 +60,8 @@ in
|
||||
displayname = "Discord bridge bot";
|
||||
avatar = "mxc://maunium.net/nIdEykemnwdisvHbpxflpDlC";
|
||||
};
|
||||
# These will be generated automatically
|
||||
as_token = "generate";
|
||||
hs_token = "generate";
|
||||
# Don't override as_token/hs_token - let them use the default placeholder
|
||||
# which will trigger automatic generation
|
||||
|
||||
database = {
|
||||
type = "sqlite3";
|
||||
@@ -86,6 +85,7 @@ in
|
||||
|
||||
environment.systemPackages = [
|
||||
pkgs.nettools
|
||||
pkgs.yq
|
||||
];
|
||||
};
|
||||
|
||||
@@ -156,7 +156,45 @@ in
|
||||
|
||||
with subtest("verify registration file was created"):
|
||||
homeserver.wait_until_succeeds("test -f /var/lib/mautrix-discord/discord-registration.yaml")
|
||||
homeserver.succeed("ls -la /var/lib/mautrix-discord/")
|
||||
|
||||
# Verify tokens were generated and are not default values
|
||||
config_as_token = homeserver.succeed("yq -r '.appservice.as_token' /var/lib/mautrix-discord/config.yaml").strip()
|
||||
config_hs_token = homeserver.succeed("yq -r '.appservice.hs_token' /var/lib/mautrix-discord/config.yaml").strip()
|
||||
reg_as_token = homeserver.succeed("yq -r '.as_token' /var/lib/mautrix-discord/discord-registration.yaml").strip()
|
||||
reg_hs_token = homeserver.succeed("yq -r '.hs_token' /var/lib/mautrix-discord/discord-registration.yaml").strip()
|
||||
|
||||
print(f"Config as_token: {config_as_token[:20]}...")
|
||||
print(f"Config hs_token: {config_hs_token[:20]}...")
|
||||
|
||||
# Verify tokens are not the default placeholder or "generate"
|
||||
assert config_as_token not in ["This value is generated when generating the registration", "generate"], \
|
||||
f"Config as_token was not replaced: {config_as_token}"
|
||||
assert config_hs_token not in ["This value is generated when generating the registration", "generate"], \
|
||||
f"Config hs_token was not replaced: {config_hs_token}"
|
||||
|
||||
# Verify tokens match between config and registration
|
||||
assert config_as_token == reg_as_token, \
|
||||
f"as_token mismatch: config={config_as_token[:20]}... vs reg={reg_as_token[:20]}..."
|
||||
assert config_hs_token == reg_hs_token, \
|
||||
f"hs_token mismatch: config={config_hs_token[:20]}... vs reg={reg_hs_token[:20]}..."
|
||||
|
||||
print("Tokens generated and synchronized correctly")
|
||||
|
||||
with subtest("verify tokens persist after service restart"):
|
||||
# Restart the registration service to simulate rebuild
|
||||
homeserver.succeed("systemctl restart mautrix-discord-registration.service")
|
||||
homeserver.wait_for_unit("mautrix-discord-registration.service")
|
||||
|
||||
# Verify tokens were preserved
|
||||
config_as_token_2 = homeserver.succeed("yq -r '.appservice.as_token' /var/lib/mautrix-discord/config.yaml").strip()
|
||||
config_hs_token_2 = homeserver.succeed("yq -r '.appservice.hs_token' /var/lib/mautrix-discord/config.yaml").strip()
|
||||
|
||||
assert config_as_token_2 == config_as_token, \
|
||||
f"as_token changed after restart: {config_as_token[:20]}... -> {config_as_token_2[:20]}..."
|
||||
assert config_hs_token_2 == config_hs_token, \
|
||||
f"hs_token changed after restart: {config_hs_token[:20]}... -> {config_hs_token_2[:20]}..."
|
||||
|
||||
print("Tokens persisted correctly after restart")
|
||||
|
||||
with subtest("verify bridge connects to homeserver"):
|
||||
# Give the bridge a moment to connect
|
||||
|
||||
Reference in New Issue
Block a user