vSphere VM Security Configuration with Ansible

Since security is a requirement for the complete infrastructure stack, we will cover the vSphere VM Security Configuration with Ansible in this article. One of my prior posts has already covered the VMware ESXi Security Configuration with Ansible and is a good starting point when you are new to this topic.

VM Security Configuration

The vSphere 6.7 Update 1 Security Configuration Guidehas different subject areas regarding VM Security Configuration: Configure only the minimum required devices, disable unexposed features, limit the information you collect and disable non-essential features. I have additionally added the use of UEFI Secure Boot, if possible.

vSphere VM Advanced Options with Ansible

Most of the recommendations require an additional Advanced Option. The Ansible Module vmware_guest, which is needed anyway to create the vSphere VM, is able to set Advanced Options (Parameter: customvalues).

- name: Create new VM - {{ vm_name }}
  vmware_guest:
      hostname: "{{ vcenter_hostname }}"
      username: "{{ vcenter_username }}"
      password: "{{ vcenter_password }}"
      datacenter: "{{ vm_datacenter }}"
      cluster: "{{ vm_cluster }}"
      validate_certs: no
      folder: "{{ vm_folder }}"
      name: "{{ vm_name }}" 
      state: poweredoff
      guest_id: rhel7_64Guest
      datastore: "{{ vm_datastore }}"
      disk:
        - size_gb: 10
      hardware:
          memory_mb: "{{ vm_mem }}"
          memory_reservation: "{{ (vm_mem / 2) | int }}"
          num_cpus: "{{ vm_cpu }}"
          cpu_reservation: "{{ (vm_cpu * 256) | int }}"
          scsi: paravirtual
          boot_firmware: efi
      networks:
        - name: "{{ vm_network }}"
          device_type: vmxnet3
      customvalues:
        - key: "isolation.tools.copy.disable"
          value: "True"
        - key: "isolation.tools.paste.disable"
          value: "True"
        - key: "isolation.tools.diskShrink.disable"
          value: "True"
        - key: "isolation.tools.diskWiper.disable"
          value: "True"
        - key: "mks.enable3d"
          value: "False"
        - key: "tools.setInfo.sizeLimit"
          value: "1048576"
        - key: "RemoteDisplay.vnc.enabled"
          value: "False"
        - key: "tools.guestlib.enableHostInfo"
          value: "False"
      wait_for_ip_address: no
  register: vm_deploy

I have chosen these options from the vSphere 6.7 Update 1 Security Configuration Guide (svga.vgaOnly and sched.mem.pshare.salt was not set in my case):

DescriptionOption
Explicitly disable copy/paste operationsisolation.tools.copy.disable
Explicitly disable copy/paste operationsisolation.tools.paste.disable
Disable virtual disk shrinkingisolation.tools.diskShrink.disable
Disable virtual disk shrinkingisolation.tools.diskWiper.disable
Disable 3D features on Server and desktop virtual machinesmks.enable3d
Limit informational messages from the VM to the VMX filetools.setInfo.sizeLimit
Control access to VM console via VNC protocolRemoteDisplay.vnc.enabled
Do not send host information to gueststools.guestlib.enableHostInfo

Another great Advanced Option that can be set during the provisioning is “ctkEnabled = TRUE”. If you enable Changed Block Tracking (CBT) prior first boot of the VM you prevent the annoying situation that your backup software (e.g. Veeam Backup & Replication) is not able to activate CBT during the backup job because of an existing VM Snapshot.

UEFI Secure Boot with Ansible

If you want to activate UEFI Secure Boot within the vSphere VM Security Configuration with Ansible you need the vmware_guest_boot_manager Preview Module from the Ansible 2.8 Dev Branch.

- name: Enable UEFI SecureBoot for {{ vm_name }}
  vmware_guest_boot_manager:
    hostname: "{{ vcenter_hostname }}"
    username: "{{ vcenter_username }}"
    password: "{{ vcenter_password }}"
    validate_certs: no
    uuid: '{{ vm_deploy.instance.hw_product_uuid }}'
    secure_boot_enabled: True

Be aware that only newer guest operation systems support UEFI Secure Boot. I have verified Windows 2016, RHEL 7 and CentOS 7 running on VMware ESXi 6.7 Update 1.

