stockholm/krebs/4lib/types.nix

324 lines
7.9 KiB
Nix
Raw Normal View History

2016-02-21 06:39:24 +00:00
{ config, lib, ... }:
2015-07-24 10:23:52 +00:00
with builtins;
2015-07-24 10:23:52 +00:00
with lib;
with types;
let
# Inherited attributes are used in submodules that have their own `config`.
inherit (config.krebs) build users;
in
2015-07-24 10:23:52 +00:00
types // rec {
host = submodule ({ config, ... }: {
2015-07-24 10:23:52 +00:00
options = {
name = mkOption {
type = label;
default = config._module.args.name;
2015-07-24 10:23:52 +00:00
};
cores = mkOption {
type = positive;
};
nets = mkOption {
type = attrsOf net;
default = {};
2015-07-24 10:23:52 +00:00
};
2015-08-13 10:03:59 +00:00
2016-02-19 15:18:28 +00:00
owner = mkOption {
type = user;
default = users.krebs;
2016-02-19 15:18:28 +00:00
};
2015-08-13 20:28:21 +00:00
extraZones = mkOption {
default = {};
# TODO: string is either MX, NS, A or AAAA
type = with types; attrsOf string;
};
2015-09-26 22:22:50 +00:00
2015-07-24 16:36:16 +00:00
secure = mkOption {
type = bool;
default = false;
description = ''
If true, then the host is capable of keeping secret information.
TODO define minimum requirements for secure hosts
'';
};
ssh.pubkey = mkOption {
2016-03-16 00:54:49 +00:00
type = nullOr ssh-pubkey;
default = null;
apply = x:
optionalTrace (x == null && config.owner.name == build.user.name)
"The option `krebs.hosts.${config.name}.ssh.pubkey' is unused."
x;
};
ssh.privkey = mkOption {
2016-03-16 00:54:49 +00:00
type = nullOr ssh-privkey;
default = null;
};
2015-07-24 10:23:52 +00:00
};
});
2015-07-24 10:23:52 +00:00
net = submodule ({ config, ... }: {
options = {
name = mkOption {
type = label;
default = config._module.args.name;
};
2015-07-24 10:23:52 +00:00
via = mkOption {
type = nullOr net;
default = null;
};
addrs = mkOption {
type = listOf addr;
default =
optional (config.ip4 != null) config.ip4.addr ++
optional (config.ip6 != null) config.ip6.addr;
readOnly = true;
2015-07-24 10:23:52 +00:00
};
aliases = mkOption {
# TODO nonEmptyListOf hostname
type = listOf hostname;
default = [];
};
ip4 = mkOption {
type = nullOr (submodule {
options = {
addr = mkOption {
type = addr4;
};
prefix = mkOption ({
type = str; # TODO routing prefix (CIDR)
} // optionalAttrs (config.name == "retiolum") {
default = "10.243.0.0/16";
});
};
});
default = null;
};
ip6 = mkOption {
type = nullOr (submodule {
options = {
addr = mkOption {
type = addr6;
};
prefix = mkOption ({
type = str; # TODO routing prefix (CIDR)
} // optionalAttrs (config.name == "retiolum") {
default = "42::/16";
});
};
});
default = null;
};
ssh = mkOption {
type = submodule {
options = {
port = mkOption {
type = nullOr int;
default = null;
};
};
};
default = {};
2015-07-24 10:23:52 +00:00
};
tinc = mkOption {
type = let net = config; in nullOr (submodule ({ config, ... }: {
2015-07-24 10:23:52 +00:00
options = {
config = mkOption {
type = str;
default = concatStringsSep "\n" (
(optionals (net.via != null)
(map (a: "Address = ${a}") net.via.addrs))
++
(map (a: "Subnet = ${a}") net.addrs)
++
[config.pubkey]
);
2015-07-24 10:23:52 +00:00
};
pubkey = mkOption {
2016-03-16 01:04:22 +00:00
type = tinc-pubkey;
2015-07-24 10:23:52 +00:00
};
};
2015-07-27 00:45:03 +00:00
}));
default = null;
2015-07-24 10:23:52 +00:00
};
};
});
positive = mkOptionType {
name = "positive integer";
check = x: isInt x && x > 0;
merge = mergeOneOption;
};
2016-02-21 04:27:37 +00:00
secret-file = submodule ({ config, ... }: {
options = {
path = mkOption { type = str; };
mode = mkOption { type = str; default = "0400"; };
owner = mkOption {
type = user;
default = config.krebs.users.root;
};
group-name = mkOption {
type = str;
default = "root";
};
2016-02-21 04:27:37 +00:00
source-path = mkOption {
type = str;
default = toString <secrets> + "/${config._module.args.name}";
};
};
});
2015-10-09 12:07:29 +00:00
suffixed-str = suffs:
mkOptionType {
name = "string suffixed by ${concatStringsSep ", " suffs}";
check = x: isString x && any (flip hasSuffix x) suffs;
merge = mergeOneOption;
};
user = submodule ({ config, ... }: {
2015-07-24 18:48:00 +00:00
options = {
home = mkOption {
type = absolute-pathname;
default = "/home/${config.name}";
};
2015-07-24 23:05:14 +00:00
mail = mkOption {
type = str; # TODO retiolum mail address
};
2015-07-24 18:48:00 +00:00
name = mkOption {
2016-02-06 18:37:14 +00:00
type = username;
default = config._module.args.name;
2015-07-24 18:48:00 +00:00
};
pgp.pubkeys = mkOption {
type = attrsOf pgp-pubkey;
default = {};
description = ''
Set of user's PGP public keys.
Modules supporting PGP may use well-known key names to define option
defaults, e.g. using `getAttrDef well-known-name pubkeys`.
'';
};
2015-07-24 18:48:00 +00:00
pubkey = mkOption {
2016-03-16 00:54:49 +00:00
type = nullOr ssh-pubkey;
2016-02-21 06:39:24 +00:00
default = null;
2015-07-24 18:48:00 +00:00
};
2016-02-21 05:56:57 +00:00
uid = mkOption {
type = int;
default = genid config.name;
};
2015-07-24 18:48:00 +00:00
};
});
2015-07-24 18:48:00 +00:00
2016-04-07 18:29:07 +00:00
addr = either addr4 addr6;
addr4 = mkOptionType {
name = "IPv4 address";
check = let
IPv4address = let d = "([1-9]?[0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])"; in
concatMapStringsSep "." (const d) (range 1 4);
2016-04-08 02:38:10 +00:00
in x: match IPv4address x != null;
2016-04-07 18:29:07 +00:00
merge = mergeOneOption;
};
addr6 = mkOptionType {
name = "IPv6 address";
check = let
# TODO check IPv6 address harder
IPv6address = "[0-9a-f.:]+";
in x: match IPv6address x != null;
merge = mergeOneOption;
};
pgp-pubkey = str;
2016-03-16 00:54:49 +00:00
ssh-pubkey = str;
ssh-privkey = submodule {
options = {
bits = mkOption {
type = nullOr (enum ["4096"]);
default = null;
};
path = mkOption {
type = either path str;
apply = x: {
path = toString x;
string = x;
}.${typeOf x};
};
type = mkOption {
type = enum ["rsa" "ed25519"];
default = "ed25519";
};
};
};
2015-12-28 18:43:31 +00:00
2016-03-16 01:04:22 +00:00
tinc-pubkey = str;
2015-12-28 18:43:31 +00:00
krebs.file-location = types.submodule {
options = {
# TODO user
host = mkOption {
type = host;
};
# TODO merge with ssl.privkey.path
path = mkOption {
type = types.either types.path types.str;
apply = x: {
path = toString x;
string = x;
}.${typeOf x};
};
};
};
2016-02-06 18:37:14 +00:00
# RFC952, B. Lexical grammar, <hname>
hostname = mkOptionType {
name = "hostname";
check = x: all label.check (splitString "." x);
merge = mergeOneOption;
};
# RFC952, B. Lexical grammar, <name>
# RFC1123, 2.1 Host Names and Numbers
label = mkOptionType {
name = "label";
# TODO case-insensitive labels
check = x: match "[0-9A-Za-z]([0-9A-Za-z-]*[0-9A-Za-z])?" x != null;
merge = mergeOneOption;
};
2016-02-06 18:37:14 +00:00
# POSIX.12013, 3.278 Portable Filename Character Set
filename = mkOptionType {
name = "POSIX filename";
check = let
filename-chars = stringToCharacters
"-.0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
in s: all (flip elem filename-chars) (stringToCharacters s);
merge = mergeOneOption;
};
# POSIX.12013, 3.2 Absolute Pathname
# TODO normalize slashes
# TODO two slashes
absolute-pathname = mkOptionType {
name = "POSIX absolute pathname";
check = s: pathname.check s && substring 0 1 s == "/";
};
# POSIX.12013, 3.267 Pathname
# TODO normalize slashes
pathname = mkOptionType {
name = "POSIX pathname";
check = s: isString s && all filename.check (splitString "/" s);
};
2016-02-06 18:37:14 +00:00
# POSIX.1-2013, 3.431 User Name
username = mkOptionType {
name = "POSIX username";
check = s: filename.check s && substring 0 1 s != "-";
};
2015-07-24 10:23:52 +00:00
}