Explorar el Código

Issue #810 Security docs out of date

Signed-off-by: cgoveas <cassandra.goveas@dell.com>
cgoveas hace 3 años
padre
commit
52453cc565
Se han modificado 31 ficheros con 819 adiciones y 104 borrados
  1. 13 2
      .all-contributorsrc
  2. 6 3
      README.md
  3. 2 2
      control_plane/input_params/login_vars.yml
  4. 6 0
      control_plane/input_params/security_vars.yml
  5. 77 0
      control_plane/roles/control_plane_common/tasks/fetch_security_inputs.yml
  6. 16 16
      control_plane/roles/control_plane_common/tasks/verify_login_inputs.yml
  7. 14 1
      control_plane/roles/control_plane_common/vars/main.yml
  8. 62 0
      control_plane/roles/control_plane_security/files/auth_failure_check.yml
  9. 1 15
      control_plane/roles/control_plane_security/tasks/check_prerequisites.yml
  10. 35 0
      control_plane/roles/control_plane_security/tasks/configure_alerting.yml
  11. 1 4
      control_plane/roles/control_plane_security/tasks/enable_dnf_module.yml
  12. 0 5
      control_plane/roles/control_plane_security/tasks/firewall_settings.yml
  13. 14 8
      control_plane/roles/control_plane_security/tasks/install_ipa_server.yml
  14. 39 0
      control_plane/roles/control_plane_security/tasks/install_snoopy.yml
  15. 6 6
      control_plane/roles/control_plane_security/tasks/ipa_configuration.yml
  16. 28 19
      control_plane/roles/control_plane_security/tasks/main.yml
  17. 26 0
      control_plane/roles/control_plane_security/tasks/user_monitor.yml
  18. 23 1
      control_plane/roles/control_plane_security/vars/main.yml
  19. 1 1
      control_plane/roles/webui_grafana/tasks/plugins.yml
  20. 7 0
      control_plane/roles/webui_grafana/tasks/pre-requisites.yml
  21. 1 0
      control_plane/roles/webui_grafana/vars/main.yml
  22. 5 10
      docs/INSTALL_OMNIA_CONTROL_PLANE.md
  23. 17 0
      docs/Security/Enable_Security_LoginNode.md
  24. 22 0
      telemetry/add_node_idrac.yml
  25. 6 1
      telemetry/roles/common/tasks/pre-requisites.yml
  26. 5 0
      telemetry/roles/common/vars/main.yml
  27. 75 0
      telemetry/roles/idrac_telemetry/tasks/filter_idrac.yml
  28. 297 0
      telemetry/roles/idrac_telemetry/tasks/initiate_telemetry.yml
  29. 4 0
      telemetry/roles/idrac_telemetry/tasks/main.yml
  30. 1 1
      telemetry/roles/idrac_telemetry/tasks/mysqldb_deployment.yml
  31. 9 9
      telemetry/telemetry.yml

+ 13 - 2
.all-contributorsrc

@@ -20,7 +20,8 @@
         "mentoring",
         "design",
         "review",
-        "talk"
+        "talk",
+        "bug"
       ]
     },
     {
@@ -74,7 +75,8 @@
       "avatar_url": "https://avatars.githubusercontent.com/u/73195862?v=4",
       "profile": "https://github.com/sakshiarora13",
       "contributions": [
-        "code"
+        "code",
+        "bug"
       ]
     },
     {
@@ -343,6 +345,15 @@
       "contributions": [
         "code"
       ]
+    },
+    {
+      "login": "githubyongchen",
+      "name": "Yong Chen",
+      "avatar_url": "https://avatars.githubusercontent.com/u/5414112?v=4",
+      "profile": "https://github.com/githubyongchen",
+      "contributions": [
+        "design"
+      ]
     }
   ],
   "contributorsPerLine": 7,

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 6 - 3
README.md


+ 2 - 2
control_plane/input_params/login_vars.yml

@@ -98,8 +98,8 @@ powervault_me4_password: ""
 # and will be added to the instance of directory server created for IPA.
 # The password must be at least 8 characters long
 # The password must not contain -,\, ',"
-directory_manager_password: ""
+ms_directory_manager_password: ""
 
 # The IPA server requires an administrative user, named 'admin'.
 # This user is a regular system account used for IPA server administration
-ipa_admin_password: ""
+ms_ipa_admin_password: ""

+ 6 - 0
control_plane/input_params/security_vars.yml

@@ -11,6 +11,7 @@
 #  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 variable is used to accept the domain name the user intends to configure
 # Eg: ipa.test
@@ -44,3 +45,8 @@ lockout_duration: 10
 # Min: 90
 # Max: 180
 session_timeout: 180
+
+# Email address used for sending alerts in case of authentication failure
+# If this variable is left blank, authentication failure alerts will be disabled.
+# Required value
+alert_email_address: ""

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

@@ -43,6 +43,67 @@
     success_msg: "{{ realm_success_msg }}"
     fail_msg: "{{ realm_fail_msg }}"
   tags: [ validate, security ]
