Part 6: Deploy and Configure Shielded VMs Using SCVMM

Previous Post in Series:  Part 5:  Deploy and Configure the Host Guardian Service

Welcome to Part 6 of the Server 2016 Features Series. In this section we’re going to configure all necessary resources to enable us to deploy shielded VMs on our guarded fabric.  You’ll need to have already configured a library server within SCVMM, if you’ve yet to do this, I’ve documented the process HERE

You can jump to any of the sections covered in this post using the links below:

NOTE:  For the purposes of this guide, we’ll be deploying our shielded VMs as an administrator that has access to SCVMM. In reality, it’s unlikely that tenant will be able to do this and will be deploying their VMs using the Windows Azure Pack portal. Setting that up is out of scope for this guide but will be covered in a later one.

 

Create a Shielded VM Template in SCVMM

When deploying regular VMs from SCVMM, you’d use a template right? So it’s good news that we can also create templates for our shielded VMs. The added security of these templates does require a little more effort to setup, but that’s what we’re here to step through 🙂

We’re going to cover creating a shielded template disk and a VM template that makes use of it.

 

Prepare an Operating System VHDX

The first thing we’ll need to do is prepare an OS disk that we’ll run through the “Template Disk Wizard” RSAT tool. You can use any of your existing tools to create this disk (DISM for example), however I always prefer to create a new VM from ISO and will be using this process now.

Before creating our disk though, there are a few requirements to be aware of, see table below:

