VMware Distributed Port Group Configuration Report Using PowerCLI

From time to time we need to check that VMware Distributed Port Groups are following our standard configuration. If there is only a few port group this can be done manually but in my case I need to check a few hundred.

Since there are so many I wanted to make a script that will export the configuration of each port group and out put to a CSV.

In this post we will be going through using PowerCLI to report on the configuration setting for all distributed virtual switch port groups.

I used the PowerCLI developer doc to find the required commands to check each port group configuration settings and policies.

https://developer.vmware.com/docs/powercli/latest/products/vmwarevsphereandvsan/categories/vdport/

First we need to get the list of Distributed Virtual Switches (VDS)

Once we have the list of switches we can use the below command to return all port groups.

Get-VDPortgroup -VDSwitch switchname

Next we can take one port group and start to view the properties to get the required info.

The below will view the general port group settings like VLAN, port bindings and Numbers or ports.

Get-VDPortgroup -Name portgroupname |fl

To view the override policy use the below command.

Get-VDPortgroup -Name portgroupname | Get-VDPortgroupOverridePolicy

To view the teaming policy use the below.

Get-VDPortgroup -Name portgroupname | Get-VDUplinkTeamingPolicy

For team policies the name in PowerCLI is different than in the web UI, the below table will match up the names

LoadBalancingPolicyLoad balancing
LoadBalanceLoadBasedRoute Based on Physical NIC Load
LoadBalanceSrcMacRoute Based On Source MAC Hash
LoadBalanceSrcIdRoute Based On Originating Virtual Port
ExplicitFailoverUse Explcit Failover Order
LoadBalanceIPRoute Based on IP Hash

To view the security policy use the below.

Get-VDPortgroup -Name portgroupname | Get-VDSecurityPolicy

Now that I have all the different policy and configuration settings I can create the script.

I will be using a hash table for all export the configuration and policy settings.

The full script can be download from my GitHub repository link below.

https://github.com/TheSleepyAdmin/Scripts/blob/master/VMware/Network/VMwarePortGroupConfig.ps1

The script can be run to either output the configuration details to the PowerShell console using the below command.

.\VMwarePortGroupConfig.ps1 -VCServer vCenter

The second option is to export to CSV file by using the -ReportExport parameter.

.\VMwarePortGroupConfig.ps1 -VCServer vCenter -ReportExport .\

The below is what the CSV output should look like.

Azure Network Watcher NSG Flow Logs: Review NSG Traffic

Azure NSG flow logs are a feature of Azure Network Security Group (NSG) that allows administrators to track and monitor network traffic flowing through their Azure virtual network.

The flow logs provide detailed information on the source and destination of the traffic, as well as the protocol and port being used. This information can be used to identify trends and patterns in network usage, as well as to detect and troubleshoot potential security threats.

Azure NSG flow logs provide a valuable tool for administrators to maintain visibility and control over their Azure network environment.

To set the NSG flow logs to be sent to Log workspace we can use Traffic Analytics.

In this post we will be going through enabling NSG Flow Logs, enabling Traffic Analytics and reviewing the logs for allowed and denied traffic using Azure Log Analytics Workspace.

There will be a cost for using the Azure Storage, workspace and Traffic Analytics so confirm these before proceeding as the more data sent the more it will cost.

When creating a new deployment in Azure it is good security practice to restrict access between subnets to the required ports only. This can sometimes be a bit difficulty if the application communication is not fully documented.

This is where NSG Flow can be used as we can use this to review the traffic between the subnets going over the NSG’s. There are some prerequisite for this

  • Storage account in the same region as the NSG
  • Log Analytic workspace
  • Network Watcher (this should be created automatically once a vNet is created)
  • Network Security group
  • VM running in two network and have an NSG assigned

Once all the above are ready we can start to enabled the logging. NSG flow can be either enabled from NSG directly or through Network Watcher. We will be doing this in Network Watcher.

First step is to go to Network Watcher > NSG Flow

Select the required Subscription, the required NSG’s, storage account and retention (0 on retention means the logs are kept forever) since this is a test environment I will only keep the logs for 5 days.

On configuration select version 2 and enabled traffic analytics. On traffic analytics set the process interval to either 1 hour or 10 mins, select the subscription and workspace.

Apply tags if in use, then review and create.

The deployment should only take a minute or so and then the NSG flow should show as succeeded.

Once enabled it can take little bit for data to start showing. We can check that the container has been create on the storage account.

Open the storage account and go to Containers there should be a new insight-logs container.

