Monthly Archives: July 2020

Centos Based Certificate Authority For The VMware Lab

A useful thing for a home lab or VMware lab, is a certificate authority. There are Windows based CA’s as well as Linux based and many others. I wanted to take the Linux based route for my home lab to give me some administration time in Linux, being that Windows is my safe place! After a bit of googling, I settled on Easy-RSA as it looked like it would do what I needed in the lab. There are already a few guides out there for this, but this is my take on it for use in my VMware home lab.

I settled on CentOS 8 as a base OS. Why? Why not, I don’t have any Centos VM’s and I decided it would be good to use something other than Ubuntu or Photon.

Firstly, I stood up a low resource VM (1 vCPU, 1GB RAM) giving it a static IP and creating an admin account.

I then kicked off the update of all the install packages on the OS by first elevating to the root account using ‘SU’ and then running the upgrade command for the DNF package manager.

dnf upgrade

This prompts a ~600MB download after confirming you want to continue. Once the download completes it gets on with upgrading.

Once done, its time to install some additional packages starting with epel-release, easy-rsa and openssl. Lets quickly give some background to each.

epel-release (Extra Packages for Enterprise Linux) is a repository of popular packages which aren’t available by default. easy-rsa is one of the packages in this repository.

easy-rsa This is a utility for managing Public Key Infrastructure(PKI) aka Certificate Authority. Check out some info here.

openssl A widely used tool, in this case to create Certificate Signing Requests (CSR). I’ll let you read about this here.

Lets get to the install. You can run them as separate installs like this –

sudo dnf install epel-release
sudo dnf install easy-rsa
sudo dnf install openssl

or as a one liner –

sudo dnf install epel-release easy-rsa openssl

Now for ease of administration, create a directory in the admin users home directory and create a symbolic link so it remains updated. You also want to limit access to your admin user in my case ‘ca_admin’.