+  
+- name: Fetch the short hostname
+  command: hostname -s
+  register: short_hostname
+  changed_when: false
+  tags: [ validate, security ]
+
+- name: Verify the hostname is not blank in hostname
+  fail:
+    msg: " {{ hostname_blank_msg }}"
+  when: short_hostname.stdout | length < 1
+  tags: [ validate, security ]
+
+- name: Validate the host name
+  assert:
+    that:
+      - short_hostname.stdout is regex(("^(([a-z]|[a-z][a-z0-9\-]*[a-z0-9])\.)*([a-z]|[a-z][a-z0-9\-]*[a-z0-9])$"))
+      - short_hostname.stdout != "localhost"
+    success_msg: "{{ server_hostname_success }}"
+    fail_msg: "{{ server_hostname_fail }}"
+  tags: [ validate, security ]
+
+- name: Fetch the domain name
+  command: hostname -d
+  register: domain_name_set
+  changed_when: false
+  tags: [ validate, security ]
+
+- name: Verify the domain name is not blank in hostname
+  fail:
+    msg: " {{ domain_name_blank_msg }}"
+  when: domain_name_set.stdout | length < 1
+  tags: [ validate, security ]
+
+- name: Set fact for the domain name in hostname
+  set_fact:
+    ms_domain_name: "{{ domain_name_set.stdout }}"
+  tags: [ validate, security ]
+
+- name: Validate the domain name set on the host
+  assert:
+    that:
+      - domain_name == ms_domain_name
+    success_msg: "{{ server_domain_name_success }}"
+    fail_msg: "{{ server_domain_name_fail }}"
+  tags: [ validate, security ]
+
+- name: Get the hostname
+  command: hostname
+  register: machine_hostname
+  changed_when: false
+  tags: [ validate, security ]
+
+- name: Add host name in hosts file
+  lineinfile:
+    dest: "{{ hosts_file_path }}"
+    line: "{{ public_ip }} {{ machine_hostname.stdout }}"
+    state: present
+    create: yes
+    mode: "{{ hosts_file_mode }}"
+  tags: [ validate, security ]
 
 - name: Validate max_failures
   assert:
@@ -81,3 +142,19 @@
     success_msg: "{{ session_timeout_success_msg }}"
     fail_msg: "{{ session_timeout_fail_msg }}"
   tags: [ validate, security ]
+
+- name: Validate alert_email_address
+  assert:
+    that:
+      - email_search_key in alert_email_address
+      - alert_email_address | length < email_max_length
+    success_msg: "{{ alert_email_success_msg }}"
+    fail_msg: "{{ alert_email_fail_msg }}"
+  tags: [ validate, security ]
+  when: alert_email_address | length > 1
+
+- name: Warning - alert_email_address is empty
+  debug:
+    msg: "{{ alert_email_warning_msg }}"
+  tags: security
+  when: alert_email_address | length < 1

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

@@ -49,8 +49,8 @@
     msg: "{{ login_input_config_failure_msg }} for ipa server installation"
   tags: [ validate, security ]
   when:
-    - ( directory_manager_password | length < 1 or
-      ipa_admin_password | length < 1 ) and
+    - ( ms_directory_manager_password | length < 1 or
+      ms_ipa_admin_password | length < 1 ) and
       enable_security_support
 
 - name: Assert provision credentials
@@ -220,29 +220,29 @@
   when: powervault_support
   tags: [ validate, network-device ]
 
-- name: Assert directory_manager_password
+- name: Assert ms_directory_manager_password
   assert:
     that:
-      - directory_manager_password | length > min_length | int - 1
-      - directory_manager_password | length < max_length | int + 1
-      - '"-" not in directory_manager_password '
-      - '"\\" not in directory_manager_password '
-      - '"\"" not in directory_manager_password '
-      - " \"'\" not in directory_manager_password "
+      - ms_directory_manager_password | length > min_length | int - 1
+      - ms_directory_manager_password | length < max_length | int + 1
+      - '"-" not in ms_directory_manager_password '
+      - '"\\" not in ms_directory_manager_password '
+      - '"\"" not in ms_directory_manager_password '
+      - " \"'\" not in ms_directory_manager_password "
     success_msg: "{{ success_msg_dir_manager_password }}"
     fail_msg: "{{ fail_msg_dir_manager_password }}"
   when: enable_security_support
   tags: [ validate, security ]
 
-- name: Assert ipa_admin_password
+- name: Assert ms_ipa_admin_password
   assert:
     that:
-      - ipa_admin_password | length > min_length | int - 1
-      - ipa_admin_password | length < max_length | int + 1
-      - '"-" not in ipa_admin_password '
-      - '"\\" not in ipa_admin_password '
-      - '"\"" not in ipa_admin_password '
-      - " \"'\" not in ipa_admin_password "
+      - 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 "
     success_msg: "{{ success_msg_ipa_admin_pwd }}"
     fail_msg: "{{ fail_msg_ipa_admin_pwd }}"
   when: enable_security_support

+ 14 - 1
control_plane/roles/control_plane_common/vars/main.yml

@@ -219,6 +219,14 @@ dom_name_success_msg: "domain name successfully validated"
 dom_name_fail_msg: "Failed. Incorrect format provided for domain name in security_vars.yml"
 realm_success_msg: "realm_name successfully validated"
 realm_fail_msg: "Failed. Incorrect realm_name format in security_vars.yml"
+domain_name_blank_msg: "Failed. Domain name is not set in hostname It should have hostname.domain_name format"
+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"
+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"
 max_failures_fail_msg: "Failed. Incorrect max_failures value in security_vars.yml"
 failure_reset_interval_success_msg: "failure_reset_interval successfully validated"
@@ -234,10 +242,15 @@ lockout_duration_min_value: 5
 lockout_duration_max_value: 10
 session_timeout_min_value: 90
 session_timeout_max_value: 180
+alert_email_success_msg: "alert_email_address successfully validated"
+alert_email_fail_msg: "Failed. Incorrect alert_email_address value in security_vars.yml"
+alert_email_warning_msg: "[WARNING] alert_email_address is empty. Authentication failure alerts won't be configured."
+email_max_length: 320
+email_search_key: "@"
 
 # Usage: validate_idrac_vars.yml
 idrac_input_filename: input_params/idrac_vars.yml
 firmware_update_success_msg: "firmware_update_required validated"
 firmware_update_fail_msg: "Failed. firmware_update_required accepts only true or false in idrac_vars.yml"
 poweredge_model_success_msg: "poweredge_model validated"
