Support HTTP basic auth and switch bifrost-cli to it

The voting jobs also use the new mode (since it requires more OS
coverage), the DHCP jobs are left with no-auth.

Change-Id: I8c8ee112edbc1e61b54aff13c06c518c7daa9700
This commit is contained in:
Dmitry Tantsur 2020-07-20 17:06:04 +02:00
parent 02fb11fcc7
commit bcda97b630
20 changed files with 164 additions and 18 deletions

View File

@ -158,7 +158,7 @@ def cmd_install(args):
network_interface=args.network_interface,
enable_keystone=args.enable_keystone,
use_public_urls=args.enable_keystone,
noauth_mode=not args.enable_keystone,
noauth_mode='false',
enabled_hardware_types=args.hardware_types,
cleaning_disk_erase=args.cleaning_disk_erase,
testing=args.testenv,

View File

@ -31,6 +31,7 @@ oslo.i18n==3.20.0
oslo.log==3.36.0
oslo.serialization==2.25.0
oslo.utils==3.36.0
passlib==1.7.2
pbr==2.0.0
prettytable==0.7.2
pyasn1==0.4.2

View File

@ -15,3 +15,4 @@
ZUUL_BRANCH: "{{ zuul.branch }}"
BOOT_MODE: "{{ boot_mode | default('') }}"
TEST_VM_NODE_DRIVER: "{{ test_driver | default('ipmi') }}"
NOAUTH_MODE: "{{ noauth_mode | default(false) | bool | lower }}"

View File

@ -25,6 +25,14 @@ bifrost-ironic-install role.
testing: false
Enables no-authentication mode where no authentication is used for accessing
API services. Setting it to ``false`` will make ironic and ironic-inspector
either use keystone (if ``enable_keystone`` is true) or HTTP basic auth
(use ``admin_username``/``admin_password`` and
``default_username``/``default_password`` to configure).
noauth_mode: true
Node cleaning, which was a feature added to ironic during the Kilo cycle,
removes the previous contents of a node once it has been moved from an
active to available state, such as setting the provision state to deleted.

View File

@ -33,6 +33,7 @@ required_packages:
- python-pip
- gcc
- dnsmasq
- apache2-utils
# NOTE(TheJulia): The above entry for dnsmasq must be the last entry in the
# package list as the installation causes name resolution changes that can
# temporarily block packages following it while the system is being

View File

@ -10,6 +10,7 @@ required_packages:
- dnsmasq
- gcc
- genisoimage
- httpd-tools
- ipmitool
- ipxe-bootimgs
- kpartx

View File

@ -36,6 +36,7 @@ required_packages:
- socat
- firewalld
- python3-firewall
- httpd-tools
iscsi_required_packages:
- iscsi-initiator-utils
- gdisk

View File

@ -41,6 +41,7 @@ required_packages:
- python-pip
- gcc
- python-PyMySQL
- apache2-utils
iscsi_required_packages:
- open-iscsi
- gptfdisk

View File

@ -27,6 +27,7 @@ required_packages:
- uuid-runtime
- curl
- dnsmasq
- apache2-utils
# NOTE(TheJulia): The above entry for dnsmasq must be the last entry in the
# package list as the installation causes name resolution changes that can
# temporarily block packages following it while the system is being

View File

@ -134,6 +134,26 @@
command: cp -r "{{ ironic_git_folder }}/etc/ironic/rootwrap.d/" "/etc/ironic/rootwrap.d"
when: not skip_install | bool
- name: "Generate admin htpasswd for ironic"
htpasswd:
path: /etc/ironic/htpasswd
crypt_scheme: bcrypt
name: "{{ admin_username }}"
password: "{{ admin_password }}"
when:
- not noauth_mode | bool
- not enable_keystone | bool
- name: "Generate user htpasswd for ironic"
htpasswd:
path: /etc/ironic/htpasswd
crypt_scheme: bcrypt
name: "{{ default_username }}"
password: "{{ default_password }}"
when:
- not noauth_mode | bool
- not enable_keystone | bool
- name: "Populate keystone for Bifrost"
include: keystone_setup.yml
when: enable_keystone is defined and enable_keystone | bool == true

View File

@ -61,6 +61,26 @@
- name: "Copy rootwrap.d contents from ironic-inspector source folder"
command: cp -r "{{ ironicinspector_git_folder }}/rootwrap.d/" "/etc/ironic-inspector/rootwrap.d"
- name: "Generate admin htpasswd for ironic-inspector"
htpasswd:
path: /etc/ironic-inspector/htpasswd
crypt_scheme: bcrypt
name: "{{ admin_username }}"
password: "{{ admin_password }}"
when:
- not noauth_mode | bool
- not enable_keystone | bool
- name: "Generate user htpasswd for ironic-inspector"
htpasswd:
path: /etc/ironic-inspector/htpasswd
crypt_scheme: bcrypt
name: "{{ default_username }}"
password: "{{ default_password }}"
when:
- not noauth_mode | bool
- not enable_keystone | bool
- name: "Populate keystone for ironic-inspector "
include: keystone_setup_inspector.yml
when: enable_keystone is defined and enable_keystone | bool == true