If we navigate down the folder structure there will be a JSON file that has all the NSG access requests, we could use the JSON file it self but it pretty difficult to read.

To check that data is going to the workspace, go to Log Analytics Workspace. Select the workspace we used earlier.

We will use the AzureNetworkAnalytics_CL table and flowlog to view the data. I used the below Learn article to help understand the table / fields and create the queries.

https://learn.microsoft.com/en-us/azure/network-watcher/traffic-analytics-schema

We can run the below KQL query this will return

AzureNetworkAnalytics_CL
| where SubType_s == "FlowLog"
| project FlowType_s, FlowEndTime_t, SrcIP_s, DestIP_s, DestPort_d, L4Protocol_s, L7Protocol_s

Now that we have confirmed data is being shipped to the log workspace, we can start to create the KQL query that will show all traffic between the specific IP of the servers.

The below query will return inbound and outbound request for specified source and destination IP

AzureNetworkAnalytics_CL
| where SubType_s == "FlowLog"
| extend Direction = case(FlowDirection_s == 'O', 'Outbound', FlowDirection_s == 'I','Inbound', FlowDirection_s)
| extend Access = case(FlowStatus_s == 'A', 'Allowed', FlowStatus_s == 'D', 'Denied', FlowStatus_s )
| extend Protocol = case(L4Protocol_s == 'T', "TCP", L4Protocol_s == 'U', "UDP", L4Protocol_s)
| project TimeGenerated, Direction, Access, SrcIP_s, DestIP_s, DestPort_d, Protocol, L7Protocol_s, NSGRule_s
| where SrcIP_s contains "Source IP" and DestIP_s contains "Destination IP"

We can now see all the traffic that is going from one server two the other, we can use this to review and allow the required traffic.

To export we can then export the results and use that to review the required ports.

The last step will be to update the rules on the NSG to only allow the required traffic.

Upgrading VMware vCenter Server Appliance from 7.0 to 8.0

With the release of VMware vCenter Server Appliance 8.0 (vCSA), I wanted to upgrade my lab setup to the latest release to check out some of the new features.

In this post we will go through the process, this is be the same process as previous version of vCSA just some of the wizard screen have changed slightly.

Before starting the upgrade process make sure you have a valid backup and I also take a snapshot of the existing vCSA just incase there are any issues.

First, we need to download the vCSA ISO,

https://customerconnect.vmware.com/downloads/info/slug/datacenter_cloud_infrastructure/vmware_vsphere/8_0

Next, I usually rename the existing VCSA to _old as I want to deploy to the vCenter with the same name.

Next, we can mount the vCenter ISO to launch the installer.exe.

Next on the install select upgrade.

The introduction will warn that if using an external PSC it will be converged as external PSC are being deprecated.

Next accept the end user agreement.

Put in the details for the existing Appliance.

We will have to put in the details of the existing vCenter or ESXi host. My vCSA is installed on a standalone ESXi host, so I used those details.

If there is a cert warning accept to continue.

Enter the details for the target server where the new vCSA is going to be deployed to.

Enter the existing vCenter server name (as long as you renamed the VM name first)

Select the VM size.

Select the datastore to use.

Next, we need to select the network and give the vCSA a temporary IP, this is to allow it to be contactable so that the data migration can happen. After the data migration the original IP will be moved to the new vCSA.

Now review the deployment details.

Click finish to start the deployment.

Once the deployment is completed, we can start stage 2.

Click continue

Next we will go through stage two of the upgrade.

First part will verify the connection and run pre-checks for any issues.

Review these result to confirm there will be no issues. .

Select what data to move.

Tick to join customer experience or not and continue.

Review the settings and confirm everything is correct.

Click finish to start the data transfer.

The data migration can take a while depending on the amount of data to be moved.

Once completed we can now logon to the vCSA and confirm that we are running vCenter 8.0.

Network Security Group: Restrict Access between Azure Subnets

In this post we will be going through configuring Network Security Group’s to restrict access between subnets under a single vNet.

Routing between subnets happens automatically and is allowed by default.

This can allow resources communicate over any port and there is no network access control.

To make the Azure network more secure this should be restricted as much as possible to only allow the required communication.

Below is a link to the Microsoft network best practice.

https://learn.microsoft.com/en-us/azure/security/fundamentals/network-best-practices?toc=https%3A%2F%2Flearn.microsoft.com%2Fen-us%2Fazure%2Farchitecture%2Ftoc.json&bc=https%3A%2F%2Flearn.microsoft.com%2Fen-us%2Fazure%2Farchitecture%2Fbread%2Ftoc.json#logically-segment-subnets

