diff options
author | Vincent Haupert <mail@vincent-haupert.de> | 2022-10-08 01:32:55 +0200 |
---|---|---|
committer | Vincent Haupert <mail@vincent-haupert.de> | 2022-10-08 01:32:55 +0200 |
commit | 941c79b6207fa84612b4170ca3bc04984f3d79fc (patch) | |
tree | d2479cb4cae1fa395c050cfad0083861f47265c4 | |
parent | bcf071d514f012ec8aa6dd6a8d64d1a21c2a9ec0 (diff) |
nixos/github-runner: fix bugs related to `InaccessiblePaths=`
This commit fixes two bugs:
1) When starting a github-runner for the very first time, the
unconfigure script did not copy the `tokenFile` to the state
directory. This case just was not handled so far. As a result, the
runner could not configure. The unit did, however, fail even before
as the state token file is configured as inaccessible for the service
through `InaccessiblePaths=`. As the given path did not exist in the
described case, setting up the unit's namespacing failed.
2) Similarly, the `tokenFile` is also marked as not accessible to the
service user. There are, however, cases where other namespacing
options make the files inaccessible even before `InaccessiblePaths=`
kicks in; thus, they appear as non existing and cause the namespacing
to fail yet again. Prefixing the entry with a `-` causes Systemd to
ignore the entry if it cannot find it. This is the behavior we want.
I also took fixing those bugs as a chance to refactor the unconfigure
script to make it easier to follow.
-rw-r--r-- | nixos/modules/services/continuous-integration/github-runner.nix | 81 |
1 files changed, 50 insertions, 31 deletions
diff --git a/nixos/modules/services/continuous-integration/github-runner.nix b/nixos/modules/services/continuous-integration/github-runner.nix index 9abe13a89af1..2ece75722a1d 100644 --- a/nixos/modules/services/continuous-integration/github-runner.nix +++ b/nixos/modules/services/continuous-integration/github-runner.nix @@ -200,46 +200,65 @@ in ${lines} ''; - currentConfigPath = "$STATE_DIRECTORY/.nixos-current-config.json"; runnerRegistrationConfig = getAttrs [ "name" "tokenFile" "url" "runnerGroup" "extraLabels" "ephemeral" ] cfg; newConfigPath = builtins.toFile "${svcName}-config.json" (builtins.toJSON runnerRegistrationConfig); - newConfigTokenFilename = ".new-token"; + currentConfigPath = "$STATE_DIRECTORY/.nixos-current-config.json"; + newConfigTokenPath= "$STATE_DIRECTORY/.new-token"; + currentConfigTokenPath = "$STATE_DIRECTORY/${currentConfigTokenFilename}"; + runnerCredFiles = [ ".credentials" ".credentials_rsaparams" ".runner" ]; unconfigureRunner = writeScript "unconfigure" '' - differs= - - if [[ "$(ls -A "$STATE_DIRECTORY")" ]]; then - # State directory is not empty - # Set `differs = 1` if current and new runner config differ or if `currentConfigPath` does not exist - ${pkgs.diffutils}/bin/diff -q '${newConfigPath}' "${currentConfigPath}" >/dev/null 2>&1 || differs=1 - # Also trigger a registration if the token content changed - ${pkgs.diffutils}/bin/diff -q \ - "$STATE_DIRECTORY"/${currentConfigTokenFilename} \ - ${escapeShellArg cfg.tokenFile} \ - >/dev/null 2>&1 || differs=1 - # If .credentials does not exist, assume a previous run de-registered the runner on stop (ephemeral mode) - [[ ! -f "$STATE_DIRECTORY/.credentials" ]] && differs=1 - fi - - if [[ -n "$differs" ]]; then - echo "Config has changed, removing old runner state." - # In ephemeral mode, the runner deletes the `.credentials` file after de-registering it with GitHub - [[ -f "$STATE_DIRECTORY/.credentials" ]] && echo "The old runner will still appear in the GitHub Actions UI." \ - "You have to remove it manually." - find "$STATE_DIRECTORY/" -mindepth 1 -delete - + copy_tokens() { # Copy the configured token file to the state dir and allow the service user to read the file - install --mode=666 ${escapeShellArg cfg.tokenFile} "$STATE_DIRECTORY/${newConfigTokenFilename}" + install --mode=666 ${escapeShellArg cfg.tokenFile} "${newConfigTokenPath}" # Also copy current file to allow for a diff on the next start - install --mode=600 ${escapeShellArg cfg.tokenFile} "$STATE_DIRECTORY/${currentConfigTokenFilename}" + install --mode=600 ${escapeShellArg cfg.tokenFile} "${currentConfigTokenPath}" + } + + clean_state() { + find "$STATE_DIRECTORY/" -mindepth 1 -delete + copy_tokens + } + + diff_config() { + changed=0 + + # Check for module config changes + [[ -f "${currentConfigPath}" ]] \ + && ${pkgs.diffutils}/bin/diff -q '${newConfigPath}' "${currentConfigPath}" >/dev/null 2>&1 \ + || changed=1 + + # Also check the content of the token file + [[ -f "${currentConfigTokenPath}" ]] \ + && ${pkgs.diffutils}/bin/diff -q "${currentConfigTokenPath}" ${escapeShellArg cfg.tokenFile} >/dev/null 2>&1 \ + || changed=1 + + # If the config has changed, remove old state and copy tokens + if [[ "$changed" -eq 1 ]]; then + echo "Config has changed, removing old runner state." + echo "The old runner will still appear in the GitHub Actions UI." \ + "You have to remove it manually." + clean_state + fi + } + + if [[ "${optionalString cfg.ephemeral "1"}" ]]; then + # In ephemeral mode, we always want to start with a clean state + clean_state + elif [[ "$(ls -A "$STATE_DIRECTORY")" ]]; then + # There are state files from a previous run; diff them to decide if we need a new registration + diff_config + else + # The state directory is entirely empty which indicates a first start + copy_tokens fi ''; configureRunner = writeScript "configure" '' - if [[ -e "$STATE_DIRECTORY/${newConfigTokenFilename}" ]]; then + if [[ -e "${newConfigTokenPath}" ]]; then echo "Configuring GitHub Actions Runner" args=( @@ -256,7 +275,7 @@ in # If the token file contains a PAT (i.e., it starts with "ghp_"), we have to use the --pat option, # if it is not a PAT, we assume it contains a registration token and use the --token option - token=$(<"$STATE_DIRECTORY/${newConfigTokenFilename}") + token=$(<"${newConfigTokenPath}") if [[ "$token" =~ ^ghp_* ]]; then args+=(--pat "$token") else @@ -271,7 +290,7 @@ in rm -rf "$STATE_DIRECTORY/_diag/" # Cleanup token from config - rm "$STATE_DIRECTORY/${newConfigTokenFilename}" + rm "${newConfigTokenPath}" # Symlink to new config ln -s '${newConfigPath}' "${currentConfigPath}" @@ -305,8 +324,8 @@ in WorkingDirectory = runtimeDir; InaccessiblePaths = [ - # Token file path given in the configuration - cfg.tokenFile + # Token file path given in the configuration, if visible to the service + "-${cfg.tokenFile}" # Token file in the state directory "${stateDir}/${currentConfigTokenFilename}" ]; |