Browse Source

Merge pull request #838 from abhishek-sa1/control_plane_security

Issue #837: 389-ds installation in leap for Management Station
Sujit Jadhav 3 năm trước cách đây
mục cha
commit
dcf706428b

+ 1 - 1
control_plane/input_params/base_vars.yml

@@ -22,7 +22,7 @@ ansible_conf_file_path: /etc/ansible
 # This variable is used to support the management network container.
 # This container configures IP for all the different devices like idrac, switches and powervaults.
 # Accepted value: "true" or "false"
-# Default value: "true"
+# Default value: "false"
 device_config_support: false
 
 # This variable is used to enable idrac support

+ 2 - 1
control_plane/input_params/login_vars.yml

@@ -100,6 +100,7 @@ powervault_me4_password: ""
 # The password must not contain -,\, ',"
 ms_directory_manager_password: ""
 
+# ms_kerberos_admin_password used by IPA admin user in Rocky OS and used by 389-ds for kerberos admin password in leap OS
 # The IPA server requires an administrative user, named 'admin'.
 # This user is a regular system account used for IPA server administration
-ms_ipa_admin_password: ""
+ms_kerberos_admin_password: ""

+ 1 - 1
control_plane/roles/control_plane_common/tasks/fetch_base_inputs.yml

@@ -42,7 +42,7 @@
 
 - name: Validate management network nic
   assert:
-    that: mngmnt_network_nic | length < 1
+    that: mngmnt_network_nic | length > 1
     fail_msg: "{{ input_base_failure_msg }}"
   when: device_config_support
   

+ 1 - 0
control_plane/roles/control_plane_common/tasks/fetch_security_inputs.yml

@@ -69,6 +69,7 @@
   command: hostname -d
   register: domain_name_set
   changed_when: false
+  failed_when: false
   tags: [ validate, security ]
 
 - name: Verify the domain name is not blank in hostname

+ 8 - 8
control_plane/roles/control_plane_common/tasks/verify_login_inputs.yml

@@ -48,7 +48,7 @@
   tags: [ validate, security ]
   when:
     - ( ms_directory_manager_password | length < 1 or
-      ms_ipa_admin_password | length < 1 ) and
+      ms_kerberos_admin_password | length < 1 ) and
       enable_security_support
 
 - name: Assert provision credentials
@@ -239,15 +239,15 @@
   when: enable_security_support
   tags: [ validate, security ]
 
-- name: Assert ms_ipa_admin_password
+- name: Assert ms_kerberos_admin_password
   assert:
     that:
-      - ms_ipa_admin_password | length > min_length | int - 1
-      - ms_ipa_admin_password | length < max_length | int + 1
-      - '"-" not in ms_ipa_admin_password '
-      - '"\\" not in ms_ipa_admin_password '
-      - '"\"" not in ms_ipa_admin_password '
-      - " \"'\" not in ms_ipa_admin_password "
+      - ms_kerberos_admin_password | length > min_length | int - 1
+      - ms_kerberos_admin_password | length < max_length | int + 1
+      - '"-" not in ms_kerberos_admin_password '
+      - '"\\" not in ms_kerberos_admin_password '
+      - '"\"" not in ms_kerberos_admin_password '
+      - " \"'\" not in ms_kerberos_admin_password "
     success_msg: "{{ success_msg_ipa_admin_pwd }}"
     fail_msg: "{{ fail_msg_ipa_admin_pwd }}"
   when: enable_security_support

+ 19 - 7
control_plane/roles/control_plane_common/vars/main.yml

@@ -79,10 +79,10 @@ fail_msg_ethernet_credentials: "Failed. Incorrect ethernet_switch_username or et
 fail_msg_ib_credentials: "Failed. Incorrect ib_username or ib_password format provided in login_vars.yml"
 fail_msg_me4_credentials: "Failed. Incorrect powervault_me4_username or powervault_me4_password format provided in login_vars.yml"
 login_security_config_failure_msg: "Failed. Please provide the required passwords in login_vars.yml for installing ipa"
-success_msg_dir_manager_password: "directory_manager_password successfully validated"
-fail_msg_dir_manager_password: "Failed. Incorrect format provided for directory_manager_password"
-success_msg_ipa_admin_pwd: "ipa_admin_password successfully validated"
-fail_msg_ipa_admin_pwd: "Failed. Incorrect format provided for ipa_admin_password"
+success_msg_dir_manager_password: "ms_directory_manager_password successfully validated"
+fail_msg_dir_manager_password: "Failed. Incorrect format provided for ms_directory_manager_password"
+success_msg_ipa_admin_pwd: "ms_kerberos_admin_password successfully validated"
+fail_msg_ipa_admin_pwd: "Failed. Incorrect format provided for ms_kerberos_admin_password"
 
 # Usage: verify_omnia_params.yml
 config_filename: "omnia_config.yml"