One way to limit the communication is to use NSG’s.

In this example we will be using a 10.10.1.0/24 address space

Address Space

Then we will be creating multiple subnets with /28 mask.

Subnets

I have added one server to both the Ops and Mgmt subnets. Now if we make a connection between each VM the traffic will be routed directly between both VM’s.

trace route

Next, we will setup the NSG to only allow connection between the subnets for RDP and SMB. In this case we will be creating an NSG per subnet, but this could be done in one NSG.

Network Security Group

Next, we need to create two new inbound rules one to allow the required ports and the second to deny all other access.

Go to inbound rules and select Add.

Add rule

Added in the required details

·       Source: IP Address

·       Source Port: 

·       Destination: IP Address

·       Destination IP Address:

·       Service: Custom

·       Destination Port Ranges:

·       Protocol TCP

·       Action: Allow

·       Priority: 110

·       Name: Allow_Mgmt_Subnet_Access

Allow inbound rule

Next, we will create the deny rule.

 

Deny inbound rule

I would usually set the deny to a much lower priority, so that if more rules are required in the future there won’t be an issue with the deny rule having a higher priority and blocking the traffic. 

Once saved, the allow and deny rule should show under inbound rules.

Now when we try to run tracert again, this time we won’t be able to connect.

 

Tracert

If we try open a connection using SMB, we can connect without issue.

To block access back to the other subnet we will need to create the same rules but with the opposition subnet source and destination IP ranges.

After creating both set of NSG rules there will be no access between the subnets on any port other than those specified in the inbound rules.

Microsoft Graph: Restrict Access Using Conditional Access Policy

In this post we will be going through setting up a conditional access policy to allow connection’s to a Microsoft App Registration that will be used for calling Microsoft GraphAPI from only certain countries / public IP’s.

Microsoft has a preview feature in Conditional Access for workload identities. A workload identity is an identity which allows an application or service principal access to resources.

When an App Registration is created, it will create a service principal. This service principal is what we will use in the conditional access policy.

First we need to create the named location to define where we want to allow the access from.

To create a named location go to endpoint management admin page.

https://endpoint.microsoft.com/

Go to Endpoint security > Conditional access.

MEM Admin Page

Once in Conditional access, go to Named location and add the required countries locations and or IP ranges.

Named locations

To add as single IP use /32 bit subnet mask.

IP range

Once we have the named locations we can create the Conditional access policy.

Go to the policies tab and click on new policy.

Policies page

Give the policy a name and set the assignment to workload identities.

Conditional access policy

Next select the service principal for the Graph App registration.

Users or workload selection

Next on Cloud apps or actions select, All cloud apps

Cloud apps or actions selection

Next we need to specify which location will be included, which we set to any location as we will use the exclude to allow access from the named location we will connect from.

Conditions selection

Next select the location that will be excluded from the policy in my case it will be the public IP we added earlier to the named location.

Excluded Locations

Next we set the access, I will be blocking access as I only want to allow access from the one public IP we specified in the excluded location.

Access selection

With any conditional access policy I would recommend setting the policy to Report-only to confirm that only the access that we excepted to be blocked is.

Policy settings enabled section

To check if the policy is applying correctly against the service principal we can check the sign-in logs.

First connect using Graph query and then go to sign-in logs.

MEM Admin Blade

Select service principal sign-ins.

Sign-in logs

Click on the request ID and look at the Report-only tab to see if the access would have been blocked or allowed.

Sign-in logs

Once we confirm that the policy is applying the correct access, the conditional access can be set to on.

Now once we try to connect from an IP or location not on the excluded list, it will be blocked from accessing.

Graph Connection

When we connect from an allowed location, we will get back the access token and be allowed to connect.

Graph Connection Token

When creating App registration we should look at access controls for these as this can be over looked and lead to a security risk, most application do not need access from any location and should be limited to only the require location or IP address to give greater access control.

Microsoft Graph: Restrict Exchange Online Mailbox Access

Recently we have been reviewing some of our old Exchange Web Service mailbox connections and updating these to use Microsoft Graph. We wanted to restrict what mailbox’s the Azure App registration used for Microsoft Graph could connect to.

To set this up in Exchange Online we can use an Application Access Policy. In this post we will be going through setting up and confirming the mailbox’s access.

I have gone through setting up Azure App registration for Microsoft Graph before so we wont be going through that in this post.

I will also be using certificate and Microsoft MSAL PowerShell Module to get the Graph access token.