-poweredge_model_fail_msg: "Failed. poweredge_model is incorrect or unsupported. Please update the list with the supported models in the correct format"
+poweredge_model_fail_msg: "Failed. poweredge_model is incorrect or unsupported. Please update the list with the supported models in the correct format"

+ 62 - 0
control_plane/roles/control_plane_security/files/auth_failure_check.yml

@@ -0,0 +1,62 @@
+#  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: Authentication failure alert mail
+  hosts: localhost
+  connection: local
+  vars:
+    alert_file_path: /tmp/alerting
+    auth_failure_check_time: 60
+    auth_failure_search_key: "authentication failure"
+    auth_failure_info_file: "{{ alert_file_path }}/auth_failure_{{ ansible_date_time.iso8601_basic_short }}.txt"
+    auth_failure_mail_subject: "Alert - Authentication Failure"
+    auth_failure_mail_body: "Attached the authentication failure report"
+    auth_failure_mail_sender: omnia-alert
+    file_mode: 644
+  tasks:
+    - name: Check auth failure in last {{ auth_failure_check_time }} minutes
+      shell: journalctl -u sshd --since "{{ auth_failure_check_time }} minutes ago" | grep "{{ auth_failure_search_key }}"
+      changed_when: false
+      failed_when: false
+      register: auth_failure_check
+
+    - name: Create alerting log directory
+      file:
+        path: "{{ alert_file_path }}"
+        state: directory
+        mode: "{{ file_mode }}"
+
+    - name: Save the authentication failure info
+      copy:
+        dest: "{{ auth_failure_info_file }}"
+        content: |
+          "{{ auth_failure_check.stdout }}"
+        mode: "{{ file_mode }}"
+      when: auth_failure_search_key in auth_failure_check.stdout
+
+    - name: Sent mail on auth failure
+      community.general.mail:
+        subject: "{{ auth_failure_mail_subject }}"
+        body: "{{ auth_failure_mail_body }}"
+        sender: "{{ auth_failure_mail_sender }}"
+        to: "{{ alert_email_address }}"
+        attach:
+          - "{{ auth_failure_info_file }}"
+      when: auth_failure_search_key in auth_failure_check.stdout
+
+    - name: Delete the authentication failure info file
+      file:
+        path: "{{ auth_failure_info_file }}"
+        state: absent

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

@@ -26,20 +26,6 @@
   set_fact:
     server_hostname_ms: "{{ new_serv_hostname.stdout }}"
 
-- name: Create files directory
-  file:
-    path: "{{ role_path }}/files"
-    state: directory
-    mode: "{{ file_mode }}"
-    
-- name: Save the hostname
-  copy:
-    dest: "{{ server_file }}"
-    content: |
-      ipaddress: "{{ public_ip }}"
-      server_hostname: "{{ server_hostname_ms }}"
-      server_domain: "{{ domain_name }}"
-    mode: "{{ file_mode }}"
     
 - name: Check freeipa ui accessible or not
   uri:
@@ -50,7 +36,7 @@
   failed_when: false
 
 - name: Check freeipa admin authentication
-  shell: set -o pipefail && echo $'{{ ipa_admin_password }}' | kinit {{ ipa_admin_username }}
+  shell: set -o pipefail && echo $'{{ ms_ipa_admin_password }}' | kinit {{ ms_ipa_admin_username }}
   register: freeipa_authentication
   no_log: true
   changed_when: false

+ 35 - 0
control_plane/roles/control_plane_security/tasks/configure_alerting.yml

@@ -0,0 +1,35 @@
+#  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: Install mailx and postfix
+  package:
+    name: "{{ mail_packages }}"
+    state: present
+
+- name: Start postfix service
+  systemd:
+    name: postfix
+    state: started
+
+- name: Fetch ansible-playbook path
+  command: whereis ansible-playbook
+  changed_when: false
+  register: ansible_playbook_path
+
+- name: Schedule cron job for alerting
+  cron:
+    name: Auth failure alerting
+    special_time: hourly
+    job: "{{ ansible_playbook_path.stdout.split(' ')[1] }} {{ role_path }}/files/auth_failure_check.yml -e 'alert_email_address={{ alert_email_address }}'"

+ 1 - 4
control_plane/roles/control_plane_security/tasks/enable_dnf_module.yml

@@ -13,9 +13,6 @@
 #  limitations under the License.
 ---
 
-- name: Enable module idm in Rocky or CentOS
+- name: Enable module idm
   command: dnf module enable idm:DL1 -y
   changed_when: false
-  when:
-    - ( os_supported_centos in mgmt_os ) or
-      ( os_supported_rocky in mgmt_os )

+ 0 - 5
control_plane/roles/control_plane_security/tasks/firewall_settings.yml

@@ -17,14 +17,12 @@
   package:
     name: firewalld
     state: present
-  tags: firewalld
 
 - name: Start and enable firewalld
   service:
     name: firewalld
     state: started
     enabled: yes
-  tags: firewalld
 
 - name: Firewall ports addition - tcp/udp ports
   firewalld:
@@ -45,16 +43,13 @@
     - "{{ dns_port2 }}"
     - "{{ ntp_port1 }}"
     - "{{ dt_port1 }}"
-  tags: firewalld
 
 - name: Reload firewalld
   command: firewall-cmd --reload
   changed_when: true
-  tags: firewalld
 
 - name: Stop and disable firewalld
   service:
     name: firewalld
     state: stopped
     enabled: no
-  tags: firewalld

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

@@ -13,18 +13,15 @@
 #  limitations under the License.
 ---
 
