From 2a6fc72559a8248aebc32dd52e19bdb38db17c40 Mon Sep 17 00:00:00 2001 From: Dmitry Tantsur Date: Tue, 21 Jul 2020 16:11:33 +0200 Subject: [PATCH] Use random passwords by default It's easy to forget to override them, and you'll end up with a well known password used in your keystone and database. Use the password module to generate secure random passwords instead. Operators of production environments are still expected to provide their own passwords. The generated passwords are stored in /etc/bifrost and reused on the next installation. A new task is provided for upgrading the bootstrap (admin) user in keystone to the new password. Change-Id: I6771015f2b062233eeff85704655c8e2ab64364d --- doc/source/install/index.rst | 5 +- doc/source/install/keystone.rst | 16 +++- playbooks/inventory/group_vars/localhost | 4 +- playbooks/inventory/group_vars/target | 4 +- .../bifrost-ironic-install/defaults/main.yml | 89 ++++++++++--------- .../tasks/keystone_setup.yml | 1 + .../tasks/keystone_setup_inspector.yml | 1 + .../templates/clouds.yaml.j2 | 6 +- .../templates/openrc.j2 | 6 +- .../defaults/main.yml | 21 ++++- .../bifrost-keystone-install/tasks/main.yml | 26 ++++++ .../random-passwords-b33b8de010ee82b6.yaml | 18 ++++ 12 files changed, 136 insertions(+), 61 deletions(-) create mode 100644 releasenotes/notes/random-passwords-b33b8de010ee82b6.yaml diff --git a/doc/source/install/index.rst b/doc/source/install/index.rst index d4d5c3b20..bd289670f 100644 --- a/doc/source/install/index.rst +++ b/doc/source/install/index.rst @@ -302,8 +302,9 @@ upon. your local installation. - Change ``network_interface`` to match the interface that will need to service DHCP requests. -- Change the ``ironic_db_password`` which is set by ansible in MySQL - and in ironic's configuration file. +- Set ``service_password`` which is used for communication between services. + If unset, a random password is generated during the initial installation and + stored on the controller in ``~/.config/bifrost/service_password``. The install process, when executed will either download, or build disk images for the deployment of nodes, and be deployed to the nodes. diff --git a/doc/source/install/keystone.rst b/doc/source/install/keystone.rst index 1c8fed608..baa8c7e3d 100644 --- a/doc/source/install/keystone.rst +++ b/doc/source/install/keystone.rst @@ -18,7 +18,21 @@ oneanother. Example:: ansible-playbook -vvvv -i inventory/target install.yaml -e enable_keystone=true -e noauth_mode=false However, prior to installation, overriding credentials should be set -in order to customize the deployment to meet your needs. +in order to customize the deployment to meet your needs. At the very least, +the following parameters should be changed for a production environment: + +``admin_password`` + Password for the bootstrap user (called ``admin`` by default). +``default_password`` + Password for the regular user (called ``bifrost_user`` by default). +``service_password`` + Password for communication between services (never exposed to end users). + +If any of these values is not set, a random password is generated during the +initial installation and stored on the controller in an accordingly named file +in the ``~/.config/bifrost`` directory (override using ``password_dir``). + +See the following files for more settings that can be overridden: * ``playbooks/roles/bifrost-ironic-install/defaults/main.yml`` * ``playbooks/roles/bifrost-keystone-install/defaults/main.yml`` diff --git a/playbooks/inventory/group_vars/localhost b/playbooks/inventory/group_vars/localhost index b15204499..6cfa2c9a3 100644 --- a/playbooks/inventory/group_vars/localhost +++ b/playbooks/inventory/group_vars/localhost @@ -7,8 +7,8 @@ # network_interface: "virbr0" -# ironic_db_password ironic user password for rabbit -ironic_db_password: aSecretPassword473z +# password to use between services +#service_password: aSecretPassword473z # mysql_username: Default mysql admin username mysql_username: root # mysql_password: Default mysql admin user password diff --git a/playbooks/inventory/group_vars/target b/playbooks/inventory/group_vars/target index b15204499..6cfa2c9a3 100644 --- a/playbooks/inventory/group_vars/target +++ b/playbooks/inventory/group_vars/target @@ -7,8 +7,8 @@ # network_interface: "virbr0" -# ironic_db_password ironic user password for rabbit -ironic_db_password: aSecretPassword473z +# password to use between services +#service_password: aSecretPassword473z # mysql_username: Default mysql admin username mysql_username: root # mysql_password: Default mysql admin user password diff --git a/playbooks/roles/bifrost-ironic-install/defaults/main.yml b/playbooks/roles/bifrost-ironic-install/defaults/main.yml index b66e3e69d..0fddd7018 100644 --- a/playbooks/roles/bifrost-ironic-install/defaults/main.yml +++ b/playbooks/roles/bifrost-ironic-install/defaults/main.yml @@ -112,11 +112,6 @@ ipa_git_url: https://opendev.org/openstack/ironic-python-agent ipa_builder_git_url: https://opendev.org/openstack/ironic-python-agent-builder mysql_username: "root" mysql_password: "" -# NOTE(TheJulia): While we have indicated we're going to deprecate ironic_db_password, -# we didn't properly notate it from what I can see at a glance, and we seem to have -# an odd variable expansion issue on fedora blocking migration to fedora-27 that this -# should fix.... -ironic_db_password: aSecretPassword473z disable_dnsmasq_dns: True ironic_git_folder: /opt/stack/ironic ironicclient_git_folder: /opt/stack/python-ironicclient @@ -266,47 +261,32 @@ enable_keystone: false ironic_api_url: "http://localhost:6385" ironic_inspector_api_url: "http://localhost:5050" -# NOTE: The keystone support in this role -# expects the keystone.bootstrap variables to -# either be loaded OR present from keystone -# installation. The keystone settings below -# should only be used if the role is utilized -# independently of the keystone installation -# role, such as leveraging a pre-existing -# keystone installation. -# WARNING: Using a pre-existing keystone has -# not been tested. -# -#keystone: -# debug: true -# bootstrap: -# enabled: true -# username: admin -# password: ChangeThisPa55w0rd -# project_name: admin -# admin_url: "http://127.0.0.1:35357/v3/" -# public_url: "http://127.0.0.1:5000/v3/" -# internal_url: "http://127.0.0.1:5000/v3/" -# region_name: "RegionOne" -# message_queue: -# username: keystone -# password: ChangeThisPa55w0rd -# host: 127.0.0.1 -# database: -# name: keystone -# username: keystone -# password: ChangeThisPa55w0rd -# host: 127.0.0.1 +# Directory (on the controller) to keep the passwords +password_dir: "{{ lookup('env', 'HOME') }}/.config/bifrost" + +# Various credentials +default_username: bifrost_user +default_password: "{{ lookup('password', password_dir + '/default_password') }}" + +admin_username: admin +admin_password: "{{ lookup('password', password_dir + '/admin_password') }}" + +# NOTE(dtantsur): various URLs in configuration files don't like special +# symbols in passwords. +service_password: "{{ lookup('password', password_dir + '/service_password chars=ascii_letters,digits') }}" + +# TODO(dtantsur): deprecate in favor of service_password +ironic_db_password: "{{ service_password }}" ironic: service_catalog: username: "ironic" - password: "ChangeThisPa55w0rd" + password: "{{ service_password }}" auth_url: "http://127.0.0.1:5000/v3" project_name: "service" keystone: - default_username: "bifrost_user" - default_password: "ChangeThisPa55w0rd" + default_username: "{{ default_username }}" + default_password: "{{ default_password }}" database: name: "ironic" username: "ironic" @@ -316,19 +296,40 @@ ironic: ironic_inspector: service_catalog: username: "ironic_inspector" - password: "ChangeThisPa55w0rd" + password: "{{ service_password }}" auth_url: "http://127.0.0.1:5000/v3" project_name: "service" keystone: - default_username: "inspector_user" - default_password: "ChangeThisPa55w0rd" + default_username: "{{ default_username }}" + default_password: "{{ default_password }}" database: name: "inspector" username: "inspector" password: "{{ ironic_db_password }}" host: "localhost" - # DEPRECATED(TheJulia): Inheritance of ironic_db_password params - # should be removed in Queens. + +# NOTE(dtantsur): keep in sync with bifrost-keystone-install +keystone: + debug: true + bootstrap: + enabled: true + username: "{{ admin_username }}" + password: "{{ admin_password }}" + project_name: admin + admin_url: "http://127.0.0.1:35357/v3/" + public_url: "http://127.0.0.1:5000/v3/" + internal_url: "http://127.0.0.1:5000/v3/" + region_name: "RegionOne" + message_queue: + username: keystone + password: "{{ service_password }}" + host: localhost + port: 5672 + database: + name: keystone + username: keystone + password: "{{ service_password }}" + host: localhost pip_opts: "{{ lookup('env', 'PIP_OPTS') | default('') }}" diff --git a/playbooks/roles/bifrost-ironic-install/tasks/keystone_setup.yml b/playbooks/roles/bifrost-ironic-install/tasks/keystone_setup.yml index f1101b6b4..38454a04f 100644 --- a/playbooks/roles/bifrost-ironic-install/tasks/keystone_setup.yml +++ b/playbooks/roles/bifrost-ironic-install/tasks/keystone_setup.yml @@ -65,6 +65,7 @@ project_name: "{{ keystone.bootstrap.project_name | default('admin') }}" project_domain_id: "default" user_domain_id: "default" + update_password: always wait: yes environment: "{{ bifrost_venv_env if enable_venv else {} }}" no_log: true diff --git a/playbooks/roles/bifrost-ironic-install/tasks/keystone_setup_inspector.yml b/playbooks/roles/bifrost-ironic-install/tasks/keystone_setup_inspector.yml index 33a42f83b..754da4c13 100644 --- a/playbooks/roles/bifrost-ironic-install/tasks/keystone_setup_inspector.yml +++ b/playbooks/roles/bifrost-ironic-install/tasks/keystone_setup_inspector.yml @@ -194,6 +194,7 @@ project_name: admin project_domain_id: "default" user_domain_id: "default" + update_password: always wait: yes environment: "{{ bifrost_venv_env if enable_venv else {} }}" no_log: true diff --git a/playbooks/roles/bifrost-keystone-client-config/templates/clouds.yaml.j2 b/playbooks/roles/bifrost-keystone-client-config/templates/clouds.yaml.j2 index 0c39516f3..ff932adaa 100644 --- a/playbooks/roles/bifrost-keystone-client-config/templates/clouds.yaml.j2 +++ b/playbooks/roles/bifrost-keystone-client-config/templates/clouds.yaml.j2 @@ -6,9 +6,9 @@ clouds: auth_type: "password" region_name: {{ cloud.1.config_region_name }} auth: - username: {{ cloud.1.config_username }} - password: {{ cloud.1.config_password }} - project_name: {{ cloud.1.config_project_name }} + username: "{{ cloud.1.config_username }}" + password: "{{ cloud.1.config_password }}" + project_name: "{{ cloud.1.config_project_name }}" auth_url: {{ cloud.1.config_auth_url }} project_domain_id: "{{ cloud.1.config_project_domain_id | default('default') }}" user_domain_id: "{{ cloud.1.config_user_domain_id | default('default') }}" diff --git a/playbooks/roles/bifrost-keystone-client-config/templates/openrc.j2 b/playbooks/roles/bifrost-keystone-client-config/templates/openrc.j2 index 75c4c5deb..3c807073e 100644 --- a/playbooks/roles/bifrost-keystone-client-config/templates/openrc.j2 +++ b/playbooks/roles/bifrost-keystone-client-config/templates/openrc.j2 @@ -8,9 +8,9 @@ case "$1" in "{{ cloud.0 }}") export OS_PROJECT_DOMAIN_NAME="{{ cloud.1.config_project_domain_id | default('default') }}" export OS_USER_DOMAIN_NAME="{{ cloud.1.config_user_domain_id | default('default') }}" - export OS_PROJECT_NAME={{ cloud.1.config_project_name }} - export OS_USERNAME={{ cloud.1.config_username }} - export OS_PASSWORD={{ cloud.1.config_password }} + export OS_PROJECT_NAME="{{ cloud.1.config_project_name }}" + export OS_USERNAME="{{ cloud.1.config_username }}" + export OS_PASSWORD="{{ cloud.1.config_password }}" export OS_AUTH_URL={{ cloud.1.config_auth_url }} export OS_IDENTITY_API_VERSION=3 ;; diff --git a/playbooks/roles/bifrost-keystone-install/defaults/main.yml b/playbooks/roles/bifrost-keystone-install/defaults/main.yml index 98ccc96de..e0bd98760 100644 --- a/playbooks/roles/bifrost-keystone-install/defaults/main.yml +++ b/playbooks/roles/bifrost-keystone-install/defaults/main.yml @@ -1,4 +1,6 @@ --- +enable_keystone: false + keystone_source_install: true # *_git_url can be overridden by local clones for offline installs keystone_git_url: https://opendev.org/openstack/keystone @@ -47,12 +49,23 @@ bifrost_venv_env: pydoc: "python -m pydoc" ansible_python_interpreter: "{{ bifrost_venv_dir + '/bin/python3' if enable_venv | bool else '/usr/bin/python3' }}" +# Directory (on the controller) to keep the passwords +password_dir: "{{ lookup('env', 'HOME') }}/.config/bifrost" + +admin_username: admin +admin_password: "{{ lookup('password', password_dir + '/admin_password') }}" + + +# NOTE(dtantsur): various URLs in configuration files don't like special +# symbols in passwords. +service_password: "{{ lookup('password', password_dir + '/service_password chars=ascii_letters,digits') }}" + keystone: debug: true bootstrap: enabled: true - username: admin - password: ChangeThisPa55w0rd + username: "{{ admin_username }}" + password: "{{ admin_password }}" project_name: admin admin_url: "http://127.0.0.1:35357/v3/" public_url: "http://127.0.0.1:5000/v3/" @@ -60,13 +73,13 @@ keystone: region_name: "RegionOne" message_queue: username: keystone - password: ChangeThisPa55w0rd + password: "{{ service_password }}" host: localhost port: 5672 database: name: keystone username: keystone - password: ChangeThisPa55w0rd + password: "{{ service_password }}" host: localhost pip_opts: "{{ lookup('env', 'PIP_OPTS') | default('') }}" diff --git a/playbooks/roles/bifrost-keystone-install/tasks/main.yml b/playbooks/roles/bifrost-keystone-install/tasks/main.yml index 0cc12c838..1b02abb31 100644 --- a/playbooks/roles/bifrost-keystone-install/tasks/main.yml +++ b/playbooks/roles/bifrost-keystone-install/tasks/main.yml @@ -44,3 +44,29 @@ - name: "Start Keystone services" include: start.yml when: enable_keystone is defined and enable_keystone |bool == True and skip_start | bool != True + +- name: "Change the bootstrap password from the static value on upgrade" + os_user: + name: "{{ keystone.bootstrap.username }}" + password: "{{ keystone.bootstrap.password }}" + update_password: always + state: present + domain: "default" + default_project: "{{ keystone.bootstrap.project_name }}" + auth: + auth_url: "{{ ironic.service_catalog.auth_url | default('http://127.0.0.1:5000/') }}" + username: "{{ keystone.bootstrap.username }}" + password: "ChangeThisPa55w0rd" + project_name: "{{ keystone.bootstrap.project_name | default('admin') }}" + project_domain_id: "default" + user_domain_id: "default" + wait: yes + environment: "{{ bifrost_venv_env if enable_venv else {} }}" + no_log: true + ignore_errors: true + when: + - enable_keystone | bool + - not skip_bootstrap | bool + - test_created_keystone_db is undefined or not test_created_keystone_db.changed | bool + - keystone.bootstrap.enabled | bool + - keystone.database.host == 'localhost' diff --git a/releasenotes/notes/random-passwords-b33b8de010ee82b6.yaml b/releasenotes/notes/random-passwords-b33b8de010ee82b6.yaml new file mode 100644 index 000000000..21454f932 --- /dev/null +++ b/releasenotes/notes/random-passwords-b33b8de010ee82b6.yaml @@ -0,0 +1,18 @@ +--- +upgrade: + - | + The ``inspector_user`` user is not created by default any more. Use + ``bifrost_user`` instead. + - | + If you're relying on default passwords (e.g. for the database or keystone + passwords), they will be changed on upgrade. Please use explicit values + if you want to avoid it. +security: + - | + Random passwords are now generated by default instead of using a constant. + The same parameters as before can be used to override them. +deprecations: + - | + The ``ironic_db_password`` parameter is deprecated, please use + ``service_password`` to set a password to use between services or + override the whole ``ironic`` and ``keystone`` objects.