@@ -103,8 +103,10 @@ fail_msg_directory_manager_password: "Failed. Incorrect format provided for dire
 success_msg_ipa_admin_password: "ipa_admin_password successfully validated"
 fail_msg_ipa_admin_password: "Failed. Incorrect format provided for ipa_admin_password"
 omnia_input_config_failure_msg: "Failed. Please provide all the required parameters in omnia_config.yml for for login_node"
-login_node_required_success_msg: "Login_node_required successfully validated"
-login_node_required_fail_msg: "Failed. login_node_required can be either true or false"
+login_node_required_success_msg: "login_node_required successfully validated"
+login_node_required_fail_msg: "Failed. login_node_required should be either true or false"
+secure_login_node_success_msg: "enable_secure_login_node successfully validated"
+secure_login_node_fail_msg: "Failed. enable_secure_login_node should be either true or false"
 
 # Usage: fetch_base_inputs.yml
 base_vars_filename: "input_params/base_vars.yml"
@@ -154,10 +156,20 @@ provision_state_success_msg: "provision_state validated"
 provision_state_fail_msg: "Failed. Incorrect provision_state selected. Supported only stateful"
 enable_security_support_success_msg: "enable_security_support validated"
 enable_security_support_fail_msg: "Failed. enable_security_support only accepts boolean values true or false"
+dns_empty_warning_msg: "[WARNING] primary_dns and secondary_dns is empty. DHCP routing in compute nodes for internet access won't be configured. Stop and re-run control_plane.yml, if DHCP routing is required."
+primary_dns_empty_msg: "primary_dns is empty and secondary_dns provided. If one dns entry present, provide primary_dns only."
+primary_dns_success_msg: "primary_dns successfully validated"
+primary_dns_fail_msg: "Failed. Incorrect primary_dns provided in base_vars.yml"
+primary_dns_not_reachable_msg: "Failed. primary_dns is not reachable. Provide valid dns"
+secondary_dns_success_msg: "secondary_dns successfully validated"
+secondary_dns_fail_msg: "Failed. Incorrect secondary_dns provided in base_vars.yml"
+secondary_dns_not_reachable_msg: "[WARNING] secondary_dns is not reachable"
+ping_search_key: "100% packet loss"
 success_device_config: " Success. Device_config_support has valid values"
 fail_device_config: "Failed. Give a valid value in device_config_support"
 device_ip_list_not_supported: "[Warning] Device_ip_list is invalid as minimum idrac_support should be true"
 mgmnt_device_fail: "Failed. Container already present. Either delete the container or make device_config_support as true"
+
 # Usage: device_config_validations
 success_msg_ib: "Infiniband variables validated"
 fail_msg_ib: "Failed. Please provide all the InfiniBand related parameters in base_vars.yml"
@@ -232,7 +244,7 @@ server_domain_name_success: "Domain name in server hostname validated"
 server_domain_name_fail: "Failed. Domain name set is not same as domain name in security_vars.yml"
 hosts_file_path: /etc/hosts
 hosts_file_mode: "0644"
-hostname_blank_msg: "Failed. Domain name is not set in hostname It should have hostname.domain_name format"
+hostname_blank_msg: "Failed. Domain name is not set in hostname or missing entries in /etc/hosts. It should have hostname.domain_name format."
 server_hostname_success: "Hostname in server hostname validated"
 server_hostname_fail: "Failed. Hostname set is not valid"
 max_failures_success_msg: "max_failures successfully validated"

+ 7 - 0
control_plane/roles/control_plane_security/files/temp_dsrc

@@ -0,0 +1,7 @@
+# /root/.dsrc file for administering the ldap1 instance
+
+[ldap1]
+
+uri = ldapi://%%2fvar%%2frun%%2fslapd-ldap1.socket
+basedn = dc=omnia,dc=test
+binddn = cn=Directory Manager

+ 23 - 0
control_plane/roles/control_plane_security/files/temp_krb5.conf