Ansible Playbook

My complete Playbook for the vSphere VM Security Configuration with Ansible covers two additional extras:

  • Check for existing VM with the same name
  • CPU and Memory Reservation

The CPU and Memory Reservation done with the vmware_guest module was recently fixed with the PR #56161 by Abhijeet. With older versions of the module, the CPU and Memory Reservation had to be set in dedicated tasks.

My Playbook sets 50% of the memory and 256Mhz per vCPU as reservation:

memory_reservation: "{{ (vm_mem / 2) | int }}"
cpu_reservation: "{{ (vm_cpu * 256) | int }}"

The task for the verification for a possible existing VM with the same name acts a little bit wyred. If everything is fine (no VM with the same name) the vmware_guest_facts – task fails, but the error is ignored and the subsequent fail – task is skipped. If the vmware_guest_facts – task is successful (VM with the same name is found) the fail – task will stop the Playbook.

vSphere VM Security Configuration with Ansible
- name: Create a VM with security configuration
  hosts: localhost
  gather_facts: no
  vars:
    vm_datacenter: lab
    vm_cluster: cluster01
    vm_folder: /{{ vm_datacenter }}/vm/
    vm_name: test_vm_01
    vm_cpu: 1
    vm_mem: 256
    vm_datastore: datastore1
    vm_network: DPortGroup1
  tasks:
  - name: Check for existing VM with the same name
    vmware_guest_facts:
      hostname: "{{ vcenter_hostname }}"
      username: "{{ vcenter_username }}"
      password: "{{ vcenter_password }}"
      datacenter: "{{ vm_datacenter }}"
      validate_certs: no
      name: "{{ vm_name }}"
    ignore_errors: True
    register: vm_find
  - fail:
      msg: "The VM already exists."
    when: vm_find is succeeded 
  - name: Create new VM - {{ vm_name }}
    vmware_guest:
        hostname: "{{ vcenter_hostname }}"
        username: "{{ vcenter_username }}"
        password: "{{ vcenter_password }}"
        datacenter: "{{ vm_datacenter }}"
        cluster: "{{ vm_cluster }}"
        validate_certs: no
        folder: "{{ vm_folder }}"
        name: "{{ vm_name }}" 
        state: poweredoff
        guest_id: rhel7_64Guest
        datastore: "{{ vm_datastore }}"
        disk:
          - size_gb: 10
        hardware:
            memory_mb: "{{ vm_mem }}"
            memory_reservation: "{{ (vm_mem / 2) | int }}"
            num_cpus: "{{ vm_cpu }}"
            cpu_reservation: "{{ (vm_cpu * 256) | int }}"
            scsi: paravirtual
            boot_firmware: efi
        networks:
          - name: "{{ vm_network }}"
            device_type: vmxnet3
        customvalues:
          - key: "isolation.tools.copy.disable"
            value: "True"
          - key: "isolation.tools.paste.disable"
            value: "True"
          - key: "isolation.tools.diskShrink.disable"
            value: "True"
          - key: "isolation.tools.diskWiper.disable"
            value: "True"
          - key: "mks.enable3d"
            value: "False"
          - key: "tools.setInfo.sizeLimit"
            value: "1048576"
          - key: "RemoteDisplay.vnc.enabled"
            value: "False"
          - key: "tools.guestlib.enableHostInfo"
            value: "False"
        wait_for_ip_address: no
    register: vm_deploy
  - name: Enable UEFI SecureBoot for {{ vm_name }}
    vmware_guest_boot_manager:
      hostname: "{{ vcenter_hostname }}"
      username: "{{ vcenter_username }}"
      password: "{{ vcenter_password }}"
      validate_certs: no
      uuid: '{{ vm_deploy.instance.hw_product_uuid }}'
      secure_boot_enabled: True

This Playbook can be found together with other vSphere related Playbooks and the required module library inside of my Ansible-Playground GitHub Repository.

4 Comments

  1. Mario Lenz 27. May 2019
  2. Rudolf Kleijwegt 28. May 2019
    • Markus Kraus 28. May 2019

Leave a Reply