-- name: Install ipa server in CentOS > 8 or Rocky 8.4
+- name: Install ipa server in CentOS or Rocky
   command: >-
-    ipa-server-install -n '{{ domain_name }}' --hostname='{{ server_hostname_ms }}' -a '{{ ipa_admin_password }}'
-    -p '{{ directory_manager_password }}' -r '{{ realm_name }}' --setup-dns --no-forwarders --no-reverse --no-ntp -U
+    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
-  when:
-    - ( os_supported_centos in mgmt_os ) or
-      ( os_supported_rocky in mgmt_os )
-
+  
 - name: Authenticate as admin
-  shell: set -o pipefail && echo $'{{ ipa_admin_password }}' | kinit {{ ipa_admin_username }}
+  shell: set -o pipefail && echo $'{{ ms_ipa_admin_password }}' | kinit {{ ms_ipa_admin_username }}
   no_log: true
   changed_when: false
 
@@ -34,3 +31,12 @@
     dest: "{{ resolv_conf_path }}"
     mode: "{{ file_mode }}"
     remote_src: yes
+
+- name: Save the hostname
+  copy:
+    dest: "{{ server_file }}"
+    content: |
+      ipaddress: "{{ hpc_ip }}"
+      server_hostname: "{{ server_hostname_ms }}"
+      server_domain: "{{ domain_name }}"
+    mode: "{{ file_mode }}"

+ 39 - 0
control_plane/roles/control_plane_security/tasks/install_snoopy.yml

@@ -0,0 +1,39 @@
+#  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: Install required packages
+  package:
+    name: "{{ snoopy_packages }}"
+    state: present
+
+- name: Download snoopy package
+  get_url:
+    url: "{{ snoopy_url }}"
+    dest: "{{ snoopy_path }}"
+
+- name: Change permissions
+  file:
+   path: "{{ snoopy_path }}"
+   mode: "{{ snoopy_mode }}"
+
+- name: Run the script
+  shell: sh ./install-snoopy.sh stable
+  args:
+   chdir: "{{ snoopy_path }}"
+  changed_when: false
+
+- name: Enable snoopy
+  command: snoopy-enable
+  changed_when: false

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

@@ -19,8 +19,8 @@
     failinterval: "{{ failure_reset_interval }}"
     lockouttime: "{{ lockout_duration }}"
     ipa_host: "{{ server_hostname_ms }}"
-    ipa_user: "{{ ipa_admin_username }}"
-    ipa_pass: "{{ ipa_admin_password }}"
+    ipa_user: "{{ ms_ipa_admin_username }}"
+    ipa_pass: "{{ ms_ipa_admin_password }}"
 
 - name: Create sysadmin group
   community.general.ipa_group:
@@ -28,8 +28,8 @@
     description: "{{ sysadmin_group_description }}"
     state: present
     ipa_host: "{{ server_hostname_ms }}"
-    ipa_user: "{{ ipa_admin_username }}"
-    ipa_pass: "{{ ipa_admin_password }}"
+    ipa_user: "{{ ms_ipa_admin_username }}"
+    ipa_pass: "{{ ms_ipa_admin_password }}"
     
 - name: Create sysadmin_sudo rule
   community.general.ipa_sudorule:
@@ -42,5 +42,5 @@
     usergroup:
       - "{{ sysadmin_user_group }}"
     ipa_host: "{{ server_hostname_ms }}"
-    ipa_user: "{{ ipa_admin_username }}"
-    ipa_pass: "{{ ipa_admin_password }}"
+    ipa_user: "{{ ms_ipa_admin_username }}"
+    ipa_pass: "{{ ms_ipa_admin_password }}"

+ 28 - 19
control_plane/roles/control_plane_security/tasks/main.yml

@@ -14,29 +14,38 @@
 ---
 
 - block:
-    - name: Check freeipa installed or not
-      include_tasks: check_prerequisites.yml
-
     - block:
-        - name: Add ports of manager and login node to firewall
-          include_tasks: firewall_settings.yml
+        - name: Check freeipa installed or not
+          include_tasks: check_prerequisites.yml
+
+        - block:
+            - name: Add ports of manager and login node to firewall
+              include_tasks: firewall_settings.yml
 
-        - name: Enable module idm in Rocky or Centos >= 8.0
-          include_tasks: enable_dnf_module.yml
+            - name: Enable module idm
+              include_tasks: enable_dnf_module.yml
 
-        - name: Install required packages
-          include_tasks: install_packages.yml
+            - name: Install required packages
+              include_tasks: install_packages.yml
 
-        - name: Install FreeIPA server
-          include_tasks: install_ipa_server.yml
-      when: not freeipa_status
-    
-    - name: FreeIPA configuration
-      include_tasks: ipa_configuration.yml
+            - name: Install FreeIPA server
+              include_tasks: install_ipa_server.yml
+          when: not freeipa_status
+        
+        - name: FreeIPA configuration
+          include_tasks: ipa_configuration.yml
+      when: os_supported_leap not in mgmt_os
+      
+    - name: Install snoopy
+      include_tasks: install_snoopy.yml
+
+    - name: Install psacct/acct
+      include_tasks: user_monitor.yml
 
     - name: Session timeout configuration
       include_tasks: session_timeout.yml
-  when: 
-    - enable_security_support
-    - ( os_supported_centos in mgmt_os ) or
-      ( os_supported_rocky in mgmt_os )
+
+    - name: Alert configuration
+      include_tasks: configure_alerting.yml
+      when: alert_email_address | length > 1
+  when: enable_security_support

+ 26 - 0
control_plane/roles/control_plane_security/tasks/user_monitor.yml