Requirement for VHDXReason
Must be a GUID Partition Table (GPT) diskNeeded for generation 2 virtual machines to support UEFI
Disk type must be Basic as opposed to Dynamic.
Note: this refers to the logical disk type, not the “dynamically expanding” VHDX feature supported by Hyper-V.
BitLocker does NOT support dynamic disks
The disk has at least two partitions. One partition must include the drive on which Windows is installed. This is the drive that BitLocker will encrypt. The other partition is the active partition, which contains the bootloader and remains unencrypted so that the computer can be started.Needed for BitLocker
File system is NTFSNeeded for BitLocker
The operating system installed on the VHDX is one of the following:
Windows Server 2012, 2012 R2 or 2016
Windows 8, 8.1, or 10
Needed to support generation 2 virtual machines and the Microsoft Secure Boot template
Operating system must be generalized (run sysprep.exeTemplate provisioning involves specializing VMs for a specific tenant’s workload

With all of that in mind, go spin up a VM so we can steal it’s disk 🙂

Once you’ve fully patched the OS, we need to run sysprep but before we do that, enable remote desktop as that is the tenants only means to access a shielded VM (other than remote PowerShell over the network assuming required ports have been opened and no ACL’s block it).

To do this, open an elevated PowerShell console and run the following:

Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server'-name "fDenyTSConnections" -Value 0
Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -name "UserAuthentication" -Value 1
Get-NetFirewallRule -DisplayName "Remote Desktop*" | Enable-NetFirewallRule

If you do forget to enable Remote Desktop or forget to open up Windows Firewall, it’s not the end of the world. WS-Man is enabled by default and the above rules can be added by using New-PsSession and Enter-PSSession to connect to the VM (it’s IP can be found in the SCVMM console)…pretty cool right?

Now we can sysprep the OS, instructions below:

Press “Windows Key + R” and type “sysprep”

Run the sysprep application

Select “Enter System Out-of-Box Experience…”, tick “Generalize” and select “Shutdown”. Now click “OK”

clip_image001

Once the VM has finished sysprepping (yeah it’s a word!), we’ll want to copy the disk. This will allow us to keep the VM for usage somewhere else later, including updating it as once it’s been signed, you will not be able to alter it.

NOTE:  Don’t copy the VHDX to your VMM library just yet.

 

Sign and Protect the VHDX With the Template Disk Wizard

Before we can use a template disk to deploy shielded VMs, it must be signed and encrypted with BitLocker. To do this we will make use of the Template Disk Wizard RSAT tool. The wizard will generate a hash for the disk and add it to a Volume Signature Catalog (VSC). The VSC is signed using a certificate specified by either the tenant or the service provider (depending on who is supplying the template disk, as it can all be done by the tenant if that’s their preference) and is used in the provisioning process to ensure that the disk has not been altered or replaced with a disk the tenant hasn’t trusted. BitLocker is also installed on the disk’s operating system to prepare it for encryption during the VM provisioning process.

As the OS disk is modified in place, decide what server you want to install the VM Shielding RSAT tools on and copy the VHDX you prepared earlier across to it.

NOTE:  The server you choose will need to be rebooted to complete installation of the tools.

Now log onto the server and install the Shielded VM RSAT Tools using the PowerShell below:

Install-WindowsFeature RSAT-Shielded-VM-Tools –Restart

You will now need to obtain a certificate to sign the VHDX, for production purposes, this certificate should be from a Certificate Authority trusted by both the tenant and the hoster. If however, this is purely for testing purposes then the PowerShell below will create a certificate that you can use.

NOTE:  Tenants will be able to see details of the certificate when looking at the VSC of the disk (they’ll use this when creating their shielding data later)

New-SelfSignedCertificate -DnsName gimme.certificate.com

Armed with a certificate and prepared VHDX, we can launch the “Template Disk Wizard”, you’ll find it under “Windows Administrative Tools” in the Start menu

On the “Certificate” screen, click “Browse” and select the certificate you created above and click “OK”. Now click “Next”

clip_image002

clip_image003

Click “Browse” and select the VHDX you prepared earlier and click “Next”

clip_image004

Give your disk a friendly name and a version number (yup, 3 decimal places) and click “Next”

clip_image005

Review your choices and click “Generate” to sign your VHDX

clip_image006

This process may take a while depending on the size of the disk you created, and whether you went with Dynamic or Fixed. I also just noticed that hovering over the progress bar will show you the completion percentage…nice touch 🙂

clip_image007

 

Copy the Template Disk to the SCVMM Library

Now that we have a shielded template disk, we want to copy it across to our SCVMM library for use in VM provisioning, Carry out the steps below on your SCVMM server:

Copy the VHDX to your SCVMM library share folder, this could be local on the server or if you used this guide a dedicated share on your SOFS cluster (I’ve yet to update my VMM deployment with this piece, coming very soon).

Refresh the SCVMM library. Navigate to “Library”, right-click on your library server object and select “Refresh”.

Once the refresh job has completed, you should see the new shielded VHDX in your library…and hey LOOK, it’s got a shielded icon 🙂

You can also right-click the context bar at the top of the pane and enable a column for denoting resources as “Shielded”

clip_image008

Now we want to give SCVMM some information about the disk, like it’s operating system and Virtualisation platform:

In the “Physical Objects” pane of the library, right-click on your shielded VHDX and select “Properties”

Change the “Operating System” to “Windows Server 2016*” and change the “Virtualization Platform” to “Microsoft Hyper-V”. Now click “OK”

clip_image009

 

Create a Shielded VM Template in SCVMM (Continued)

Before we can use our newly signed template disk, we need to create a VM template, much in the same way you already do for non-shielded VMs. The main differences being that options like Generation 2, UEFI, secure boot etc. are greyed out. Tenant customisation options are also limited.

Let’s crack on:

Navigate to “Library”, right-click “VM Templates” and select “Create VM Template”

clip_image010

Select “Use and existing VM template or virtual hard disk stored in the library” and click “Browse”

Select your signed template disk, you can make this earlier by right-clicking the context bar and enabling a “Shielded” column. Now click “OK” and “Next”

clip_image011

Type a name for your VM Template and click “Next”

clip_image012

Modify the resources as required, Processors, Memory and Availability. Make sure you attach your network adapter to a VM Network as this is a tenants only route into a shielded VM. If you’re using static IP pools, these should already be configured (See my earlier guide for info on how to do this HERE). Now click “Next”

clip_image013

On the “Operating System” tab, add a product key if you’re providing this on behalf of your tenants, or leave it blank if not (more on this later in the unattend file creation section). For the purposes of this guide, I’ll be populating it in SCVMM as I’ll be both the hoster and the tenant. Confirm you have the correct time zone configured and click “Next” and “Create”

clip_image014

Notice that you’re new template also shows that it’s for deploying shielded or encryption supported VMs.

clip_image015

We’re not going to deploy a shielded VM just yet as we’ll need a Shielding Data file for that. Let’s finish up with the hoster side of things before moving on to that 🙂

 

Create and Prepare VM Shielding Helper VHD

So we’ve made sure that we can allow our customers to create shielded VMs from scratch, but what if one of our customers wants to shield an already deployed VM…that’s where the VM Shielding Helper VHD comes in. This section will detail the step required to get this up and running.

Create a new Generation 2 VM running Windows Server 2016 from ISO* (currently this can be core, desktop experience but NOT Nano).

*NOTE:

The VM Shielding Helper VHD must not be related to the template disks you created in Hosting service provider creates a shielded VM template. If you re-use a template disk, there will be a disk signature collision during the shielding process because both disks will have the same GPT disk identifier. You can avoid this by creating a new (blank) VHD and installing Windows Server 2016 onto it using your ISO installation media.

From <https://technet.microsoft.com/en-us/windows-server-docs/security/guarded-fabric-shielded-vm/guarded-fabric-vm-shielding-helper-vhd>

Once the VM is up and running, log into the desktop, complete any setup steps and make sure the VM is in a working state. Now shut down the VM

NOTE:  Do not sysprep the VM

Now copy the VHDX to the server you used for signing the template disk earlier in this guide (it already has the required RSAT tools installed)

Launch an elevated PowerShell console and run the following:

Initialize-VMShieldingHelperVHD -Path ShieldingHelper.vhdx

Once the command has completed, repeat the Copy the Template Disk to the SCVMM Library section from earlier.

Now we need to tell SCVMM to use this VHDX when shielding existing VMs.

Navigate to “Settings”, “General” and “Host Guardian Settings”.

Click “Browse” and select the ShieldingHelper VHDX you just copied to the library. Now click “Finish”

clip_image016

NOTE: Now delete the VM you used to create the ShieldingHelper disk as starting it up again will corrupt the ShieldingHelper disk.

 

Create Shielding Data File

For the purposes of this guide we’ll be creating this file as a tenant with access to SCVMM, when a tenant does this in production, certain information will be made available for download from the Windows Azure Portal. I’ll be covering this in a later guide and as such it’s out of scope for this one.

A shielding data file comes in .PDK format and holds the following secrets:

  • Unattend file – Used to specialise the VM
  • Customer certificates – An RDP certificate is the example we’ll be using
  • Administrator account password
  • Volume Signature Catalog file – Provided by the tenant or hoster (depending on who provides the signed VHDX), this details what signed disks the tenant has trusted
  • Guarded Fabric Metadata XML – This is always provided by the hoster and denotes what guarded fabrics a tenants shielded VM can run on

 

Obtain a Certificate for RDP

Being that tenants can only connect to their shielded VMs using RDP or other remote management tools, it is important that tenants know they are connecting to the correct endpoint. We are going to satisfy this by configuring an RDP certificate Remote Desktop Services will present to the user when they connect to their shielded VM. Tenants will generally create these certificates using their own PKI but for the purposes of this guide we’ll be using a self-signed certificate.

NOTE:  When generating an RDP certificate, make sure it’s a wildcard as you’ll be using the same shielding data file to spin up multiple virtual machines.

Log onto the server you used earlier for signing your template disk (as it already has the required RSAT tools installed).

Launch an elevated PowerShell console and run the following to generate your self-signed certificate:

$RDPCertificate = New-SelfSignedCertificate -DnsName "*.domain.com"
$Password = ConvertTo-SecureString -AsPlainText "Password" –Force
Export-PfxCertificate –Cert $RDPCertificate -FilePath C:\Temp\rdpCert.pfx -Password $Password

 

Create an Answer File

Microsoft have made this process MUCH easier than it was in Technical Preview by giving us a new PowerShell cmdlet that takes most of the pain away 🙂 Cheers guys, this was my least favourite part.

Still on the same server as above.

To install the new module, run the following from an elevated PowerShell console:

Save-Module -Name guardianFabricTools -Path C:\Temp\
Install-Module -Name GuardedFabricTools

Notice the warning when installing. You may also receive an error relating to your configured Execution Policy, this can be set to the following values:

  • AllSigned
  • Bypass
  • Default
  • RemoteSigned
  • Restricted
  • Undefined
  • Unrestricted

You can set this to “Unrestricted” long enough to allow you to install the module by running

Set-ExecutionPolicy -ExecutionPolicy Unrestricted

You can set it back to the default value by running:

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned

clip_image017

For this guide, we’ll have to provide the following values to our New-ShieldingDataAnswerFile command

  • AdminPassword – This will be the password for the local administrator account
  • RDPCertificatePath – This is the path to the RDP PFX we created earlier
  • RDPCertificatePassword – This is the password we locked the above PFX with
  • StaticIP – This sets the unattend file to pull IP and DNS settings for the VM from an SCVMM static IP Pool
  • ProductKey – This states whether we’ll be providing the product key in the unattend file or using one configured in in the shielded VM template in SCVMM
  • Language – Required as sysprep resets this back to en-US, which is fine if you’re in America…I’m not, so I’ll set it back to en-GB

The following PowerShell will create an unattend file that we can use with the current setup of my environment, you may need to make slight changes to this to work with your environment, if you’ve followed the guide completely though, you should be good.

$AdminPassword = ConvertTo-SecureString -AsPlainText "password" -Force
$RDPCertPassword = ConvertTo-SecureString -AsPlainText "password" -Force
New-ShieldingDataAnswerFile -AdminPassword $AdminPassword -RDPCertificateFilePath C:\Temp\rdpCert.pfx -RDPCertificatePassword $RDPCertPassword -ProductKey UserSupplied -StaticIP -Path C:\Temp\unattend.xml -Language en-GB

NOTE: Make sure you’re SCVMM setup is in line with the warning detailed in the screenshot below:

clip_image018

 

Obtain the Volume Signature Catalog File

To get the VSC file, log onto your SCVMM server and launch an elevated PowerShell prompt and run the following:

This code assumes that you only have one signed disk in your SCVMM library at the time of running, if this is not the case, modify the first line as follows:

$Disk = Get-SCVirtualDisk -Name "NameOfSignedDisk"
$Disk = Get-SCVirtualHardDisk | ? Shielded -eq True
$VSC = Get-SCVolumeSignatureCatalog -VirtualHardDisk $Disk
$FileName = $Disk.Name
$VSC.WriteToFile("C:\Temp\$FileName.vsc")

NOTE:  As previously mentioned, a tenant would generally download this file from the Windows Azure Pack portal.

If the tenant created the signed VHDX themselves, then they could obtain it’s VSC by running the following command:

Save-VolumeSignatureCatalog -TemplateDiskPath "PathToDisk.vhdx" -VolumeSignatureCatalogPath "VSCSaveLocation.vsc"

 

Obtain Fabric Guardian Metadata File

The last thing we need to do before we can create our Shielding data is to designate which guarded fabrics the tenants VMs are allowed to run on. For this, we need to get a hold of the guardian metadata. For the purposes of this guide, we’ll be obtaining this using an SCVMM PowerShell cmdlet.

Log onto your SCVMM server, launch an elevated PowerShell console and run the following:

Invoke-WebRequest "http://HGS Service FQDN/KeyProtection/service/metadata/2014-07/metadata.xml" -OutFile C:\Temp\GuardianName.xml

…and with that, we can FINALLY create the tenants shielding data file

 

Create a Shielding Data File

Being that this will always be done by the tenant, lets act like one and run all this from a desktop machine. Microsoft have made their RSAT tools available for download and install for Windows 10. If you don’t have access to a Windows 10 machine, then you can continue this process on the server you used to sign the VHDX earlier (if that’s the case, skip the RSAT download and install steps).

Assuming however you DO have a Windows 10 machine, you can download the tools HERE

Now copy the unattend file, RDP file, VSC file and metadata XML file to your local machine C:\Temp\

From your start menu, navigate to “Microsoft Administrative Tools” and select “Shielding Data File Wizard”

On the “File and Policy” screen make sure “Create a new shielding data file” is ticked and click “Browse” to select a storage location for your secrets PDK.

The first .PDK we’re going to create will be for fully shielding VMs, as such, click “Shielded” and click “Next”

clip_image019

You’ll know from earlier, we needed to download the hoster guardian metadata file to confirm which guarded fabrics we could run our VMs on, now we need to create a local guardian. This gives us as the owner of a VM, the ability to change it from Shielded to Encryption Supported and vice versa.

To create our local guardian, click “Manage Local Guardians” and “Create”.

Give your guardian a name and either generate self-signed certificates or select existing certificates you already own. For the purposes of this guide, we’ll be using self-signed.

Select “Self-signed guardian” and click “Next”, “Create” and “Close”. Now click “OK” to get back to the wizard.

clip_image020

Now we to need import the hosters guardian metadata file we obtained earlier.

Again, click “Manage Local Guardians” and click “Import”.

Click “Browse” and select the locate your metafile file, enter a name for the guardian and click “OK”

Click “OK” to get back to the wizard.

clip_image021

Back on the “Owners and Guardians” page, select the local guardian you just created from the drop-down, and select the hosters guardian you just imported from the list below it. Now click “Next”

clip_image022

On the “Volume ID Qualifiers” page and click “Add”
Click “Browse” to locate the .VSC file you obtained earlier and click “OK”. Now click “Next”

clip_image023

clip_image024

On the “Specialization Files” page, click “Browse” and locate the unattend file you created earlier. The unattend file is checked before it’s added to make sure there are no issues with its layout etc…so that’s good 🙂

Click “Add” and browse to the RDP file you created earlier, now click “Next”, “Generate” and “Close”

clip_image025

Congratulations, you now have all you need to deploy a shielded VM 🙂

 

Create a Shielded VM in SCVMM

It’s all gonna work right? RIGHT? Let’s find out 🙂

In the last section, you created a .PDK containing all the tenant secrets necessary to deploy a Shielded VM, we now need to upload that file to SCVMM.

 

Upload VM Shielding Data to SCVMM

Copy the .PDK file to your SCVMM server and from the SCVMM console, navigate to “Library”, “VM Shielding Data”, right-click and select “Import Shielding Data”

clip_image026

Click “Browse” and locate your .PDK file.
Now enter a name for your file and optionally, a description. Now click “Import”

clip_image027

clip_image028

 

Deploy a Shielded VM from Template

OK, now let’s deploy a shielded VM, shall we?

From your SCVMM console, navigate to “Library”, “VM Template”, right-click on your shielded template and select “Create Virtual Machine”

clip_image029

Enter a name for your shielded VM and click “Next”

clip_image030

On the “Configure Hardware” tab, configure you’re VM as desired but make sure you put the VM on a VM network which has either DHCP or uses a static IP pool (as we’ve done for this guide – See screenshot)

Now click “Next”

clip_image031

Click “Next” on the “Configure Operating System” tab as already configured this when creating the template.

Click “Browse”, highlight the shielding data file you just uploaded and click “OK” and “Next”

clip_image032

Select the host group that contains your guarded hosts and click “Next”.
Select a host and click “Next”.

clip_image033

clip_image034

On the “Configure Settings” tab, accept the default or change the VMs storage location and select “Next”

clip_image035

Configure the “Add Properties” screen as desired and click “Next” and “Create”

clip_image036

You can watch the job progress on the pop-up jobs window, the deployment will take a while depending on the speed of your hardware…go get a coffee 🙂

Good coffee? You should now be looking at a job status like this:

clip_image037

So what’s left to do? Power up your VM and make sure you can RDP to it. You can find it’s IP address within the SCVMM console:

clip_image038

In the interest of transparency I made a mistake deploying my first shielded VM and ended up with an IP conflict…WHOOPS! What I’d actually done was manually specify an IP address from my static pool, which SCVMM knew nothing about and therefore gave it out to my shielded VM. Don’t be me, be better!

This however does allow me to reiterate that without networking, a shielded VM is basically a brick 🙂

If you also find yourself in the situation where you can’t RDP to the VM, recreate your .PDK file but instead of selecting “Shielded”, select “Encryption Supported”. This will allow you to console onto the VM and troubleshoot what’s causing the issue. It’s very likely that RDP wasn’t enabled or the networking isn’t being applied as expected, or like me, it’s an IP address conflict. Once you’ve resolved the issue, deploy the VM using your “Shielding” .PDK file.

clip_image039

So…I deployed another VM after shutting down my moron subroutine and it went swimmingly 🙂

You’ll notice that when you RDP, you see a popup which shows the RDP certificate you placed in your shielding data file, so that works!

clip_image040

So we’ve successfully deployed a fully shielded VM and everything is working as intended, but before we move on, let’s take a look at a couple of things we CAN’T do using our usual management tools.

Trying to console on to the VM from SCVMM is greyed out…hmmm

clip_image041

Trying to do the same from Hyper-V manager gives us a little more insight into why this is:

clip_image042

You’ll also notice that you can’t see what’s going on inside the VM from its preview window. This is because the video memory isn’t captured because the VM runs within a protected process, which other processes (like video memory redirection) can’t be attached to.

OK, so we’ve deployed a shielded VM from scratch, but what if we what to shield an existing VM? Remember that shielding helper VHDX we created earlier?

 

Shield an existing VM in SCVMM

The shielding data file we created earlier cannot be used to shield existing VM as their requirements are slightly different. So let’s create a new one.

From your Windows 10 machine (or server if you didn’t have one), launch the “Shielded Data File Wizard”.

Click “Browse” to select a storage path and name for your .PDK

Select “Shielding data for existing VMs and non-Shielded templates”, “Shielded” and click “Next”

clip_image043

Select the local guardian you created earlier from the drop-down and highlight the hoster guardian you imported earlier from the windows below it. Click “Next”

clip_image044

Add any file that you want to upload to the VM and click “Next” – you’ll notice that you don’t need to add an unattend file OR a Volume Shielding Catalog file here as the VM you’re shielding already exists.

Now click “Generate”

clip_image045

clip_image046

Copy your new Shielding Data File to your SCVMM server and import it following the process we used above

Deploy a VM from a non -shielded template. Once it’s up and running, make sure you can RDP to it and carry out any addition setup steps.

Now shut down the VM as it can’t be shielded while it’s running.

Right-click the VM you want to shield and select “Shield”

clip_image047

You should only be able to select the Shielding Data File you just uploaded as they’re scoped down based on shielding method. Select your .PDK and click “OK”

clip_image048

During this process you will see a new virtual machine is created called “Temporary Shielding Helper*” this will also be deleted as part of the shielding job. There will be a few warnings and/or errors in the SCVMM job logs regarding this temporary VM as discoveries etc. that are run against it may fail. These can be ignored, and hopefully MS will supress these in a future patch as it ruins my sea of green ticks 🙂

The job should complete with the following status:

clip_image049

Your VM should also now show as shielded within the console:

clip_image050

So there you have it, you can now deploy shielded VMs to your guarded fabric. Join me in part 7 where I’ll be detailing how to offer this service to tenants via the Windows Azure Portal.

5 Replies to “Part 6: Deploy and Configure Shielded VMs Using SCVMM”

  1. Nice Article!

    I ran the template disk wizard and the vhdx was bitlocked. However, when i copy the vhdx over to VMM it is still saying the vhdx is not shielded. Am i missing something here?

    1. Hi Kent,

      Glad you’re enjoying the post 🙂

      If you followed all steps exactly as they appear on the post, then you’re not missing anything. The only time I’ve seen this was when I accidentally copied the VHDx from the VM and not the copy that I’d just signed. Ashamed to admit, that took me about 3 minutes to work that out 🙂

      Also worth checking that you don’t have more than one VHDx in your library with the same name, incase that’s what you’re seeing.

      Worse case scenario, take another copy of the prepared VHDx from your VM and run through the process again, taking note of how long the signing process takes. I assume all the requirements for the prepared VHDx were met( noted in the table at the top of the section)?
      Also, what version of SCVMM are you running? Ideally you want your hosts and SCVMM to be running at the latest patch level.

      Apologies if that’s not a great help but it’s not a part of the process I’ve ever seen fail

      1. Hi David,

        Thanks for your help. I am running SCVMM 2016 with update rollup 2.1. I figured out what my problem was finally.

        Basically, my file server nodes that was hosting the SCVMM Libraries was still running Windows 2012 R2. Once i upgraded the first node to Windows Server 2016 i was able to see the shielded disk template!

        1. Hi Kent,

          I’m glad you managed to resolve the issue. I’ll pass that one back to the guys at MS to confirm that’s expected behaviour.

          Thanks for passing your fix on, much appreciated.

          1. Sounds good! It would be nice to hear what they come back with. I am in the process of upgrading the second node now. Thanks again!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.