View File

@ -1,10 +1,13 @@
# {{ ansible_managed }}
[DEFAULT]
{% if enable_keystone is defined and enable_keystone | bool == true %}
{% if enable_keystone | bool %}
auth_strategy = keystone
{% else %}
{% elif noauth_mode | bool %}
auth_strategy = noauth
{% else %}
auth_strategy = http_basic
http_basic_auth_user_file = /etc/ironic-inspector/htpasswd
{% endif %}
debug = {{ inspector_debug | bool }}
@ -29,7 +32,7 @@ driver = iptables
{% endif %}
[ironic]
{% if enable_keystone is defined and enable_keystone | bool == true %}
{% if enable_keystone | bool %}
os_region = {{ keystone.bootstrap.region_name | default('RegionOne') }}
project_name = baremetal
username = {{ ironic_inspector.keystone.default_username }}
@ -38,10 +41,14 @@ auth_url = {{ ironic_inspector.service_catalog.auth_url }}
auth_type = password
user_domain_id = default
project_domain_id = default
{% else %}
{% elif noauth_mode | bool %}
auth_type = none
endpoint_override = {{ ironic_api_url }}
{% else %}
auth_type = http_basic
endpoint_override = {{ ironic_api_url }}
username = {{ admin_username }}
password = {{ admin_password }}
{% endif %}
{% if enable_keystone is defined and enable_keystone | bool == true %}

View File

@ -27,10 +27,13 @@ transport_url = rabbit://ironic:{{ironic_db_password }}@{{ message_queue_host |
rpc_transport = json-rpc
{% endif %}
{% if enable_keystone is defined and enable_keystone | bool == true %}
{% if enable_keystone | bool %}
auth_strategy = keystone
{% else %}
{% elif noauth_mode | bool %}
auth_strategy = noauth
{% else %}
auth_strategy = http_basic
http_basic_auth_user_file = /etc/ironic/htpasswd
{% endif %}
{% if ironic_log_dir | default("") != "" %}
@ -106,7 +109,7 @@ use_web_server_for_images = true
[inspector]
power_off = {{ power_off_after_inspection }}
extra_kernel_params = {{ inspector_extra_kernel_options | default('') }}
{% if enable_keystone is defined and enable_keystone | bool == true %}
{% if enable_keystone | bool %}
auth_type = password
auth_url = {{ ironic.service_catalog.auth_url }}
username = {{ ironic.service_catalog.username }}
@ -116,9 +119,14 @@ project_name = {{ ironic.service_catalog.project_name }}
project_domain_id = default
region_name = {{ keystone.bootstrap.region_name | default('RegionOne')}}
callback_endpoint_override = http://{{ internal_ip }}:5050
{% else %}
{% elif noauth_mode | bool %}
auth_type=none
endpoint_override = http://{{ internal_ip }}:5050
{% else %}
auth_type = http_basic
endpoint_override = http://{{ internal_ip }}:5050
username = {{ admin_username }}
password = {{ admin_password }}
{% endif %}
{% endif %}
@ -134,7 +142,7 @@ project_domain_id = default
{% endif %}
[service_catalog]
{% if enable_keystone is defined and enable_keystone | bool == true %}
{% if enable_keystone | bool %}
auth_url = {{ ironic.service_catalog.auth_url }}
auth_type = password
project_name = {{ ironic.service_catalog.project_name }}
@ -143,13 +151,18 @@ password = {{ ironic.service_catalog.password }}
user_domain_id = default
project_domain_id = default
region_name = {{ keystone.bootstrap.region_name | default('RegionOne')}}
{% else %}
{% elif noauth_mode | bool %}
auth_type = none
{% else %}
auth_type = http_basic
username = {{ admin_username }}
password = {{ admin_password }}
{% endif %}
endpoint_override = http://{{ internal_ip }}:6385
[json_rpc]
{% if enable_keystone is defined and enable_keystone | bool == true %}
{% if enable_keystone | bool %}
auth_strategy = keystone
auth_url = {{ ironic.service_catalog.auth_url }}
auth_type = password
project_name = {{ ironic.service_catalog.project_name }}
@ -157,6 +170,16 @@ username = {{ ironic.service_catalog.username }}
password = {{ ironic.service_catalog.password }}
user_domain_id = default
project_domain_id = default
{% else %}
{% elif noauth_mode | bool %}
auth_strategy = noauth
auth_type = none
{% else %}
auth_strategy = http_basic
auth_type = http_basic
http_basic_auth_user_file = /etc/ironic/htpasswd
username = {{ admin_username }}
password = {{ admin_password }}
# Deprecated - compatibility
http_basic_username = {{ admin_username }}
http_basic_password = {{ admin_password }}
{% endif %}