@@ -0,0 +1,26 @@
+#  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: Install psacct on rocky
+  package:
+    name: "{{ psacct }}"
+    state: present
+  when: os_supported_rocky in mgmt_os
+
+- name: Install acct on leap
+  package:
+    name: "{{ acct }}"
+    state: present
+  when: os_supported_leap in mgmt_os

+ 23 - 1
control_plane/roles/control_plane_security/vars/main.yml

@@ -46,7 +46,7 @@ ipa_server_packages:
 # Usage: install_ipa_server.yml
 resolv_conf_path: /etc/resolv.conf
 temp_resolv_conf_path: /tmp/resolv.conf
-ipa_admin_username: admin
+ms_ipa_admin_username: admin
 
 # Usage: ipa_configuration.yml
 sysadmin_sudo_rule: sysadmin_sudo
@@ -56,3 +56,25 @@ sysadmin_group_description: "User group with sudo permission"
 
 # Usage: session_timeout.yml
 sshd_conf_file: /etc/ssh/sshd_config
+
+# Usage: configure_alerting.yml
+mail_packages:
+  - mailx
+  - postfix
+  
+# Usage: install_snoopy.yml
+snoopy_packages:
+  - gcc
+  - gzip
+  - make
+  - procps
+  - socat
+  - tar
+  - wget
+snoopy_mode: 0755
+snoopy_url: https://github.com/a2o/snoopy/raw/install/install/install-snoopy.sh
+snoopy_path: /var/lib
+
+# Usage: user_monitor.yml
+psacct: psacct
+acct: acct

+ 1 - 1
control_plane/roles/webui_grafana/tasks/plugins.yml

@@ -20,7 +20,7 @@
     version: main
 
 - name: Wait for grafana pod to come to ready state
-  command: kubectl wait --for=condition=ready --timeout=10m -n "{{ grafana_namespace }}" pod -l app="{{ grafana_k8s }}"
+  command: kubectl wait --for=condition=ready --timeout="{{ grafana_pod_timeout }}" -n "{{ grafana_namespace }}" pod -l app="{{ grafana_k8s }}"
   changed_when: false
   
 - name: Unzip plugins at grafana-plugins folder

+ 7 - 0
control_plane/roles/webui_grafana/tasks/pre-requisites.yml

@@ -17,6 +17,13 @@
   command: ansible-galaxy collection install "{{ item }}"
   with_items: "{{ collections_name }}"
   changed_when: false
+
+- name: Install PyYAML using pip3
+  pip:
+    name: PyYAML
+    state: present
+    executable: pip3
+    extra_args: --ignore-installed
   
 - name: Install openshift using pip3
   pip:

+ 1 - 0
control_plane/roles/webui_grafana/vars/main.yml

@@ -36,6 +36,7 @@ grafana_http_port: 5000
 grafana_plugins_names: "hpcviz-idvl-hpcc-sankey,hpcviz-idvl-hpcc-parallel-coordinate,hpcviz-idvl-hpcc-spiral-layout,hpcviz-idvl-hpcc-stream-net"
 
 # Usage: plugins.yml
+grafana_pod_timeout: 30m
 plugins_name:
   - parallel-coordinate.zip
   - sankey.zip

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 5 - 10
docs/INSTALL_OMNIA_CONTROL_PLANE.md


+ 17 - 0
docs/Security/Enable_Security_LoginNode.md

@@ -0,0 +1,17 @@
+# Enabling Security on the Login Node
+
+## Prerequisites to enabling security
+
+* Ensure that `enable_secure_login_node` is set to **true** in `omnia_config.yml`
+* Set the following parameters in `omnia_security_config.yml`
+
+|  Parameter Name        |  Default Value  |  Additional Information                                                                                                                                          |
+|------------------------|-----------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| max_failures           | 3               | Failures allowed before lockout. <br> This value cannot currently   be changed.                                                                                  |
+| failure_reset_interval | 60              | Period (in seconds) after which the number of failed login attempts is   reset <br> Accepted Values: 30-60                                                       |
+| lockout_duration       | 10              | Period (in seconds) for which users are locked out. <br> Accepted   Values: 5-10                                                                                 |
+| session_timeout        | 180             | Period (in seconds) after which idle users get logged out automatically   <br> Accepted Values: 30-90                                                            |
+| alert_email_address    |                 | Email address used for sending alerts in case of authentication failure   <br> If this variable is left blank, authentication failure alerts will   be disabled. |
+| allow_deny             | Allow           | This variable sets whether the user list is Allowed or Denied. <br>   Accepted Values: Allow, Deny                                                               |
+| user                   |                 | Array of users that are allowed or denied based on the `allow_deny`   value. Multiple users must be separated by a space.                                        |
+

+ 22 - 0
telemetry/add_node_idrac.yml

@@ -0,0 +1,22 @@
+# 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: Initiate telemetry for iDRACs present on AWX
+  hosts: localhost
+  connection: local
+  gather_facts: false
+  tasks:
+  - name: Initiate telemetry
+    include_tasks: "{{ playbook_dir }}/roles/idrac_telemetry/tasks/initiate_telemetry.yml"

+ 6 - 1
telemetry/roles/common/tasks/pre-requisites.yml

@@ -61,6 +61,11 @@
 
 - name: Install openshift using pip3
   pip:
-    name: openshift
+    name: "{{ item }}"
     state: present
     executable: pip3
+  with_items: "{{ pip_packages }}"
+
+- name: Install sqldb collection
+  command: ansible-galaxy collection install "{{ mysqldb_collection_name }}"
+  changed_when: false

+ 5 - 0
telemetry/roles/common/vars/main.yml