mkdir ~/easy-rsa
ln -s /usr/share/easy-rsa/3/* ~/easy-rsa/
chmod 700 /home/ca_admin/easy-rsa

If you’re not familiar with chmod commands, ‘chomd 700’ = Protects a file against any access from other users, while the issuing user still has full access.

Now to initialise your new PKI. Change Directory (cd) to the easy-rsa directory you created in your admin users home directory and run the initialisation command.

cd ~/easy-rsa
./easyrsa init-pki

You will get a message showing it is complete and it will state the new pki directory that has been created inside the easy-rsa directory (/home/ca_admin/easy-rsa/pki)

You now need to create and populate a file called ‘vars’ in /home/ca_admin/easy-rsa and populate it with your organisation/lab information. You can achieve this with the vi editor.

set_var EASYRSA_REQ_PROVINCE "Labshire"
set_var EASYRSA_REQ_CITY "Lab City"
set_var EASYRSA_REQ_ORG "Home Lab"
set_var EASYRSA_REQ_EMAIL "admin@lab.local"
set_var EASYRSA_REQ_OU "Lab"
set_var EASYRSA_ALGO "ec"(or rsa if you wish...)
set_var EASYRSA_DIGEST "sha512"

Once created, you are now ready to create the root certificate and private key by running the following command –

./easyrsa build-ca

You will be prompted to specify a passphrase which you need to keep safe as you will need it when issuing certificates. There will then be a second prompt to provide a common name; Enter you CA’s name. eg. CA01.

This process will have now created your root certificate and the private key (keep this safe). You will find them in the following locations /home/ca_admin.easy-rsa/pki/ca.crt (root certificate) and /home/ca_admin.easy-rsa/pki/private/ca.key (private key).

If you are using a Windows device to access your HomeLab, you are going to want to add the ca.crl file to the ‘Trusted Root Certification Authorities’ store on your Windows device so that any certificates issued are trusted. You can copy the ca.crt file using a tool such as WINSCP to transfer the file to a local directory to then install. You can do the equivalent on Mac and Linux OS’s too.

You will also need this handy for any certificates that require the full chain to be included.

I won’t go into every Certificate Signing Request (CSR) scenario as there are many. I will however, show you the commands needed to produce a certificate from a CSR.

To issue a certificate from a CSR, you will need to copy the .req or .csr file to a directory such as /tmp on your CA server, again using a tool like WINSCP.

You can then run the following commands to import the certificate signing request. The Common name is often the device name or FQDN.

cd ~/easy-rsa
./easyrsa import-req /tmp/<csr_file_name>.req <CommonName or FQDN> 
./easyrsa sign-req server <CommonName or FQDN>

The import command will import the .req or .csr file into /home/ca_admin.easy-rsa/pki/reqs (you can’t place the .req directly in here!) which is then processed by the sign-req command, again asking for the passphrase, leaving you with your new certificate in the /home/ca_admin.easy-rsa/pki/issued directory.

You can then use WINSCP again to transfer the file off the CA, and install it on the device or service in which you requested it from.

As always with any root CA, you don’t want it to become compromised. To help with this, keep it turned off when you’re not issuing, or administering your certificates.

I have also not included any Certificate Revocation List details as this isn’t something I need in my lab environment.

Now the VMware bit… below is the process for acquiring the CSR and installing the generated certificate on an ESXi host and a vCenter server using the methods above.

Standalone ESXi Host 6.7

First for a standalone ESXi Host, browse to – Host > Manage > Security & Users > Certificates

Select Import new certificate then select either ‘Generate FQDN signing request’ or ‘Generate IP signing request’.

You will be presented with a screen like this.

Copy this into a file with the extension .req. This can then be imported and issued using the method above.

Then, go back the the ‘Import new certificate’ wizard and import the certificate in the same format at the CSR into the box. (Open the .crt file using notepad)

Once complete close and open your browser and head back to your hosts web client and you will see you no longer have a certificate error.

vCenter Server 6.7

Log into your vCenter appliance using via SSH. Then run the following command –


Select option 1, (you will be prompted to provide your SSO credentials), followed by option 1 again.

You will then need to provide the following information for the CSR.

As you complete the wizard you will have a .csr and a .key file in /tmp which again can be issued using the process above.

If using WinSCP you may hit the following error.

You will need to change over to the bash shell.

chsh -s /bin/bash root

You could then face another error…

root@vcsa02 [ ~ ]# chsh -s /bin/bash root
You are required to change your password immediately (password aged)
chsh: PAM: Authentication token is no longer valid; new one required

This is due to the password expiring. To change the password on the account run the passwd command

Further info on both of these errors can be found at these two VMware Articles. Here and here.

Once you have issued the certificate, you need to then copy the .crt file back to the /tmp directory along with the root certificate (or chain).

Now back to the Certificate Manager. Selecting option 1 to now import the certifictes. You will be prompted to provide the path and file name of each component. The certificate you created, the .key file that was created during the CSR generation and the root or CA chain certificate. Finally you will be asked to confirm you want to replace the Machine SSL certificate, type y.

It will take a few minutes, but eventually you will get confirmation that the task is complete and you can then reload your browser to see the Web Client is now showing a valid certificate.

Hope this has been useful. I will cover vCenter 7.0 Machine SSL certificate replacement in a future post.

Thanks for reading!

Configuring Encrypted vMotion With PowerCLI

Encrypted vMotion is a feature available in vSphere 6.5 onwards. It is something that is always used to secure vMotions of encrypted virtual machines, its a required option, but is optional for non encrypted virtual machines.

By default, non encrypted virtual machines will be set to ‘opportunistic’. If both the source and destination hosts support it (so ESXi 6.5 onwards), vMotions will be encrypted. If the source or destination does not support it, then the vMotion traffic will not be encrypted.

The ‘required’ option is exactly what it says, encrypted vMotion is required. If either the source or destination host does not support it, the vMotion will fail. As I’ve said, encrypted virtual machines have no choice, they have to use encrypted vMotion.

The final option is to set it to ‘disabled’, for when you don’t want it to even attempt encrypting vMotion traffic for a virtual machine.

To set this option on either a singular virtual machine or all virtual machines, you can use the options below. Firstly to view the current settings you can run this. If you want to target a single VM enter the VM name after Get-VM.

Get-VM | Select-Object Name, @{Name="vMotionEncrpytion";Expression={$_.extensiondata.config.MigrateEncryption}}
Name vMotionEncrpytion
---- -----------------
CentOS opportunistic
vRepDR opportunistic
vcsa01 opportunistic
pho01 opportunistic

Now to change these all to ‘required’ you can run the following:

$VMView = Get-VM | Get-View
                    $Config = New-Object VMware.Vim.VirtualMachineConfigSpec
                    $Config.MigrateEncryption = New-Object VMware.Vim.VirtualMachineConfigSpecEncryptedVMotionModes
                    $Config.MigrateEncryption = "required"

You can confirm this by re-running the get command:

Name vMotionEncrpytion
---- -----------------
CentOS required
vRepDR required
vcsa01 required
pho01 required

To set them back to opportunistic, use the following:

$VMView = Get-VM | Get-View
                    $Config = New-Object VMware.Vim.VirtualMachineConfigSpec
                    $Config.MigrateEncryption = New-Object VMware.Vim.VirtualMachineConfigSpecEncryptedVMotionModes
                    $Config.MigrateEncryption = "opportunistic"

As you can see, they are then back to the default setting.

Name vMotionEncrpytion
---- -----------------
CentOS opportunistic
vRepDR opportunistic
vcsa01 opportunistic
pho01 opportunistic

And finally, setting it to ‘disabled’:

$VMView = Get-VM | Get-View
                    $Config = New-Object VMware.Vim.VirtualMachineConfigSpec
                    $Config.MigrateEncryption = New-Object VMware.Vim.VirtualMachineConfigSpecEncryptedVMotionModes
                    $Config.MigrateEncryption = "disabled"
Name vMotionEncrpytion
---- -----------------
CentOS disabled
vRepDR disabled
vcsa01 disabled
pho01 disabled

Here is a link to the official documentation on Encrypted vMotion for further information – here.

Thanks for reading!

Exporting and Importing Active Directory OU Structures

Recently I needed to build out some test Active Directory Forests that resemble production in order to complete some testing. One of the forests contained a significant amount of OU’s that I had no intention of manually recreating.

To run the New-ADOrganizationalUnit cmdlet, you need to provide the OU name and the Path where you want to create it. However, Get-ADOrganizationalUnit doesn’t provide the path, so you need to determine it from the DistinguishedName.

After a number of google searches, I couldn’t find exactly what I needed, so I began piecing together various bits of Powershell that I found. I ended up learning a bit of Regex in the process! Powerful tool if you know how to use it.

I came up with two versions in the end, you can see both below with the differences highlighted.

$OUs=Get-ADOrganizationalUnit -Filter * | select name,DistinguishedName,@{n=’OUPath’;e={$_.distinguishedName -replace '^.+?,',''}},@{n=’OUNum’;e={([regex]::Matches($_.distinguishedName, “OU=” )).count}} | Sort OUNum | export-csv C:\<Path_to_CSV>\OUTree.csv -NoTypeInformation
$OUs=Get-ADOrganizationalUnit -Filter * | select name,DistinguishedName,@{n=’OUPath’;e={$_.distinguishedName -replace '^.+?,(CN|OU|DC.+)','$1'}},@{n=’OUNum’;e={([regex]::Matches($_.distinguishedName, “OU=” )).count}} | Sort OUNum | export-csv C:\<Path_to_CSV>\OUTree.csv -NoTypeInformation

The first one effectively takes everything up to the first ‘,’ and replaces it with nothing, effectively removing the OU Name. The second one captures everything after the first ‘,’ and replaces the whole string with what was captured. Both have produced the same result in my scenario, but it was useful to understand both methods for future use of Regex.

Both also have a property called ‘OUNum’, this property counts how many time ‘OU=’ appears in the original DistigushedName string. OU’s need to be created in order, so that the parent OU exists before the child. This orders the OU’s in ‘tiers’ before exporting them to CSV. All OU’s in the root of the directory will get a value of 1, OU’s within these will get a value of 2 and so on. Credit to ‘David Z’ for this bit!

Once you have your data, you may or may not need to modify the domain. If you are importing it into a different domain, you’ll need to. In my case it was simple enough to do a find and replace in a text editor (eg. DC=lab,DC=local to DC=lab2,DC=local). You could look at using concepts from above to achieve this before exporting the data if you so wish.

Now you have your data, you need to import it. You can run the following in the target domain.

$OUs = import-csv C:\<Path_to_CSV>\OUTree.csv
ForEach ($OU in $OUs) 
          {New-ADOrganizationalUnit -Name $OU.Name -Path $OU.OUPath}

Hope this has been useful. Thanks for reading!