See post below if you need to know how to connect using MSAL with certificate base authentication.

Once we have the app registration setup and certificate issued and uploaded to the app registration, we can then assign the GaphApi permission to access mailboxes.

If we don’t apply the permission we will get access denied.

Graph Message Access Error

I will be giving Mail.Read API permission, this will give access to view all mailboxes.

Graph API Permissions

Grant admin consent for the API permission.

Now if we try to query the mailbox we should now be able to see the messages.

Graph Message Response

At this stage we can use the App registration to read messages from any mailboxes.

To lock this down so that the Graph query is only able to view certain mailboxes we can use

New-ApplicationAccessPolicy

to create an application access policy. The policy can be applied to a group or a single users.

To run the command, we will need Application ID of the app registration, mailbox or mail enabled security group and description. Using a group is useful if there are multiple mailboxes that they will need to allow access.

New-ApplicationAccessPolicy -AppId ApplicationID -PolicyScopeGroupId "user_group@domain.com" -AccessRight RestrictAccess -Description "Restrict this app to view mailbox or security group."

To run the command we need to connect to Exchange Online

Connect-ExchangeOnline

Then run the command to create the application access policy.

We can test what mailboxes the app registration can access using.

Test-ApplicationAccessPolicy -AppId ApplicationID -Identity user_group@domain.local

Now once we try to query the mailbox we have give access to we will see the message returned, if we try query any other mailbox we will an error message.

Applying the application access policy is a good idea for security as allowing an application to read mailboxes that it doesn’t need access to can be a risk if the app was ever compromised or there is sensitive data in mailboxes that no other users or application should have access to.

Patching VMware vCenter 7.0 Server Appliance Using CLI

There are a few different way’s to update to vCenter server appliance (VCSA). In this post we will be going through using CLI method to apply vCenter patches. Before updating VCSA make sure you have a current backup and take a snapshot before proceeding in case of any issues with the update.

First we need to connect to the vCenter server using SSH. I will be using the inbuilt OpenSSH feature in PowerShell but you can use what ever SSH client you prefer.