@@ -23,6 +23,11 @@ ctrl_plane_login_vars_filename: "{{ role_path }}/../../../control_plane/input_pa
 fail_msg_base_vars: "telemetry/base_vars.yml file doesn't exist."
 fail_msg_login_vars: "telemetry/login_vars.yml file doesn't exist."
 ctrl_plane_fail_msg_login_vars: "control_plane/login_vars.yml file doesn't exist"
+pip_packages:
+  - openshift
+  - omsdk
+  - PyMySQL
+mysqldb_collection_name: community.mysql:3.1.0
 
 #Usage: validate_base_vars.yml
 folder_perm: '644'

+ 75 - 0
telemetry/roles/idrac_telemetry/tasks/filter_idrac.yml

@@ -0,0 +1,75 @@
+# 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: iDRAC count incrementer
+  set_fact:
+    idrac_awx_count: "{{ idrac_awx_count | int + 1 }}"
+    awx_idrac: "{{ awx_idrac + [ idrac_inventory_jsondata['results'][idrac_index].name ] }}"
+
+- name: Filter iDRAC
+  block:
+  - name: Get system inventory
+    dellemc.openmanage.idrac_system_info:
+      idrac_ip: "{{ idrac_inventory_jsondata['results'][idrac_index].name }}"
+      idrac_user: "{{ idrac_username }}"
+      idrac_password: "{{ idrac_password }}"
+    register: idrac_system_info
+
+  - name: Check datacenter license status
+    set_fact:
+      datacenter_license: true
+    with_items: "{{ idrac_system_info.system_info.License }}"
+    loop_control:
+      index_var: index
+      label: "{{ idrac_system_info.system_info.License[index].LicenseDescription }}"
+    when:
+      - '"iDRAC9" in idrac_system_info.system_info.License[index].LicenseDescription'
+      - '"Data" in idrac_system_info.system_info.License[index].LicenseDescription'
+      - '"License" in idrac_system_info.system_info.License[index].LicenseDescription'
+      - '"Healthy" in idrac_system_info.system_info.License[index].PrimaryStatus'
+
+  - name: Filter iDRAC with supported firmware version
+    block:
+    - name: Get firmware version
+      dellemc.openmanage.idrac_firmware_info:
+        idrac_ip:   "{{ idrac_inventory_jsondata['results'][idrac_index].name }}"
+        idrac_user: "{{ idrac_username }}"
+        idrac_password:  "{{ idrac_password }}"
+      register: idrac_firmware_info
+
+    - name: Set firmware version status
+      set_fact:
+        firmware_version: true
+      with_items: "{{ idrac_firmware_info.firmware_info.Firmware }}"
+      loop_control:
+        index_var: index
+        label: "{{ idrac_firmware_info.firmware_info.Firmware[index].FQDD }}"
+      when:
+          - '"iDRAC" in idrac_firmware_info.firmware_info.Firmware[index].FQDD'
+          - (idrac_firmware_info.firmware_info.Firmware[index].MajorVersion | int) > 4
+    when: datacenter_license is true
+
+  rescue:
+    - name: iDRAC check list
+      set_fact:
+        failed_idrac: "{{ failed_idrac + [ idrac_inventory_jsondata['results'][idrac_index].name ] }}"
+
+- name: Filtered iDRAC list
+  set_fact:
+    telemetry_idrac: "{{ telemetry_idrac + [ idrac_inventory_jsondata['results'][idrac_index].name ] }}"
+    filtered_idrac_count: "{{ filtered_idrac_count | int + 1 }}"
+  when:
+    - datacenter_license is true
+    - firmware_version is true

+ 297 - 0
telemetry/roles/idrac_telemetry/tasks/initiate_telemetry.yml

