diff options
author | Florian Klink <flokli@flokli.de> | 2019-09-07 12:52:44 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-09-07 12:52:44 -0700 |
commit | 2f3b9cd52cf501c81bc92d2ea5c65547198defa9 (patch) | |
tree | 5c5dda422cbeb84c7aa5cdb91c257459bd7a3496 /nixos/lib/utils.nix | |
parent | 493e51deadfd6f27e6fc3c6949c5e9a048fde5d6 (diff) | |
parent | 240649a5100fcb5ea6f18bc5bc87acc3ce216646 (diff) |
Merge pull request #66274 from talyz/gitlab
nixos/gitlab: Add support for secure secrets and more
Diffstat (limited to 'nixos/lib/utils.nix')
-rw-r--r-- | nixos/lib/utils.nix | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/nixos/lib/utils.nix b/nixos/lib/utils.nix index 3297cf06108b7..6ab4c3927955b 100644 --- a/nixos/lib/utils.nix +++ b/nixos/lib/utils.nix @@ -24,4 +24,116 @@ pkgs: with pkgs.lib; throw "${shell} is not a shell package" else shell; + + /* Recurse into a list or an attrset, searching for attrs named like + the value of the "attr" parameter, and return an attrset where the + names are the corresponding jq path where the attrs were found and + the values are the values of the attrs. + + Example: + recursiveGetAttrWithJqPrefix { + example = [ + { + irrelevant = "not interesting"; + } + { + ignored = "ignored attr"; + relevant = { + secret = { + _secret = "/path/to/secret"; + }; + }; + } + ]; + } "_secret" -> { ".example[1].relevant.secret" = "/path/to/secret"; } + */ + recursiveGetAttrWithJqPrefix = item: attr: + let + recurse = prefix: item: + if item ? ${attr} then + nameValuePair prefix item.${attr} + else if isAttrs item then + map (name: recurse (prefix + "." + name) item.${name}) (attrNames item) + else if isList item then + imap0 (index: item: recurse (prefix + "[${toString index}]") item) item + else + []; + in listToAttrs (flatten (recurse "" item)); + + /* Takes an attrset and a file path and generates a bash snippet that + outputs a JSON file at the file path with all instances of + + { _secret = "/path/to/secret" } + + in the attrset replaced with the contents of the file + "/path/to/secret" in the output JSON. + + When a configuration option accepts an attrset that is finally + converted to JSON, this makes it possible to let the user define + arbitrary secret values. + + Example: + If the file "/path/to/secret" contains the string + "topsecretpassword1234", + + genJqSecretsReplacementSnippet { + example = [ + { + irrelevant = "not interesting"; + } + { + ignored = "ignored attr"; + relevant = { + secret = { + _secret = "/path/to/secret"; + }; + }; + } + ]; + } "/path/to/output.json" + + would generate a snippet that, when run, outputs the following + JSON file at "/path/to/output.json": + + { + "example": [ + { + "irrelevant": "not interesting" + }, + { + "ignored": "ignored attr", + "relevant": { + "secret": "topsecretpassword1234" + } + } + ] + } + */ + genJqSecretsReplacementSnippet = genJqSecretsReplacementSnippet' "_secret"; + + # Like genJqSecretsReplacementSnippet, but allows the name of the + # attr which identifies the secret to be changed. + genJqSecretsReplacementSnippet' = attr: set: output: + let + secrets = recursiveGetAttrWithJqPrefix set attr; + in '' + if [[ -h '${output}' ]]; then + rm '${output}' + fi + '' + + concatStringsSep + "\n" + (imap1 (index: name: "export secret${toString index}=$(<'${secrets.${name}}')") + (attrNames secrets)) + + "\n" + + "${pkgs.jq}/bin/jq >'${output}' '" + + concatStringsSep + " | " + (imap1 (index: name: ''${name} = $ENV.secret${toString index}'') + (attrNames secrets)) + + '' + ' <<'EOF' + ${builtins.toJSON set} + EOF + ''; } |