-
-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
nixos/keystone: init at liberty version #20905
Conversation
@nlewo, thanks for your PR! By analyzing the history of the files in this pull request, we identified @edolstra, @joachifm and @offlinehacker to be potential reviewers. |
policy_file=${cfg.package}/etc/policy.json | ||
|
||
[database] | ||
connection = mysql://${cfg.database.user}:${cfg.database.password}@${cfg.database.host}/${cfg.database.name} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure, but maybe would be better to move all this config line as parameter instead of splitting it into smaller parts? For example keystone supports postgresql as well, in such a case user could just paste all the connection string.
In the description field there could be a link to keystone documentation. there is also example field in mkOption so you could provide one or two examples.
And probably this could be a "secret".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -629,4 +629,5 @@ | |||
./virtualisation/vmware-guest.nix | |||
./virtualisation/xen-dom0.nix | |||
./virtualisation/xe-guest-utilities.nix | |||
./virtualisation/keystone.nix |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMHO, I think keystone is not about virtualization at all.
My preference would be to either:
- move separate services to categories that match what they do
- create sub-category in virtualisation for open stack and keep everything there, i.e.
virtualisation.openstack = {
keystone.enable=true;
};
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My preference is your point 2. Moreover, this is already the openstack nix packages layout.
default = false; | ||
type = types.bool; | ||
description = '' | ||
Bootstrap the Keystone service by creating the service |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to mention if the bootstrap will be done only first time or each time we deploy. I would expect that if I have bootstrap = true, the bootstrap will be done only one time but I'm not sure what is the behaviour from this description.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
type = types.str; | ||
default = "localhost"; | ||
description = '' | ||
The address of the public identity endpoint. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Option name says endpoint and description says address. I'm probably biased by when I think about endpoint I have URL/URI in my mind (http://example.org:25/path, tcp://127.0.0.5), when I think of address I have in my mind IP:PORT combination, eventually DNS:PORT. Would be nice to use explain better in the description what values are allowed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed this option a little bit to be more explicit.
# systems! | ||
virtualisation.keystone.package = mkDefault pkgs.keystone; | ||
|
||
services.mysql.enable = mkDefault (cfg.database.host == "localhost"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't :-)
This can be done on higher level. This can be surprise (also it was not mentioned in the description), maybe somebody would like to use postgres.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done ;)
gid = config.ids.gids.keystone; | ||
}]; | ||
|
||
systemd.services.keystone-all = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not just keystone?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The binary name is keystone-all while the binary keystone is the client. For me, it's more clear to use keystone-all since I know this is the keystone server. This is a respond to the "why" and not a respond at the question "what is the best" ;)
path = [ cfg.package pkgs.mysql pkgs.curl pkgs.pythonPackages.keystoneclient pkgs.gawk ]; | ||
wantedBy = [ "multi-user.target" ]; | ||
preStart = '' | ||
mkdir -m 755 -p /var/lib/keystone |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
optionally you could have "work-dir" option as some other modules
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be addressed later without any breaking changes I think.
postStart = optionalString cfg.bootstrap.enable '' | ||
# Wait until the keystone is available for use | ||
count=0 | ||
while ! curl -s http://localhost:35357/v2.0 > /dev/null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably the port could be configurable (actually I'm not sure actually if it is related to endpointPublic or not). There was no other parameter to specify listening address.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need "--fail" option
-f, --fail
(HTTP) Fail silently (no output at all) on server errors. This is mostly done to bet‐
ter enable scripts etc to better deal with failed attempts. In normal cases when an
HTTP server fails to deliver a document, it returns an HTML document stating so (which
often also describes why and more). This flag will prevent curl from outputting that
and return error 22.
This method is not fail-safe and there are occasions where non-successful response
codes will slip through, especially when authentication is involved (response codes
401 and 407).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Thanks.
# Set up the keystone's PKI infrastructure | ||
${cfg.package}/bin/keystone-manage --config-file=${keystoneConf} pki_setup --keystone-user keystone --keystone-group keystone | ||
''; | ||
postStart = optionalString cfg.bootstrap.enable '' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you may consider "set -eu" to make script more robust (it will break script when there is an error or when variable is not set but used)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -0,0 +1,51 @@ | |||
{ system ? builtins.currentSystem }: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very nice smoketest!
@nlewo thanks for making those changes. |
This commit introduces a nixos module for the Openstack Keystone service. It also provides a optional bootstrap step that creates some basic initial resources (tenants, endpoints,...). The provided test starts Keystone by enabling bootstrapping and checks if user creation works well. This commit is based on initial works made by domenkozar.
# 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 ? ""}: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh boy, you really like those nix store passwords, don't you :-)
Anyway, if files are working I'm ok with it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could test if the password contains '/', then use '|' as separator, and so on...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure it's worth, even if we fix it here, some values might break the application config files itself (this is probably application specific).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, exactly...
default = "##${name}##"; | ||
description = "The pattern that represent the secret."; | ||
}; | ||
storage = mkOption { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you add
default = "fromFile";
I'll be more than happy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this is not working. If you set this default, I guess you can not use fromNixStore anymore.
But anyway, the user have to declare these variable, and I think the name is enough explicit to inform the user its password will be store in the nix store or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you set default, yes, you can use other values as well. Just without explicit set, the default is taken, that's it.
If you think that explicit decision here is better, fair enough.
# 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} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can break if password contains /
, but I don't have better idea what to do with it now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
;)
In fact, I would like to have an "easy to use" mode. If someone wants to test the module, or deploy a dev environment, he doesn't have to handle password file and manually manage its password.
Thanks for adding "passwords from files" feature. |
It is strange there is not a common mechanism to handle these passwords in nixos. In fact, I'm not really fan of the way proposed here but it does the job in the context of this PR. I think we could open a topic to implement a clean and common way to do this. I haven't time on this for now. Moreover, I tryied complex options definitions and submodule and either option type seems to be fragile, especially with default values. |
@nlewo It's not strange, the discussion is still going I think (check one of the first issues on github about private nix store entries), on the other front, recently, the security team is forming, all this stuff is slowly happening. Good stuff anyway, I think this module is very nice start. Probably you need to grab someone now who has merge permissions to review and merge. |
@spinus Thanks for your reviews and comments. |
@domenkozar do you know who could I ping to review and merge this PR? Maybe @FRidh? (sorry for the spam) |
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}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is hard coding mysql://
wanted here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't test it with another database, so I prefer to let it hardcoded for now. If another backend is required and tested, we could easily add it by preserving backward compatibility.
@@ -0,0 +1,79 @@ | |||
{ system ? builtins.currentSystem }: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this test should be referenced in nixos/release.nix
, otherwise it won't be automatically run.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I pushed a new commit related to your comment... but I'm really not sure it's correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you want set yourself as maintainer for this test, so you get informed in case it fails?
meta = with pkgs.stdenv.lib.maintainers; {
maintainers = [ ...];
};
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
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.
Thanks! |
Motivation for this change
Things done
(nix.useSandbox on NixOS,
or option
build-use-sandbox
innix.conf
on non-NixOS)
nix-shell -p nox --run "nox-review wip"
./result/bin/
)This commit introduces a nixos module for the Openstack Keystone
service. It also provides a optional bootstrap step that creates some
basic initial resources (tenants, endpoints,...).
The provided test starts Keystone by enabling bootstrapping and checks
if user creation works well.
This commit is based on initial works made by domenkozar.