diff options
author | Antoine Eiche <lewo@abesis.fr> | 2016-12-10 23:14:50 +0100 |
---|---|---|
committer | Jörg Thalheim <joerg@higgsboson.tk> | 2016-12-16 20:53:32 +0100 |
commit | a932f68d9c2a020e04b49f225310decf39bb34d0 (patch) | |
tree | d3da8cd0d0ce5439f556f16a1a898d5d45808f0a /nixos/modules/virtualisation/openstack | |
parent | 415c9ff90b4aa9f6452f618e60aa948ab94a93fb (diff) | |
download | nixlib-a932f68d9c2a020e04b49f225310decf39bb34d0.tar nixlib-a932f68d9c2a020e04b49f225310decf39bb34d0.tar.gz nixlib-a932f68d9c2a020e04b49f225310decf39bb34d0.tar.bz2 nixlib-a932f68d9c2a020e04b49f225310decf39bb34d0.tar.lz nixlib-a932f68d9c2a020e04b49f225310decf39bb34d0.tar.xz nixlib-a932f68d9c2a020e04b49f225310decf39bb34d0.tar.zst nixlib-a932f68d9c2a020e04b49f225310decf39bb34d0.zip |
nixos/keystone: secrets can be read from files
A secret can be stored in a file. It is written at runtime in the configuration file. Note it is also possible to write them in the nix store for dev purposes.
Diffstat (limited to 'nixos/modules/virtualisation/openstack')
-rw-r--r-- | nixos/modules/virtualisation/openstack/common.nix | 54 | ||||
-rw-r--r-- | nixos/modules/virtualisation/openstack/keystone.nix | 63 |
2 files changed, 100 insertions, 17 deletions
diff --git a/nixos/modules/virtualisation/openstack/common.nix b/nixos/modules/virtualisation/openstack/common.nix new file mode 100644 index 000000000000..3fce54a2fa59 --- /dev/null +++ b/nixos/modules/virtualisation/openstack/common.nix @@ -0,0 +1,54 @@ +{ lib }: + +with lib; + +rec { + # A shell script string helper to get the value of a secret at + # runtime. + getSecret = secretOption: + if secretOption.storage == "fromFile" + then ''$(cat ${secretOption.value})'' + else ''${secretOption.value}''; + + + # A shell script string help to replace at runtime in a file the + # pattern of a secret by its value. + replaceSecret = secretOption: filename: '' + sed -i "s/${secretOption.pattern}/${getSecret secretOption}/g" ${filename} + ''; + + # This generates an option that can be used to declare secrets which + # can be stored in the nix store, or not. A pattern is written in + # the nix store to represent the secret. The pattern can + # then be overwritten with the value of the secret at runtime. + mkSecretOption = {name, description ? ""}: + mkOption { + description = description; + type = types.submodule ({ + options = { + pattern = mkOption { + type = types.str; + default = "##${name}##"; + description = "The pattern that represent the secret."; + }; + storage = mkOption { + type = types.enum [ "fromNixStore" "fromFile" ]; + description = '' + Choose the way the password is provisionned. If + fromNixStore is used, the value is the password and it is + written in the nix store. If fromFile is used, the value + is a path from where the password will be read at + runtime. This is generally used with <link + xlink:href="https://nixos.org/nixops/manual/#opt-deployment.keys"> + deployment keys</link> of Nixops. + '';}; + value = mkOption { + type = types.str; + description = '' + If the storage is fromNixStore, the value is the password itself, + otherwise it is a path to the file that contains the password. + ''; + }; + };}); + }; +} diff --git a/nixos/modules/virtualisation/openstack/keystone.nix b/nixos/modules/virtualisation/openstack/keystone.nix index 30bdb8690462..e32c5a4cae1b 100644 --- a/nixos/modules/virtualisation/openstack/keystone.nix +++ b/nixos/modules/virtualisation/openstack/keystone.nix @@ -1,22 +1,25 @@ { config, lib, pkgs, ... }: -with lib; +with lib; with import ./common.nix {inherit lib;}; let cfg = config.virtualisation.openstack.keystone; - keystoneConf = pkgs.writeText "keystone.conf" '' + keystoneConfTpl = pkgs.writeText "keystone.conf" '' [DEFAULT] - admin_token = ${cfg.adminToken} + admin_token = ${cfg.adminToken.pattern} policy_file=${cfg.package}/etc/policy.json [database] - connection = ${cfg.databaseConnection} + + connection = "mysql://${cfg.database.user}:${cfg.database.password.pattern}@${cfg.database.host}/${cfg.database.name}" [paste_deploy] config_file = ${cfg.package}/etc/keystone-paste.ini ${cfg.extraConfig} ''; + keystoneConf = "/var/lib/keystone/keystone.conf"; + in { options.virtualisation.openstack.keystone = { package = mkOption { @@ -44,9 +47,8 @@ in { ''; }; - adminToken = mkOption { - type = types.str; - default = "mySuperToken"; + adminToken = mkSecretOption { + name = "adminToken"; description = '' This is the admin token used to boostrap keystone, ie. to provision first resources. @@ -87,9 +89,8 @@ in { ''; }; - adminPassword = mkOption { - type = types.str; - default = "admin"; + adminPassword = mkSecretOption { + name = "keystoneAdminPassword"; description = '' The keystone admin user's password. ''; @@ -104,13 +105,34 @@ in { }; }; - databaseConnection = mkOption { + database = { + host = mkOption { + type = types.str; + default = "localhost"; + description = '' + Host of the database. + ''; + }; + + name = mkOption { type = types.str; - default = mysql://keystone:keystone@localhost/keystone; + default = "keystone"; description = '' - The SQLAlchemy connection string to use to connect to the - Keystone database. + Name of the existing database. ''; + }; + + user = mkOption { + type = types.str; + default = "keystone"; + description = '' + The database user. The user must exist and has access to + the specified database. + ''; + }; + password = mkSecretOption { + name = "mysqlPassword"; + description = "The database user's password";}; }; }; @@ -132,12 +154,19 @@ in { systemd.services.keystone-all = { description = "OpenStack Keystone Daemon"; - packages = [ mysql ]; after = [ "network.target"]; path = [ cfg.package pkgs.mysql pkgs.curl pkgs.pythonPackages.keystoneclient pkgs.gawk ]; wantedBy = [ "multi-user.target" ]; preStart = '' mkdir -m 755 -p /var/lib/keystone + + cp ${keystoneConfTpl} ${keystoneConf}; + chown keystone:keystone ${keystoneConf}; + chmod 640 ${keystoneConf} + + ${replaceSecret cfg.database.password keystoneConf} + ${replaceSecret cfg.adminToken keystoneConf} + # Initialise the database ${cfg.package}/bin/keystone-manage --config-file=${keystoneConf} db_sync # Set up the keystone's PKI infrastructure @@ -162,7 +191,7 @@ in { # We use the service token to create a first admin user export OS_SERVICE_ENDPOINT=http://localhost:35357/v2.0 - export OS_SERVICE_TOKEN=${cfg.adminToken} + export OS_SERVICE_TOKEN=${getSecret cfg.adminToken} # If the tenant service doesn't exist, we consider # keystone is not initialized @@ -170,7 +199,7 @@ in { then keystone tenant-create --name service keystone tenant-create --name ${cfg.bootstrap.adminTenant} - keystone user-create --name ${cfg.bootstrap.adminUsername} --tenant ${cfg.bootstrap.adminTenant} --pass ${cfg.bootstrap.adminPassword} + keystone user-create --name ${cfg.bootstrap.adminUsername} --tenant ${cfg.bootstrap.adminTenant} --pass ${getSecret cfg.bootstrap.adminPassword} keystone role-create --name admin keystone role-create --name Member keystone user-role-add --tenant ${cfg.bootstrap.adminTenant} --user ${cfg.bootstrap.adminUsername} --role admin |