Skip to content

Commit

Permalink
update secret contract (#311)
Browse files Browse the repository at this point in the history
This makes the secret contract better (IMNSHO):

- Improves documentation, explains better the reasoning behind the
contract.
- Makes it easier to create an option implementing the secret contract.
  • Loading branch information
ibizaman authored Oct 1, 2024
1 parent fb89064 commit 5a0ae36
Show file tree
Hide file tree
Showing 11 changed files with 280 additions and 168 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
- `shb.authelia.oidcClients.secret` -> `shb.authelia.oidcClients.client_secret`
- `shb.authelia.ldapEndpoint` -> `shb.authelia.ldapHostname` and `shb.authelia.ldapPort`
- Make Nextcloud automatically disable maintenance mode upon service restart.
- `shb.ldap.ldapUserPasswordFile` -> `shb.ldap.ldapUserPassword.result.path`
- `shb.ldap.jwtSecretFile` -> `shb.ldap.jwtSecret.result.path`

## User Facing Backwards Compatible Changes

Expand Down
50 changes: 14 additions & 36 deletions modules/blocks/ldap.nix
Original file line number Diff line number Diff line change
Expand Up @@ -47,42 +47,20 @@ in
default = 17170;
};

ldapUserPasswordFile = lib.mkOption {
type = lib.types.path;
description = "File containing the LDAP admin user password.";
};

jwtSecretFile = lib.mkOption {
type = lib.types.path;
description = "File containing the JWT secret.";
ldapUserPassword = contracts.secret.mkOption {
description = "LDAP admin user secret.";
mode = "0440";
owner = "lldap";
group = "lldap";
restartUnits = [ "lldap.service" ];
};

secret = {
ldapUserPasswordFile = lib.mkOption {
type = contracts.secret;
description = ''
Secret configuration for the file containing the LDAP admin user password.
'';
default = {
mode = "0440";
owner = "lldap";
group = "lldap";
restartUnits = [ "lldap.service" ];
};
};

jwtSecretFile = lib.mkOption {
type = contracts.secret;
description = ''
Secret configuration for the file containing the JWT secret.
'';
default = {
mode = "0440";
owner = "lldap";
group = "lldap";
restartUnits = [ "lldap.service" ];
};
};
jwtSecret = contracts.secret.mkOption {
description = "JWT secret.";
mode = "0440";
owner = "lldap";
group = "lldap";
restartUnits = [ "lldap.service" ];
};

restrictAccessIPRange = lib.mkOption {
Expand Down Expand Up @@ -174,8 +152,8 @@ in
enable = true;

environment = {
LLDAP_JWT_SECRET_FILE = toString cfg.jwtSecretFile;
LLDAP_LDAP_USER_PASS_FILE = toString cfg.ldapUserPasswordFile;
LLDAP_JWT_SECRET_FILE = toString cfg.jwtSecret.result.path;
LLDAP_LDAP_USER_PASS_FILE = toString cfg.ldapUserPassword.result.path;

RUST_LOG = lib.mkIf cfg.debug "debug";
};
Expand Down
127 changes: 95 additions & 32 deletions modules/contracts/secret.nix
Original file line number Diff line number Diff line change
@@ -1,38 +1,101 @@
{ lib, ... }:
lib.types.submodule {
freeformType = lib.types.anything;

options = {
mode = lib.mkOption {
description = ''
Mode of the secret file.
'';
type = lib.types.str;
default = "0400";
};
{
mkOption =
{ description,
mode ? "0400",
owner ? "root",
group ? "root",
restartUnits ? [],
}: lib.mkOption {
inherit description;

owner = lib.mkOption {
description = ''
Linux user owning the secret file.
'';
type = lib.types.str;
default = "root";
};
type = lib.types.submodule {
options = {
request = lib.mkOption {
default = {
inherit mode owner group restartUnits;
};

group = lib.mkOption {
description = ''
Linux group owning the secret file.
'';
type = lib.types.str;
default = "root";
};
readOnly = true;

description = ''
Options set by the requester module
enforcing some properties the secret should have.
Use the `contracts.secret.mkOption` function to
create a secret option for a requester module.
See the [requester usage section](contracts-secret.html#secret-contract-usage-requester) for an example.
Some providers will need more options to be defined and this is allowed.
These extra options will be set by the user.
For example, the `sops` implementation requires to be given
the sops key in which the secret is encrypted.
`request` options are set read-only
because they must be set through option defaults,
they shouldn't be changed in the `config` section.
This would otherwise lead to infinite recursion
during evaluation.
This is handled automatically when using the `contracts.secret.mkOption` function.
'';
type = lib.types.submodule {
freeformType = lib.types.anything;

options = {
mode = lib.mkOption {
description = ''
Mode of the secret file.
'';
type = lib.types.str;
default = mode;
};

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

group = lib.mkOption {
description = ''
Linux group owning the secret file.
'';
type = lib.types.str;
default = group;
};

restartUnits = lib.mkOption {
description = ''
Systemd units to restart after the secret is updated.
'';
type = lib.types.listOf lib.types.str;
default = restartUnits;
};
};
};
};

result = lib.mkOption {
description = ''
Options set by the provider module that indicates where the secret can be found.
'';
type = lib.types.submodule {
options = {
path = lib.mkOption {
type = lib.types.path;
description = ''
Path to the file containing the secret generated out of band.
restartUnits = lib.mkOption {
description = ''
Systemd units to restart after the secret is updated.
'';
type = lib.types.listOf lib.types.str;
default = [];
This path will exist after deploying to a target host,
it is not available through the nix store.
'';
};
};
};
};
};
};
};
};
}
Loading

0 comments on commit 5a0ae36

Please sign in to comment.