escape json

This commit is contained in:
Kiara Grouwstra 2025-06-09 22:22:25 +02:00
parent 0fbea43150
commit f027d91bb1
Signed by: kiara
SSH key fingerprint: SHA256:COspvLoLJ5WC5rFb9ZDe5urVCkK4LJZOsjfF4duRJFU
4 changed files with 22 additions and 11 deletions

View file

@ -1,6 +1,6 @@
{ {
inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
outputs = { nixpkgs, ... }@self: let outputs = { nixpkgs, ... }: let
supportedArchitectures = [ supportedArchitectures = [
"aarch64-darwin" "aarch64-darwin"
"aarch64-linux" "aarch64-linux"

20
lib.nix
View file

@ -3,6 +3,12 @@
nix_templater, nix_templater,
lib ? pkgs.lib, lib ? pkgs.lib,
}: }:
let
escapeJson = {
"\"" = ''\"'';
"\\" = ''\\'';
};
in
rec { rec {
# placeholder to be substituted with the content of a secret file # placeholder to be substituted with the content of a secret file
fileContents = file: { fileContents = file: {
@ -11,12 +17,12 @@ rec {
}; };
# make a template with placeholders # make a template with placeholders
templateText = { name, text, outPath }: templateText = { name, text, outPath, translations ? {} }:
pkgs.runCommand name { pkgs.runCommand name {
textBeforeTemplate = text; textBeforeTemplate = text;
script = '' script = ''
#!/bin/sh #!/bin/sh
${nix_templater}/bin/nix_templater ${builtins.placeholder "out"}/template ${builtins.placeholder "nix_template"} "${outPath}" ${nix_templater}/bin/nix_templater ${builtins.placeholder "out"}/template ${builtins.placeholder "nix_template"} "${outPath}" '${lib.strings.toJSON translations}'
''; '';
passAsFile = [ "script" "textBeforeTemplate" ]; passAsFile = [ "script" "textBeforeTemplate" ];
} '' } ''
@ -26,14 +32,14 @@ rec {
chmod +x $out/bin/${name} chmod +x $out/bin/${name}
''; '';
templateGenerator = generator: { name, value, outPath }: templateText { templateGenerator = translations: generator: { name, value, outPath }: templateText {
inherit name outPath; inherit name outPath translations;
text = generator value; text = generator value;
}; };
templateJsonWith = options: templateGenerator (lib.generators.toJSON options); templateJsonWith = options: templateGenerator escapeJson (lib.generators.toJSON options);
templateYamlWith = options: templateGenerator (lib.generators.toYAML options); # just json templateYamlWith = options: templateGenerator escapeJson (lib.generators.toYAML options); # just json
templateIniWith = options: templateGenerator (lib.generators.toINI options); templateIniWith = options: templateGenerator escapeJson (lib.generators.toINI options);
templateJson = templateJsonWith { }; templateJson = templateJsonWith { };
templateYaml = templateYamlWith { }; templateYaml = templateYamlWith { };
templateIni = templateIniWith { }; templateIni = templateIniWith { };

View file

@ -1,10 +1,12 @@
# replace occurrences of a magic string in a template file # replace occurrences of a magic string in a template file
from json import loads
import sys import sys
from pathlib import Path from pathlib import Path
template_file = sys.argv[1] template_file = sys.argv[1]
magic_string = sys.argv[2] magic_string = sys.argv[2]
outfile = sys.argv[3] outfile = sys.argv[3]
translations = loads(sys.argv[4]) if len(sys.argv) >= 4 else {}
if Path(outfile).exists(): if Path(outfile).exists():
print(f"{outfile} already exists, aborting") print(f"{outfile} already exists, aborting")
@ -26,7 +28,7 @@ while True:
] ]
output += template_bytes[loc : loc + magic_start] output += template_bytes[loc : loc + magic_start]
# TODO handle errors better here # TODO handle errors better here
output += Path(magic_file.decode()).read_bytes() output += Path(magic_file.decode()).read_bytes().decode().translate(str.maketrans(translations)).encode()
loc = loc + magic_start + magic_end + len(magic_string) + 1 loc = loc + magic_start + magic_end + len(magic_string) + 1
Path(outfile).write_bytes(output) Path(outfile).write_bytes(output)

View file

@ -1,9 +1,10 @@
# test injecting a secret into a json template # test injecting a secret into a json template
{ legacyPackages, system, nixpkgs }: { legacyPackages, system, nixpkgs }:
let let
secret_file = (nixpkgs.legacyPackages.${system}.writeText "secret" "secret"); hostPkgs = nixpkgs.legacyPackages.${system};
secret_file = hostPkgs.writeText "secret" "secret\\needing\"escaping";
in (nixpkgs.lib.nixos.runTest { in (nixpkgs.lib.nixos.runTest {
hostPkgs = nixpkgs.legacyPackages.${system}; inherit hostPkgs;
name = "nix_templates"; name = "nix_templates";
nodes.machine = {pkgs, ...}: { nodes.machine = {pkgs, ...}: {
@ -33,6 +34,8 @@ in (nixpkgs.lib.nixos.runTest {
start_all() start_all()
print(machine.execute("uname -a")) print(machine.execute("uname -a"))
machine.wait_for_unit("multi-user.target") machine.wait_for_unit("multi-user.target")
print(machine.succeed("cat /test"))
print(machine.succeed("cat /test | grep -q secret")) print(machine.succeed("cat /test | grep -q secret"))
print(machine.succeed("cat /test | ${hostPkgs.jq}/bin/jq"))
''; '';
}) })