To enable SSH on vCenter logon to the management page using the vCenter URL with port 5480 (https://vcenter.domain.local:5480).

Go to Access and click edit to enable SSH Login.

vCenter Management UI

Next we need to connect to the vCenter server using ssh.

vCenter SSH Login

Next we can run the below command to view the vCenter update history

software-packages list --history
Patch List

We can use the below command. This will list the current update settings, if the vCenter server has no internet access then you could update the URL to use an internal web site that contains the update files.

update.get
Update configuration

We will be using the default URL from the update.get command when running the update

software-packages install --url https://vapp-updates.vmware.com/vai-catalog/valm/vmw/8d167796-34d5-4899-be0a-6daade4005a3/7.0.3.00100.latest/ --stage --acceptEulas

This command will download, stage the update and install.

Update staging

Once stage the update will then start to install.

Update Installing

The update can take awhile to complete.

Update Completion

Once the update has completed, vCenter should reboot if required to complete the install.

When the appliance boots backup we can re-connect to confirm we are now running on the updated VCSA version.

vCenter SSH Login

Azure App Registrations Cert / Client Secret MS Graph Report

In this post we will be looking at creating a report to show what Azure App registrations have expiring client secret / certificate in the specified amount of days.

There is currently no in built way to report on expiring App registrations in the Azure portal other than checking the app registration, so we will be using Microsoft Graph SDK to automate the reporting.

First to automate the report we need to create an app registration to use for the Microsoft Graph connection. I have gone through this in a previous post.

The specific Microsoft GraphApi application permission required is Application.Read.All, this needs to be added to the App Registration that we use for Microsoft Graph.

App Registration API Permission

Next we need to connect to Microsoft Graph using.

Connect-MgGraph

To list the app registration use

Get-MgApplication
Microsoft Graph Applications

Once we have the list of apps we can use PasswordCredentials to view client secret details

(Get-MgApplication).PasswordCredentials
Application Secrets Properties

and KeyCredentials to view the certificates details

Application Certificate Properties

Once we have the required properties, we can create the script to export the app registration details.

App Registration Report

There are two parameters Reportonly which returns just the result to PowerShell window and ReportExport which will export the report to the specific folder specified.

Below is what the Reportonly should look like.

.\Get-AppRegistrationDetails.ps1 -CertificateThumbprint Thumprint -ClientId ClientID -TenantId TenantID -ReportOnly -ExpiryDate 200
Report results

When using the Reportexport

.\Get-AppRegistrationDetails.ps1 -CertificateThumbprint thumbprint -ClientId ClientID -TenantId TenantID -ReportExport C:\temp\Graph\ -ExpiryDate 200

The full script can be downloaded from the below GitHub link.

https://github.com/TheSleepyAdmin/Scripts/blob/master/MSGraph/AppRegistration/Get-AppRegistrationDetails.ps1

Create Local ESXi Account Using PowerCLI

In this post we will be going through creating local ESXi account using PowerCLI.

Recently I have had to create local account to allow a monitoring tool to pull information from all ESXi hosts.

We want to automate the user creation and assign the required permissions so that they only have the permission required for a limited time.

First we need to connect to the ESXi Host using PowerCLI

Connect-VIServer
Connection to vCenter

To check what account already exist use the below.

Get-VMHostAccount
List Accounts

To create a new account we will use the New-VMHostAccount command

New-VMHostAccount -Id accountname -Password password -Description Account Description
Create new account

Next we need to assign the required permissions. We can list the current roles using

Get-VIRole
List VMware Roles

We also need an entity to set the permission or the command will error out.

Permission

To list the entity use the

Get-Folder
List Folder

Select the entity that will have the role applied. In this case we will be applying to the root object so it applies to all objects on the host and will assigning the admin role.

New-VIPermission -Entity (Get-Folder root) -Principal accountname -Role Admin
Set Permission

To remove the account use the below command.

Get-VMHostAccount -User account name | Remove-VMHostAccount -Confirm:$false

Once we have the commands, we can create the script to automate the account creation and role assignment to configure multiple hosts.

Account Creation Script

The scripts uses EsxiHost as the heading for the CSV if you want to use something different the script will need to be updated.

Below is the script running against my test hosts.

.\Create-LocalESXiUser.ps1 -ESXiHostList .\EsxiHosts.csv -ESXiUser useraccount -ESXipass password -ESXiNewUser accountname -ESXiUserPass accountpass -ESXiPermission Permission -ESXiUserdesc "Account Description"
Account creation script

This process can also be used to update the permission for a specific account.

Updating permissions

To download the full script use the below link to github.

https://github.com/TheSleepyAdmin/Scripts/blob/master/VMware/Config/Account/Create-LocalESXiUser.ps1

Configure SNMP On VMware ESXi Using PowerCLI

In this post we will be going through deploying new SNMP configuration to a list of ESXi hosts using PowerCLI. We can add SNMP using ssh and esxcli commands but this will required SSH to be enabled and connecting to each host.

We can use Set-VMHostSNMP command to set the SNMP configuration by conecting to the host using connect-viserver which uses https to connect and does not required SSH to be enabled.

First we need to connect to the ESXi host

Connect-VIServer -Server esxihost.domain.local

use a local account like root to connect

PowerCLI SNMP Command

If you get a certificate error and can’t connect you might need to update the PowerCLI Configuration or install the root cert to trust the self singed cert of the ESXi hosts.

Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false

Once connected we will be using the below set of command to configure the SNMP settings.

Get-VMHostSnmp | Set-VMHostSnmp

https://developer.vmware.com/docs/powercli/latest/vmware.vimautomation.core/commands/set-vmhostsnmp/#Default

First we will enabled and set the community string

Get-VMHostSnmp | Set-VMHostSnmp -Enabled:$true -ReadOnlyCommunity communityname

PowerCLI SNMP Command

Next we will set the target that traps will be sent.

Get-VMHostSnmp | Set-VMHostSnmp -TargetCommunity communityname -TargetHost snmp.domain.local -TargetPort 162 -AddTarget
PowerCLI SNMP Command

To test I have setup snmp on Ubutu

Ubuntu SNMP check

Now that we have set of command we can create the script. I will be doing a loop through each host and configuring the SNMP.

I also added in some if statement to check if SNMP is already enabled and to check if the target host matches the one that is set in the parameters.

SNMP Script

The full script can be downloaded from the below github link.

https://github.com/TheSleepyAdmin/Scripts/blob/master/VMware/Config/SNMP/Set-ESXiSNMP.ps1

Below is an example of what the csv file should look like if you want to use a different heading the script will need to be updated.

Each of the values will be called as parameter to allow easy re-use below is an example of the SNMP script running against my test hosts.

Using PowerCli can be a quicker way to set and enabled SNMP on a list of hosts rather than having to SSH and use esxcli command. This can also be used to update the existing SNMP configuration to a new traps target.