diff --git a/tripleo_ipa/playbooks/README.md b/tripleo_ipa/playbooks/README.md new file mode 100644 index 0000000..5105b66 --- /dev/null +++ b/tripleo_ipa/playbooks/README.md @@ -0,0 +1,55 @@ +# TLS-e IPA Server Configuration Roles + +## Included Roles + +This directory includes 3 playbooks (`ipa-server-*.yaml`) to be used for the TripleO TLS-e configuration of a FreeIPA server. The playbooks need to be run in the order that follows, however certain playbooks only need to be run once per IPA server: + +--- +1. `ipa-sever-create-role.yaml` The purpose of this playbook is to create a role on the IPA server with the appropriate permissions and privileges to add and remove hosts, principals, services and dns entries. +> Currently this playbook is required to be executed on an IPA client host with an active Kerberos token. + +> This playbook only needs to be run once per IPA server. +--- +2. `ipa-register-undercloud.yaml` This playbook registers the undercloud host as an IPA client and provides a one time password(OTP) to the operator for use in the undercloud configuration. An example of the final output of a successful run of this play will look like this: +``` +TASK [provide OTP generated by IPA server] **************************** +ok: [localhost] => { + "msg": [ + "The OTP provided by the IPA server is 9Ok~JEz!ul;&Sf:V This playbook does not require an active Kerberos token. + +> This playbook needs to be run once per openstack deployment. +--- +3. `ipa-server-create-principal.yaml` This playbook creates the nova user for the undercloud host created with `ipa-register-undercloud.yaml` and adds it to the Nova Host Manager IPA role created by `ipa-server-create-role.yaml`. +> This playbook does not require an active Kerberos token. + +> This playbook needs to be run once per openstack deployment. +--- +## Environment/Ansible variables +The playbooks currently require the following variables to be set. These can either be environment variables or ansible variables passed either in a file or on the command line with the `-e` argument to the `ansible-playbook` command. + +### `ENVIRONMENT/ansible` variable +* `tripleo_ipa_host` this is the host which ansible will connect to for playbook execution, this is the host that needs to be an IPA client. Defaults to `localhost`. +* `IPA_PRINCIPAL/tripleo_ipa_principal` is the IPA username with appropriate permissions and privileges to add roles and privileges. This value is required and has no default. +* `IPA_PASSWORD/tripleo_ipa_password` is the password for the IPA_PRINCIPAL. This value is required and has no default. +* `UNDERCLOUD_FQDN/tripleo_undercloud_fqdn` is the fully qualified domain name of the undercloud host. This value is required and has no default. + +#### Example environment variables +```bash +export IPA_PRINCIPAL=admin +export IPA_PASSWORD=password +export UNDERCLOUD_FQDN=undercloud.ooo.test +``` + +#### Example ansible variables file +```yaml +--- +tripleo_ipa_principal: admin +tripleo_ipa_password: password +tripleo_undercloud_fqdn: undercloud.ooo.test +``` diff --git a/tripleo_ipa/playbooks/ipa-server-create-principal.yaml b/tripleo_ipa/playbooks/ipa-server-create-principal.yaml new file mode 100644 index 0000000..463c81b --- /dev/null +++ b/tripleo_ipa/playbooks/ipa-server-create-principal.yaml @@ -0,0 +1,68 @@ +--- +# Copyright 2020 Red Hat, Inc. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# This playbook creates the nova user and adds it to the Nova Host Manager IPA +# role. This needs to be executed by a user that has permissions to add services +# and to add them to roles. This needs to be run once per openstack deployment. + +- name: Playbook to setup a principal for use with tripleo-ipa + connection: "{{ (tripleo_ipa_host is defined) | ternary('ssh', 'local') }}" + hosts: "{{ tripleo_ipa_host | default('localhost') }}" + tasks: + - name: ensure definitions + fail: + msg: >- + {{ item }} is undefined + when: not item.ansible_var and not item.env_var + with_items: + - name: ipa_principal + ansible_var: "{{ ipa_principal | default('') }}" + env_var: "{{ lookup('env', 'IPA_PRINCIPAL') }}" + - name: ipa_password + ansible_var: "{{ ipa_password | default('') }}" + env_var: "{{ lookup('env', 'IPA_PASSWORD') }}" + - name: undercloud_fqdn + ansible_var: "{{ tripleo_undercloud_fqdn | default('') }}" + env_var: "{{ lookup('env', 'UNDERCLOUD_FQDN') }}" + + - name: set IPA server facts + set_fact: + ipa_principal: "{{ tripleo_ipa_principal | default(lookup('env', 'IPA_PRINCIPAL')) }}" + ipa_password: "{{ tripleo_ipa_password | default(lookup('env', 'IPA_PASSWORD')) }}" + undercloud_fqdn: "{{ tripleo_undercloud_fqdn | default(lookup('env', 'UNDERCLOUD_FQDN'))}}" + + - name: set nova service user facts + set_fact: + nova_service: "nova/{{ undercloud_fqdn }}" + + - name: add nova service + ipa_service: + name: "{{ nova_service }}" + ipa_user: "{{ ipa_principal }}" + ipa_pass: "{{ ipa_password }}" + state: present + force: true + + - name: add nova host manager role + ipa_role: + name: Nova Host Manager + ipa_user: "{{ ipa_principal }}" + ipa_pass: "{{ ipa_password }}" + description: Nova Host Manager + privilege: + - Nova Host Management + service: + - "{{ nova_service }}" diff --git a/tripleo_ipa/playbooks/ipa-server-create-role.yaml b/tripleo_ipa/playbooks/ipa-server-create-role.yaml new file mode 100644 index 0000000..a5650c3 --- /dev/null +++ b/tripleo_ipa/playbooks/ipa-server-create-role.yaml @@ -0,0 +1,111 @@ +--- +# Copyright 2020 Red Hat, Inc. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# This playbook adds a role with the correct privileges needed by tripleo-ipa +# and TLS-e to add hosts and services to the IPA server. The operations in +# this playbook likely need admin privileges and should be executed on an +# IPA client. This playbook only needs to be run once per IPA server as +# multiple tripleo deployments can utilize the same role. + +- name: Playbook to setup an IPA role with correct privileges for TLS-e + connection: "{{ (tripleo_ipa_host is defined) | ternary('ssh', 'local') }}" + hosts: "{{ tripleo_ipa_host | default('localhost') }}" + tasks: + - name: ensure definitions + fail: + msg: >- + {{ item }} is undefined + when: not item.ansible_var and not item.env_var + with_items: + - name: ipa_principal + ansible_var: "{{ ipa_principal | default('') }}" + env_var: "{{ lookup('env', 'IPA_PRINCIPAL') }}" + - name: ipa_password + ansible_var: "{{ ipa_password | default('') }}" + env_var: "{{ lookup('env', 'IPA_PASSWORD') }}" + + - name: set IPA server facts + set_fact: + ipa_principal: "{{ tripleo_ipa_principal | default(lookup('env', 'IPA_PRINCIPAL')) }}" + ipa_password: "{{ tripleo_ipa_password | default(lookup('env', 'IPA_PASSWORD')) }}" + + - name: set keytab permissions facts + set_fact: + tripleo_ipa_perms: + - {name: 'Modify host password', right: "write", type: "host", attrs: "userpassword"} + - {name: 'Write host certificate', right: "write", type: "host", attrs: "usercertificate"} + - {name: 'Modify host userclass', right: "write", type: "host", attrs: "userclass"} + - {name: 'Modify service managedBy attribute', right: "write", type: "service", attrs: "managedby"} + tripleo_ipa_privilege_perms: + - 'System: add hosts' + - 'System: remove hosts' + - 'Modify host password' + - 'Modify host userclass' + - 'System: Modify hosts' + - 'Modify service managedBy attribute' + - 'System: Add krbPrincipalName to a Host' + - 'System: Add Services' + - 'System: Remove Services' + - 'Revoke certificate' + - 'System: manage host keytab' + - 'System: Manage host certificates' + - 'System: modify services' + - 'System: manage service keytab' + - 'System: read dns entries' + - 'System: remove dns entries' + - 'System: add dns entries' + - 'System: update dns entries' + - 'System: Modify Realm Domains' + - 'Retrieve Certificates from the CA' + + # unfortunately we don't have ansible module yet to create perms + # TODO(d34dh0r53): we should be able to obtain a token via curl + # which will allow us to perform these operations without a kinit first. + - name: add nova host management permissions + shell: | + ipa permission-find "{{ item.name }}" + if [ $? -ne 0 ]; then + ipa permission-add "{{ item.name }}" --right "{{ item.right }}" \ + --type "{{ item.type }}" --attrs "{{ item.attrs }}" + fi + loop: "{{ tripleo_ipa_perms|flatten(levels=1) }}" + + # unfortunately we don't have ansible module yet to create privileges + - name: add nova host privilege + shell: | + ipa privilege-find 'Nova Host Management' + if [ $? -ne 0 ]; then + ipa privilege-add --desc='Nova Host Management' 'Nova Host Management' + fi + + - name: add permissions to the nova host privilege + shell: | + ipa privilege-add-permission 'Nova Host Management' \ + --permission "{{ item }}" + register: add_perm_command + failed_when: + - add_perm_command.rc !=0 + - '"This entry is already a member" not in add_perm_command.stdout' + loop: "{{ tripleo_ipa_privilege_perms|flatten(levels=1) }}" + + - name: add nova host manager role + ipa_role: + name: Nova Host Manager + description: Nova Host Manager + ipa_user: "{{ ipa_principal }}" + ipa_pass: "{{ ipa_password }}" + privilege: + - Nova Host Management diff --git a/tripleo_ipa/playbooks/ipa-server-register-undercloud.yaml b/tripleo_ipa/playbooks/ipa-server-register-undercloud.yaml new file mode 100644 index 0000000..e5d76e4 --- /dev/null +++ b/tripleo_ipa/playbooks/ipa-server-register-undercloud.yaml @@ -0,0 +1,67 @@ +--- +# Copyright 2020 Red Hat, Inc. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# This playbook registers the undercloud host as an IPA client and provices a +# one time password to be used in the undercloud configuration file. This needs +# to be executed by a user that has permissions to add services and to add them +# to roles. This needs to be run once per openstack deployment. + +- name: Playbook to register the undercloud node and generate OTP + connection: "{{ (tripleo_ipa_host is defined) | ternary('ssh', 'local') }}" + hosts: "{{ tripleo_ipa_host | default('localhost') }}" + remote_user: root + tasks: + - name: ensure definitions + fail: + msg: >- + {{ item }} is undefined + when: not item.ansible_var and not item.env_var + with_items: + - name: ipa_principal + ansible_var: "{{ ipa_principal | default('') }}" + env_var: "{{ lookup('env', 'IPA_PRINCIPAL') }}" + - name: ipa_password + ansible_var: "{{ ipa_password | default('') }}" + env_var: "{{ lookup('env', 'IPA_PASSWORD') }}" + - name: undercloud_fqdn + ansible_var: "{{ tripleo_undercloud_fqdn | default('') }}" + env_var: "{{ lookup('env', 'UNDERCLOUD_FQDN') }}" + - name: undercloud_description + ansible_var: "{{ tripleo_undercloud_description | default('Undercloud') }}" + env_var: "{{ lookup('env', 'UNDERCLOUD_DESCRIPTION') }}" + + - name: set IPA server facts + set_fact: + ipa_principal: "{{ tripleo_ipa_principal | default(lookup('env', 'IPA_PRINCIPAL')) }}" + ipa_password: "{{ tripleo_ipa_password | default(lookup('env', 'IPA_PASSWORD')) }}" + undercloud_fqdn: "{{ tripleo_undercloud_fqdn | default(lookup('env', 'UNDERCLOUD_FQDN')) }}" + undercloud_description: "{{ tripleo_undercloud_description | default(lookup('env', 'UNDERCLOUD_DESCRIPTION')) }}" + + - name: register undercloud as IPA client + ipa_host: + ipa_user: "{{ ipa_principal }}" + ipa_pass: "{{ ipa_password }}" + fqdn: "{{ undercloud_fqdn }}" + random_password: true + force: true + register: host_otp + + - name: provide OTP generated by IPA server + debug: + msg: + - "The OTP provided by the IPA server is {{ host_otp.host.randompassword }}" + - "Please add the following to your undercloud.conf:" + - "ipa_otp = {{ host_otp.host.randompassword }}"