@@ -0,0 +1,297 @@
+# 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.
+---
+
+# Include and initialize variables
+
+- name: Include telemetry base_vars.yml
+  include_vars: "{{ playbook_dir }}/input_params/base_vars.yml"
+  no_log: true
+
+- name: Initiate telemetry process if idrac_support is enabled
+  block:
+  - name: Include telemetry common vars
+    include_vars: "{{ playbook_dir }}/roles/common/vars/main.yml"
+    no_log: true
+
+  - name: Include idrac-telemetry vars
+    include_vars: "{{ playbook_dir }}/roles/idrac_telemetry/vars/main.yml"
+    no_log: true
+
+  - name: Include timescaledb vars
+    include_vars: "{{ playbook_dir }}/roles/timescaledb/vars/main.yml"
+    no_log: true
+
+  - name: Initialize variables
+    set_fact:
+      tower_config_file: "{{ playbook_dir }}/../control_plane/roles/webui_awx/files/.tower_cli.cfg"
+      tower_vault_file: "{{ playbook_dir }}/../control_plane/roles/webui_awx/files/.tower_vault_key"
+      idrac_telemetry_scripting_repo: "https://github.com/dell/iDRAC-Telemetry-Scripting.git"
+      idrac_telemetry_scripting_branch: master
+      idrac_telemetry_scripting_folder: iDRAC-Telemetry-Scripting
+      idrac_login_input_filename: "{{ playbook_dir }}/../control_plane/input_params/login_vars.yml"
+      idrac_login_vault_filename: "{{ playbook_dir }}/../control_plane/input_params/.login_vault_key"
+      login_vars_file: "{{ playbook_dir }}/input_params/login_vars.yml"
+      vault_filename: "{{ playbook_dir }}/input_params/.login_vault_key"
+      min_firmware_version_reqd: 4
+      datacenter_license: false
+      firmware_version: false
+      file_perm: '0644'
+      telemetry_idrac: []
+      service_type: 3
+      auth_type: 1
+      idrac_awx_count: 0
+      filtered_idrac_count: 0
+      failed_idrac: []
+      awx_idrac: []
+
+# Get AWX Credentials from tower_config file
+
+  - name: Check if tower_config file is encrypted
+    command: cat {{ tower_config_file }}
+    changed_when: false
+    no_log: true
+    register: config_content
+
+  - name: Decrpyt tower_config
+    command: >-
+      ansible-vault decrypt {{ tower_config_file }}
+      --vault-password-file {{ tower_vault_file }}
+    when: "'$ANSIBLE_VAULT;' in config_content.stdout"
+    changed_when: false
+
+  - name: Change file permissions
+    file:
+      path: "{{ tower_config_file }}"
+      mode: "{{ file_perm }}"
+
+  - name: Fetch awx host
+    command: grep "host:" "{{ tower_config_file }}"
+    changed_when: false
+    register: fetch_awx_host
+
+  - name: Fetch awx username
+    command: grep "username:" "{{ tower_config_file }}"
+    register: fetch_awx_username
+    changed_when: false
+    no_log: true
+
+  - name: Fetch awx password
+    command: grep "password:" "{{ tower_config_file }}"
+    changed_when: false
+    no_log: true
+    register: fetch_awx_password
+
+  - name: Set awx variables
+    set_fact:
+      awx_host: "{{ fetch_awx_host.stdout | regex_replace('host: ','') }}"
+      awx_username: "{{ fetch_awx_username.stdout | regex_replace('username: ','') }}"
+      awx_password: "{{ fetch_awx_password.stdout | regex_replace('password: ','') }}"
+    no_log: true
+
+  - name: Encrypt tower_config_file
+    command: >-
+      ansible-vault encrypt {{ tower_config_file }}
+      --vault-password-file {{ tower_vault_file }}
+    changed_when: false
+
+  - name: Change file permissions
+    file:
+      path: "{{ tower_config_file }}"
+      mode: "{{ file_perm }}"
+
+# Get iDRAC inventory from AWX
+  - name: Get idrac-inventory id
+    shell: >-
+      awx --conf.host "{{ awx_host }}" --conf.username "{{ awx_username }}" --conf.password "{{ awx_password }}" --conf.insecure
+      inventory list -f human | grep idrac_inventory
+    register: inventory_id
+    changed_when: false
+
+  - name: Get idrac host list
+    command: >-
+      awx --conf.host "{{ awx_host }}" --conf.username "{{ awx_username }}" --conf.password "{{ awx_password }}" --conf.insecure
+      hosts list --inventory "{{ inventory_id.stdout[0] }}"
+    register: idrac_inventory_output
+    changed_when: false
+
+  - name: Save the json data
+    set_fact:
+      idrac_inventory_jsondata: "{{ idrac_inventory_output.stdout | from_json }}"
+
+# Get iDRAC Credentials
+  - name: Get iDRAC credentials
+    block:
+    - name: Check if {{ idrac_login_input_filename }} file is encrypted
+      command: cat {{ idrac_login_input_filename }}
+      changed_when: false
+      no_log: true
+      register: config_content
+
+    - name: Decrpyt login_vars.yml
+      command: >-
+        ansible-vault decrypt {{ idrac_login_input_filename }}
+        --vault-password-file {{ idrac_login_vault_filename }}
+      when: "'$ANSIBLE_VAULT;' in config_content.stdout"
+      changed_when: false
+
+    - name: Include variable file {{ idrac_login_input_filename }}
+      include_vars: "{{ idrac_login_input_filename }}"
+      no_log: true
+
+    - name: Encrypt login_vars.yml
+      command: >-
+        ansible-vault encrypt {{ idrac_login_input_filename }}
+        --vault-password-file {{ idrac_login_vault_filename }}
+      changed_when: false
+      when: "'$ANSIBLE_VAULT;' in config_content.stdout"
+
+    - name: Update login_vars.yml permission
+      file:
+        path: "{{ idrac_login_input_filename }}"
+        mode: "{{ file_perm }}"
+
+    when: idrac_inventory_jsondata['results'] is defined and (idrac_inventory_jsondata['results'] |length>0)
+
+# Get mysqldb credentials
+  - name: Get mysqldb credentials
+    block:
+    - name: Check login_vars file is encrypted
+      command: cat {{ login_vars_file }}
+      changed_when: false
+      register: config_content
+      # no_log: true
+
+    - name: Decrpyt login_vars.yml
+      command: >-
+        ansible-vault decrypt {{ login_vars_file }}
+        --vault-password-file {{ vault_filename }}
+      changed_when: false
+      when: "'$ANSIBLE_VAULT;' in config_content.stdout"
+
+    - name: Include variable file telemetry/login_vars.yml
+      include_vars: "{{ login_vars_file }}"
+      no_log: true
+
+    - name: Encrypt input config file
+      command: >-
+        ansible-vault encrypt {{ login_vars_file }}
+        --vault-password-file {{ vault_filename }}
+      changed_when: false
+
+    - name: Update login_vars.yml permission
+      file:
+        path: "{{ login_vars_file }}"
+        mode: "{{ file_perm }}"
+
+    when: idrac_inventory_jsondata['results'] is defined and (idrac_inventory_jsondata['results'] |length>0)
+
+# Filter iDRACs matching telemtry pre-requisites
+
+  - include_tasks: filter_idrac.yml
+    with_items: "{{ idrac_inventory_jsondata['results'] }}"
+    loop_control:
+      index_var: idrac_index
+    no_log: true
+
+# Add iDRAC Credentials in DB and enable telemetry fetching
+
+  - name: Enable telemetry collection on iDRAC
+    block:
+    - name: Git clone grafana plugin repo
+      ansible.builtin.git:
+        repo: "{{ idrac_telemetry_scripting_repo }}"
+        dest: "{{ mount_location + idrac_telemetry_scripting_folder }}"
+        version: "{{ idrac_telemetry_scripting_branch }}"
+      register: telemetry_collection
+
+    - name: Enable telemetry collection on iDRACs
+      command: python3 ./ConfigurationScripts/EnableOrDisableAllTelemetryReports.py -ip "{{ item }}" -u "{{ idrac_username }}" -p "{{ idrac_password }}" -s Enabled
+      args:
+        chdir: "{{ mount_location + idrac_telemetry_scripting_folder }}"
+      with_items: "{{ telemetry_idrac }}"
+      no_log: true
+    when: telemetry_idrac is defined and (telemetry_idrac |length>0)
+    rescue:
+      - name: Show failure msg
+        fail:
+          msg: "Enabling telemetry on iDRAC failed"
+
+  - name: Add iDRAC details in mysqldb
+    block:
+    - name: Wait for mysqldb pod to come to ready state
+      command: kubectl wait --for=condition=ready --timeout=10m -n "{{ namespace }}" pod -l app="{{ mysqldb_k8s_name }}"
+      changed_when: false
+
+    - name: Get mysqlDB svc IP
+      command: kubectl get svc "{{ mysqldb_k8s_name }}" -n "{{ namespace }}" -o=jsonpath='{.spec.clusterIP}'
+      changed_when: false
+      register: mysql_svc_ip
+
+    - name: Get mysqlDB svc port
+      command: kubectl get svc "{{ mysqldb_k8s_name }}" -n "{{ namespace }}" -o=jsonpath='{.spec.ports[0].port}'
+      changed_when: false
+      register: mysql_svc_port
+
+    - name: Add iDRAC host in mysqlDB
+      community.mysql.mysql_query:
+        login_host: "{{ mysql_svc_ip.stdout }}"
+        login_port: "{{ mysql_svc_port.stdout }}"
+        login_user: "{{ mysqldb_user }}"
+        login_password: "{{ mysqldb_password }}"
+        login_db: "{{ mysqldb_name }}"
+        query: INSERT IGNORE INTO {{ mysqldb_name + '.services' }} (ip, serviceType, authType, auth) VALUES (%s, %s, %s ,'{"password":"{{ idrac_password | quote }}","username":"{{ idrac_username | quote }}"}')
+        positional_args:
+          - "{{ item }}"
+          - "{{ service_type }}"
+          - "{{ auth_type }}"
+      with_items: "{{ telemetry_idrac }}"
+      no_log: true
+    when: telemetry_idrac is defined and (telemetry_idrac |length>0)
+    rescue:
+      - name: Show failure msg
+        fail:
+          msg: "Adding iDRAC credential details to mysqldb failed."
+
+# Initiate iDRAC collection
+  - name: Initiate telemetry collection
+    block:
+    - name: Wait for idrac-telemetry pod to come to ready state
+      command: kubectl wait --for=condition=ready --timeout=10m -n "{{ namespace }}" pod -l app="{{ idrac_telemetry_k8s_name }}"
+      changed_when: false
+
+    - name: Get idrac-telemetry pod name
+      command: kubectl get pods -n "{{ namespace }}" -l app="{{ idrac_telemetry_k8s_name }}" -o jsonpath="{.items[0].metadata.name}"
+      changed_when: false
+      register: idrac_telemetry_pod
+
+    - name: Wait for 15 sec for mysqldb to be ready with updated values
+      pause:
+        seconds: 15
+
+    - name: Initiate telemetry-collector
+      shell: kubectl exec --stdin --tty "{{ idrac_telemetry_pod.stdout }}" -n "{{ namespace }}" -c telemetry-receiver -- nohup go run cmd/redfishread/redfishread.go &
+      changed_when: false
+
+    when: telemetry_idrac is defined and (telemetry_idrac |length>0)
+
+  - name: Telemetry report
+    debug:
+      msg:
+        - "Count of iDRAC IPs found on AWX: {{ idrac_awx_count }}"
+        - "List of iDRAC IPs found on AWX: {{ awx_idrac }}"
+        - "Count of iDRAC IPs where telemetry is initiated: {{ filtered_idrac_count }}"
+        - "List of iDRAC IPs where telemetry is initiated: {{ telemetry_idrac }}"
+
+  when: idrac_telemetry_support is true