@@ -0,0 +1,23 @@
+[libdefaults]
+dns_canonicalize_hostname = false
+rdns = false
+default_realm = OMNIA.TEST
+ticket_lifetime = 24h
+renew_lifetime = 7d
+
+[realms]
+OMNIA.TEST = {
+kdc = hostname.omnia.test:88
+admin_server = hostname.omnia.test
+default_domain = omnia.test
+}
+
+[logging]
+kdc = FILE:/var/log/krb5kdc.log
+admin_server = FILE:/var/log/kadmind.log
+default = SYSLOG:NOTICE:DAEMON
+
+[domain_realm]
+.omnia.test = omnia.test
+omnia.test = omnia.test
+hostname.omnia.test = OMNIA.TEST

+ 11 - 0
control_plane/roles/control_plane_security/files/temp_ldap1.inf

@@ -0,0 +1,11 @@
+[general]
+config_version = 2 
+
+[slapd]
+root_password = password
+self_sign_cert = True 
+instance_name = ldap1
+
+[backend-userroot]
+sample_entries = yes 
+suffix = dc=omnia,dc=test

+ 1 - 2
control_plane/roles/control_plane_security/tasks/check_prerequisites.yml

@@ -26,7 +26,6 @@
   set_fact:
     server_hostname_ms: "{{ new_serv_hostname.stdout }}"
 
-    
 - name: Check freeipa ui accessible or not
   uri:
     url: "https://{{ server_hostname_ms }}"
@@ -36,7 +35,7 @@
   failed_when: false
 
 - name: Check freeipa admin authentication
-  shell: set -o pipefail && echo $'{{ ms_ipa_admin_password }}' | kinit {{ ms_ipa_admin_username }}
+  shell: set -o pipefail && echo $'{{ ms_kerberos_admin_password }}' | kinit {{ ms_ipa_admin_username }}
   register: freeipa_authentication
   no_log: true
   changed_when: false

+ 198 - 0
control_plane/roles/control_plane_security/tasks/install_389ds.yml