View File

@ -6,3 +6,16 @@ ironic_inspector_api_url: "http://localhost:5050"
enable_venv: true
bifrost_venv_dir: "{{ lookup('env', 'VENV') or '/opt/stack/bifrost' }}"
ansible_python_interpreter: "{{ bifrost_venv_dir + '/bin/python3' if enable_venv | bool else '/usr/bin/python3' }}"
enable_keystone: false
noauth_mode: true
# 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') }}"

View File

@ -14,7 +14,7 @@ clouds:
user_domain_id: "{{ cloud.1.config_user_domain_id | default('default') }}"
identity_api_version: "3"
{% endfor %}
{% else %}
{% elif noauth_mode | default(true) | bool %}
bifrost:
auth_type: "none"
baremetal_endpoint_override: {{ ironic_api_url }}
@ -23,4 +23,19 @@ clouds:
bifrost-inspector:
auth_type: "none"
endpoint: {{ ironic_inspector_api_url }}
{% else %}
bifrost:
auth_type: "http_basic"
auth:
username: "{{ default_username }}"
password: "{{ default_password }}"
endpoint: {{ ironic_api_url }}
baremetal_introspection_endpoint_override: {{ ironic_inspector_api_url }}
bifrost-admin:
auth_type: "http_basic"
auth:
username: "{{ admin_username }}"
password: "{{ admin_password }}"
endpoint: {{ ironic_api_url }}
baremetal_introspection_endpoint_override: {{ ironic_inspector_api_url }}
{% endif %}

View File

@ -1,7 +1,7 @@
#!/usr/bin/env bash
# WARNING: This file is managed by bifrost.
{% if (enable_keystone | default(false) | bool) %}
{% if enable_keystone | bool %}
case "$1" in
{% for cloud in clouds | default({}) | dictsort %}
# Section for {{ cloud.0 }}
@ -17,7 +17,22 @@ case "$1" in
{% endfor %}
*) echo -e "\nERROR unsupported or unspecified profile: $1\nMust be one of {{ clouds | default({}) | dictsort | map(attribute='0') | join(',') }}";;
esac
{% else %}
{% elif noauth_mode | bool %}
export OS_AUTH_TYPE=none
export OS_ENDPOINT={{ ironic_api_url }}
{% else %}
export OS_AUTH_TYPE=http_basic
export OS_ENDPOINT={{ ironic_api_url }}
unset OS_AUTH_URL
case "${1:-bifrost}" in
"bifrost")
export OS_USERNAME="{{ default_username }}"
export OS_PASSWORD="{{ default_password }}"
;;
"bifrost-admin")
export OS_USERNAME="{{ admin_username }}"
export OS_PASSWORD="{{ admin_password }}"
;;
*) echo -e "\nERROR unsupported or unspecified profile: $1\nMust be one of bifrost, bifrost-admin";;
esac
{% endif %}

View File

@ -0,0 +1,14 @@
---
features:
- |
HTTP basic authentication for API services is now supported in addition
to no authentication and Keystone. It is triggered by setting
``noauth_mode=false`` with ``enable_keystone=false``.
- |
Installations with ``bifrost-cli`` now use HTTP basic authentication if
Keystone is disabled.
deprecations:
- |
Bifrost will switch to HTTP basic authentication by default in the future.
If you want to avoid it, please set ``noauth_mode`` to ``false``
explicitly.

View File

@ -5,6 +5,7 @@ pbr!=2.1.0,>=2.0.0 # Apache-2.0
oslo.config>=5.2.0 # Apache-2.0
oslo.log>=3.36.0 # Apache-2.0
PyYAML>=3.12 # MIT
passlib>=1.7.2 # BSD
# TODO(dtantsur): remove pyOpenSSL when we no longer support Bionic and
# openSUSE updates its version to at least 18.0.0.
pyOpenSSL>=18.0.0 # Apache-2.0

View File

@ -41,7 +41,7 @@ DOWNLOAD_IPA=true
CREATE_IPA_IMAGE=false
WRITE_INTERFACES_FILE=true
PROVISION_WAIT_TIMEOUT=${PROVISION_WAIT_TIMEOUT:-900}
NOAUTH_MODE=true
NOAUTH_MODE=${NOAUTH_MODE:-true}
CLOUD_CONFIG=""
WAIT_FOR_DEPLOY=true

View File

@ -34,6 +34,7 @@
timeout: 7200
vars:
use_dhcp: true
noauth_mode: true
- job:
name: bifrost-integration-dhcp-ubuntu-bionic
@ -66,6 +67,8 @@
name: bifrost-integration-tinyipa
parent: bifrost-base
timeout: 3600
vars:
noauth_mode: false
- job:
name: bifrost-integration-tinyipa-ubuntu-bionic