+ 4 - 0
telemetry/roles/idrac_telemetry/tasks/main.yml

@@ -20,4 +20,8 @@
 
   - name: Deploy idrac_telemetry pods
     include_tasks: idrac_telemetry_deployment.yml
+
+  - name: Collect iDRAC IP from AWX and initiate telemetry collection
+    include_tasks: initiate_telemetry.yml
+
   when: idrac_telemetry_support is true

+ 1 - 1
telemetry/roles/idrac_telemetry/tasks/mysqldb_deployment.yml

@@ -92,7 +92,7 @@
                 workingDir: /go/src/github.com/telemetry-reference-tools
                 env:
                   - name: MYSQL_DATABASE
-                    value: timescale
+                    value: "{{ mysqldb_name }}"
                   - name: MYSQL_USER
                     valueFrom:
                       secretKeyRef:

+ 9 - 9
telemetry/telemetry.yml

@@ -13,15 +13,15 @@
 # limitations under the License.
 ---
 
--  name: Telemetry and visualization
-   hosts: localhost
-   connection: local
-   gather_facts: false
-   roles:
-    - common
-    - timescaledb
-    - idrac_telemetry
-    - grafana_config
+- name: Telemetry and visualization
+  hosts: localhost
+  connection: local
+  gather_facts: false
+  roles:
+  - common
+  - timescaledb
+  - idrac_telemetry
+  - grafana_config
 
 - name: Get node inventory
   hosts: localhost