@@ -0,0 +1,198 @@
+#  Copyright 2022 Dell Inc. or its subsidiaries. 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.
+---
+
+- name: Initialize ds389_status
+  set_fact:
+    ds389_status: false
+
+- name: Fetch hostname
+  command: hostname
+  register: new_serv_hostname
+  changed_when: false
+
+- name: Set fact for server hostname
+  set_fact:
+    server_hostname_ms: "{{ new_serv_hostname.stdout }}"
+
+- name: Check password policy in 389-ds
+  command: dsconf -w {{ ms_directory_manager_password }} -D "cn=Directory Manager" ldap://{{ server_hostname_ms }} pwpolicy get
+  changed_when: true
+  failed_when: false
+  no_log: true
+  register: ds389_pwpolicy_check
+
+- name: Check ds389_status admin authentication
+  shell: set -o pipefail && echo {{ ms_kerberos_admin_password }} | kinit {{ ms_ipa_admin_username }}
+  changed_when: false
+  failed_when: false
+  no_log: true
+  register: ds389_status_authentication
+ 
+- name: Modify ds389_status
+  set_fact:
+    ds389_status: true
+  when: 
+    - ds389_status_authentication.rc == 0
+    - ds389_pwpolicy_search_key in ds389_pwpolicy_check.stdout
+
+- block:
+    - name: Install 389-ds
+      zypper:
+        name: "{{ ds389_packages }}"
+        state: present 
+
+    - name: Create the ldap1.inf file
+      copy:
+        src: "{{ role_path }}/files/temp_ldap1.inf"
+        dest: "{{ ldap1_config_path }}"
+        mode: "{{ file_mode }}"       
+
+    - name: Configure ldap1.inf with domain name
+      lineinfile:
+        path: "{{ ldap1_config_path }}"
+        regexp: "^suffix = dc=omnia,dc=test"
+        line: "suffix = dc={{ domain_name.split('.')[0] }},dc={{ domain_name.split('.')[1] }}"
+
+    - name: Configure ldap1.inf with directory manager password
+      lineinfile:
+        path: "{{ ldap1_config_path }}"
+        regexp: "^root_password = password"
+        line: "root_password = {{ ms_directory_manager_password }}"  
+
+    - name: Check ldap instance is running or not
+      command: dsctl {{ ldap_instance }} status
+      changed_when: false
+      failed_when: false
+      register: ldap1_status
+
+    - name: Creating 389 directory server instance
+      shell: dscreate -v from-file {{ ldap1_config_path }} | tee {{ ldap1_output_path }}
+      changed_when: true
+      when: ldap1_search_key in ldap1_status.stdout
+      
+    - name: Remove the ldap1.inf
+      file:
+        path: "{{ ldap1_config_path }}"
+        state: absent
+
+    - name: Start dirsrv service
+      systemd:
+        name: "dirsrv@{{ ldap_instance }}.service"
+        state: started
+        enabled: yes
+
+    - name: Create the dsrc file
+      copy:
+        src: "{{ role_path }}/files/temp_dsrc"
+        dest: "{{ dsrc_path }}"
+        mode: "{{ file_mode }}"
+
+    - name: Configure dsrc file with domain name
+      lineinfile:
+        path: "{{ dsrc_path }}"
+        regexp: "^basedn = dc=omnia,dc=test"
+        line: "basedn = dc={{ domain_name.split('.')[0] }},dc={{ domain_name.split('.')[1] }}"
+
+    - name: Permit traffic in default zone for ldap and ldaps service
+      firewalld:
+        service: "{{ item }}"
+        permanent: yes
+        state: enabled
+      with_items: "{{ ldap_services }}"
+
+    - name: Reload firewalld service
+      systemd:
+        name: firewalld
+        state: reloaded
+
+    - name: Install kerberos packages
+      zypper:
+        name: "{{ kerberos_packages }}"
+        state: present 
+
+    - name: Check kerberos principal is created or not
+      stat:
+        path: "{{ kerberos_principal_path }}"
+      register: principal_status
+
+    - name: Create the kerberos conf file
+      copy:
+        src: "{{ role_path }}/files/temp_krb5.conf"
+        dest: "{{ kerberos_conf_path }}"
+        mode: "{{ file_mode }}"
+
+    - name: Configure kerberos conf file with domain name
+      replace:
+        path: "{{ kerberos_conf_path }}"
+        regexp: "omnia.test"
+        replace: "{{ domain_name }}"
+
+    - name: Configure kerberos conf file with realm name
+      replace:
+        path: "{{ kerberos_conf_path }}"
+        regexp: "OMNIA.TEST"
+        replace: "{{ realm_name }}"
+
+    - name: Configure kerberos conf file with hostname
+      replace:
+        path: "{{ kerberos_conf_path }}"
+        regexp: "hostname"
+        replace: "{{ short_hostname.stdout }}"
+
+    - block:
+        - name: Setting up the kerberos database
+          command: "kdb5_util -r {{ realm_name }} -P {{ ms_directory_manager_password }} create -s"
+          no_log: true
+          changed_when: true
+          register: setting_database
+          environment:
+            PATH: "{{ ansible_env.PATH }}:{{ kerberos_env_path }}"
+          when: not principal_status.stat.exists
+      rescue:
+        - name: Setting up the kerberos database failed
+          fail:
+            msg: "Error: {{ setting_database.stderr }}"
+
+    - name: Start krb5kdc and kadmind services
+      systemd:
+        name: "{{ item }}"
+        state: started
+        enabled: yes
+      with_items:
+        - krb5kdc
+        - kadmind
+
+    - block:
+        - name: Create admin principal
+          command: kadmin.local -q "ank -pw {{ ms_kerberos_admin_password }} admin"
+          no_log: true
+          changed_when: true
+          register: create_admin_principal
+          environment:
+            PATH: "{{ ansible_env.PATH }}:{{ kerberos_env_path }}"
+      rescue:
+        - name: Create admin principal failed
+          fail:
+            msg: "Error: {{ create_admin_principal.stderr }}"
+
+    - name: Authenticate as admin
+      shell: set -o pipefail && echo {{ ms_kerberos_admin_password }} | kinit admin
+      no_log: true
+      changed_when: false
+    
+    - name: Configure password policy in 389-ds
+      command: dsconf -w {{ ms_directory_manager_password }} -D "cn=Directory Manager" ldap://{{ server_hostname_ms }} pwpolicy set --pwdlockoutduration {{ lockout_duration }} --pwdmaxfailures {{ max_failures }} --pwdresetfailcount {{ failure_reset_interval }}
+      changed_when: true
+  when: not ds389_status

+ 14 - 8
control_plane/roles/control_plane_security/tasks/install_ipa_server.yml

@@ -13,15 +13,21 @@
 #  limitations under the License.
 ---
 
-- name: Install ipa server in CentOS or Rocky
-  command: >-
-    ipa-server-install -n '{{ domain_name }}' --hostname='{{ server_hostname_ms }}' -a '{{ ms_ipa_admin_password }}'
-    -p '{{ ms_directory_manager_password }}' -r '{{ realm_name }}' --setup-dns --no-forwarders --no-reverse --no-ntp -U
-  changed_when: true
-  no_log: true
-  
+- block:
+    - name: Install ipa server in CentOS or Rocky
+      command: >-
+        ipa-server-install -n '{{ domain_name }}' --hostname='{{ server_hostname_ms }}' -a '{{ ms_kerberos_admin_password }}'
+        -p '{{ ms_directory_manager_password }}' -r '{{ realm_name }}' --setup-dns --no-forwarders --no-reverse --no-ntp -U
+      changed_when: true
+      no_log: true
+      register: install_ipa_server
+  rescue:
+    - name: Install ipa server failed
+      fail:
+        msg: "Error: {{ install_ipa_server.stderr_lines }}"
+
 - name: Authenticate as admin
