summaryrefslogtreecommitdiffstats
path: root/providers/asecret.nix
blob: df7fe20eb9b6061d5b72b2c462a76a82908e2af1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
{ config, lib, pkgs, ... }:
let
  cfg = config.asecret;

  inherit (lib) mapAttrs' mkOption nameValuePair;
  inherit (lib.types) attrsOf nullOr str submodule;
  inherit (pkgs) writeText;
in
{
  options.asecret = mkOption {
    default = {};
    description = ''
      A secret. These should only be used in tests.
    '';

    example = lib.literalExpression ''
    {
      mySecret = {
        secret.input = {
          user = "me";
          mode = "0400";
          restartUnits = [ "myservice.service" ];
        };
        settings.content = "My Secret";
      };
    }
    '';
    type = attrsOf (submodule (mod@{ name, options, ... }: {
      options = {
        mode = mkOption {
          description = ''
            Mode of the secret file.
          '';
          type = str;
          default = "0400";
        };

        owner = mkOption {
          description = ''
            Linux user owning the secret file.
          '';
          type = str;
        };

        group = mkOption {
          description = ''
            Linux group owning the secret file.
          '';
          type = str;
          default = options.user.default;
          defaultText = "user";
        };

        content = mkOption {
          type = nullOr str;
          description = ''
            Content of the secret as a string.

            This will be stored in the nix store and should only be used for testing or maybe in dev.
          '';
          default = null;
        };

        source = mkOption {
          type = nullOr str;
          description = ''
            Source of the content of the secret as a path in the nix store.
          '';
          default = null;
        };

        path = mkOption {
          type = str;
          description = ''
            Path where the secret should be located.
          '';
          default = "/run/hardcodedSecrets/hardcodedSecret_${name}";
        };

        secrets = mkOption {
          type = config.contracts.secrets.provider;
        };
      };

      config = {
        inherit (mod.config.secret.input) mode owner group;
        secret.output.path = mod.config.path;
      };
    }));
  };

  config = {
    system.activationScripts = mapAttrs' (n: cfg':
      let
        source = if cfg'.source != null
                 then cfg'.source
                 else writeText "hardcodedSecret_${n}_content" cfg'.content;
      in
        nameValuePair "hardcodedSecret_${n}" ''
          (
            set -e
            mkdir -p "$(dirname "${cfg'.path}")"
            touch "${cfg'.path}"
            chmod ${cfg'.mode} "${cfg'.path}"
            chown ${cfg'.owner}:${cfg'.group} "${cfg'.path}"
            cp ${source} "${cfg'.path}"
          ) || echo "Failed to create hardcoded secret at ${cfg'.path}"
        ''
    ) cfg;
  };

  # Without `meta.buildDocsInSandbox = false;`, I get:
  #
  #     >        error: attribute 'contracts' missing
  #     >        at /nix/store/2gd9yzcfpqqp00vskxlqq4ds48mpgdzv-nixos/modules/testing/hardcodedSecret.nix:81:18:
  #     >            80|         secret = mkOption {
  #     >            81|           type = config.contracts.secret.provider;
  #     >              |                  ^
  #     >            82|         };
  #     > Cacheable portion of option doc build failed.
  #     > Usually this means that an option attribute that ends up in documentation (eg `default` or `description`) depends on the restricted module arguments `config` or `pkgs`.
  #     >
  #     > Rebuild your configuration with `--show-trace` to find the offending location. Remove the references to restricted arguments (eg by escaping their antiquotations or adding a `defaultText`) or disable the sandboxed build for the failing module by setting `meta.buildDocsInSandbox = false`.
  #
  # With the line, I don't get the warning but still get the missing 'contracts' attribute error.
  meta.buildDocsInSandbox = false;
}