-  shell: set -o pipefail && echo $'{{ ms_ipa_admin_password }}' | kinit {{ ms_ipa_admin_username }}
+  shell: set -o pipefail && echo $'{{ ms_kerberos_admin_password }}' | kinit {{ ms_ipa_admin_username }}
   no_log: true
   changed_when: false
 

+ 3 - 3
control_plane/roles/control_plane_security/tasks/ipa_configuration.yml

@@ -20,7 +20,7 @@
     lockouttime: "{{ lockout_duration }}"
     ipa_host: "{{ server_hostname_ms }}"
     ipa_user: "{{ ms_ipa_admin_username }}"
-    ipa_pass: "{{ ms_ipa_admin_password }}"
+    ipa_pass: "{{ ms_kerberos_admin_password }}"
 
 - name: Create sysadmin group
   community.general.ipa_group:
@@ -29,7 +29,7 @@
     state: present
     ipa_host: "{{ server_hostname_ms }}"
     ipa_user: "{{ ms_ipa_admin_username }}"
-    ipa_pass: "{{ ms_ipa_admin_password }}"
+    ipa_pass: "{{ ms_kerberos_admin_password }}"
     
 - name: Create sysadmin_sudo rule
   community.general.ipa_sudorule:
@@ -43,4 +43,4 @@
       - "{{ sysadmin_user_group }}"
     ipa_host: "{{ server_hostname_ms }}"
     ipa_user: "{{ ms_ipa_admin_username }}"
-    ipa_pass: "{{ ms_ipa_admin_password }}"
+    ipa_pass: "{{ ms_kerberos_admin_password }}"

+ 8 - 3
control_plane/roles/control_plane_security/tasks/main.yml

@@ -35,6 +35,11 @@
         - name: FreeIPA configuration
           include_tasks: ipa_configuration.yml
       when: os_supported_leap not in mgmt_os
+    
+    - block:
+        - name: Install 389 directory server
+          include_tasks: install_389ds.yml
+      when: os_supported_leap in mgmt_os
       
     - name: Install snoopy
       include_tasks: install_snoopy.yml
@@ -42,10 +47,10 @@
     - name: Install psacct/acct
       include_tasks: user_monitor.yml
 
-    - name: Session timeout configuration
-      include_tasks: session_timeout.yml
-
     - name: Alert configuration
       include_tasks: configure_alerting.yml
       when: alert_email_address | length > 1
+     
+    - name: Session timeout configuration
+      include_tasks: session_timeout.yml
   when: enable_security_support

+ 22 - 0
control_plane/roles/control_plane_security/vars/main.yml

@@ -78,3 +78,25 @@ snoopy_path: /var/lib
 # Usage: user_monitor.yml
 psacct: psacct
 acct: acct
+
+# Usage: install_389ds.yml
+ds389_packages:
+  - 389-ds
+  - db48-utils
+  - python3-argcomplete
+ldap1_search_key: "No such instance"
+ds389_pwpolicy_search_key: "passwordlockoutduration: {{ lockout_duration }}"
+ldap1_config_path: "{{ role_path }}/files/ldap1.inf"
+ldap_instance: ldap1
+ldap1_output_path: /var/log/ldap1_output.txt
+ldap_services:
+  - ldap
+  - ldaps
+dsrc_path: /root/.dsrc
+kerberos_packages:
+  - krb5
+  - krb5-server
+  - krb5-client
+kerberos_principal_path: /var/lib/kerberos/krb5kdc/principal
+kerberos_conf_path: /etc/krb5.conf
+kerberos_env_path: /usr/lib/mit/sbin/

+ 1 - 1
roles/cluster_validation/tasks/fetch_control_plane_credentials.yml

@@ -39,7 +39,7 @@
 - block:
     - name: Save variables of ipa server from Management Station
       set_fact:
-        ms_ipa_admin_password: '{{ ms_ipa_admin_password }}'
+        ms_ipa_admin_password: '{{ ms_kerberos_admin_password }}'
       no_log: True
 
     - name: Include ipa server hostname and domain name