Whilst beginning preparations to take the VMware Certificated Advanced Professional Deploy exam, I have started to look into the features and topics that I’m not overly familiar with. To help with the learning process, I am going to be deploying and configuring these features, and writing blogs on many of the topics to help cement the information. Hopefully these will be useful for anyone else learning or researching these topics!
The first one; vCenter Server Profiles!
Background
vCenter Server Profiles (Section 7.2.4 Configure VMware vCenter Server® profiles in the Exam Blueprint) were first introduced in vSphere 7.0. These addressed the challenges around configuration consistency in large multi vCenter environments by allowing a ‘base’ or ‘source’ vCenter configuration to be exported, modified and imported into multiple other vCenter’s.
Not only does this help ensure a consistent configuration for things like NTP, Syslog, SSH and security settings on the appliance, but also Roles and Users can be copied to all vCenter servers quickly and easily. The Roles and Users can be a great help if you have a role on all vCenter servers for things like backup solutions or templating.
The profile or configuration is exported as a JSON file, therefore this easily allows you to store this as a source control tool such as GitHub to enable you to track and review changes to the configuration. This can be really useful when it comes to larger teams with many updates happening.
The export and import process is all done via API’s. More on that later, first lets take a look at this in the form of a high level diagram!
API’s
As mentioned earlier, vCenter Server Profiles are currently managed via API’s, not the GUI. They can be found in the Developer Center within vCenter itself as you can see below:
There are 5 API’s in total I am going to be working with as part of this blog:
- Acquiring a SessionID token - Required to authenticate.
- Getting a list of profiles.
- Exporting a profile.
- Validating a profile.
- Importing a profile.
I will be using PowerShell to make the API calls, lets take a look at the code to do each step as well as the output.
Acquiring a SessionID Token
There are a few variable values you will need to fill out here; Username, Password and the FQDN of the source vCenter Server.
1#Authentication
2$User = "[email protected]"
3$Pass = "SecurePassword!"
4$Auth = $User + ":" + $Pass
5$Encoded = [System.Text.Encoding]::UTF8.GetBytes($Auth)
6$EncodedAuth = [System.Convert]::ToBase64String($Encoded)
7$Headers = @{"Authorization" = "Basic $($EncodedAuth)" }
8$sourcevcenter = "vm-vcsa-01.smt.com"
9#Get Session ID
10$Session = Invoke-RestMethod -Method POST -Uri "https://$($sourcevcenter)/rest/com/vmware/cis/session" -Headers $Headers
11$SessionID = $Session.Value
12$SessionID
Now when you run this, a value is outputted. This is what we will use to authenticate the other API calls.
1d84b95e370f1ed68b997f4affbe6feba
Listing Profiles
Now lets look at listing the available profiles. You will notice the output may remind you of the diagram above.
1$SessionHeaders = @{'vmware-api-session-id' = "$($SessionID)"
2}
3Invoke-RestMethod -Method GET -Uri "https://$($sourcevcenter)/api/appliance/infraprofile/configs" -Headers $SessionHeaders
Note the SessionID variable being used here. This is the value from the previous step.
Name | Info |
---|---|
ApplianceManagement | Appliance Mangment Service |
ApplianceNetwork | Appliance Network Configuration |
AuthManagement | Authentication & Authorization Management |
Exporting a Profile
Now to export the profile. As mentioned earlier, the configuration is outputted to a JSON file to a path of your choosing.
1$SessionHeaders = @{
2 "vmware-api-session-id" = "$($SessionID)"
3 "Content-type" = "application/json"
4}
5$Export = Invoke-RestMethod -Method POST -Uri "https://$($sourcevcenter)/api/appliance/infraprofile/configs?action=export" -Headers $SessionHeaders
6$Export | Out-File "C:\temp\vcenter-profile-export.json"
Here is a trimmed look at the content of the file:
1{"action":"RESTART\_SERVICE","productName":"VMware vCenter Server","creationTime":"2021-12-30T18:12:42+0000","version":"7.0.3.00100","profiles":{"ApplianceNetwork":{"description":"Appliance Network Configuration","action":"RESTART_SERVICE","actionOn":{"VC_SERVICES":["applmgmt"],"SYSTEMD":["systemd-networkd","systemd-resolved"]},"version":"7.0","config":{"/etc/sysconfig/proxy":{"HTTPS PROXY":"""","SOCKS PROXY":"""","FTP PROXY":"""","GOPHER PROXY":"""","PROXY ENABLED":""no"","SOCKS5 SERVER":"""","HTTP PROXY":"""","NO PROXY":[""localhost","127.0.0.1""]},"/etc/systemd/resolved.conf":{"Fallback DNS":null,"LLMNR is enabled":"false","DNS":"127.0.0.1 10.200.15.1"}},"name":"ApplianceNetwork"},"AuthManagement":{"description":"Authentication & Authorization Management","action":"NO_ACTION","version":"1.0","config":{"Lockout Policy":{"Maximum number of failed login attempts":5,"Time interval between failures":180,"Unlock time":300},"Password Policy":{"Minimum special characters":1,"Minimum alphabetic characters":2,"Minimum uppercase characters":1,"Minimum lowercase characters":1,"Minimum numeric characters":1,"Minimum adjacent identical characters":3,"Previous password reuse restriction":5,"Maximum lifetime":90,"Maximum length":20,"Minimum length":8},"Token Policy":{"Clock tolerance ms":600000,"Maximum token renewal count":10,"Maximum token delegation count":10,"Maximum Bearer RefreshToken lifetime":21600000,"Maximum HoK RefreshToken lifetime":2592000000}
2...
3Trimmed to save the scrolling...
4...
5{"principal":{"name":"VSPHERE.LOCAL\\NsxAuditors","group":true},"roles":[741131114],"propagate":true},{"principal":{"name":"VSPHERE.LOCAL\\NsxViAdministrators","group":true},"roles":[-2094871953],"propagate":true},{"principal":{"name":"VSPHERE.LOCAL\\NsxAdministrators","group":true},"roles":[-1723127349],"propagate":true},{"principal":{"name":"VSPHERE.LOCAL\\RegistryAdministrators","group":true},"roles":[1006],"propagate":true},{"principal":{"name":"SMT.COM\\stephan","group":false},"roles":[-1],"propagate":true},{"principal":{"name":"VSPHERE.LOCAL\\vStatsGroup","group":true},"roles":[-292639496],"propagate":true}]},"name":"AuthManagement"},"ApplianceManagement":{"description":"Appliance Mangment Service","action":"RESTART\_SERVICE","actionOn":{"VC\_SERVICES":\["applmgmt"\],"SYSTEMD":\["sendmail","rsyslog"]},"version":"7.0","config":{"/etc/applmgmt/appliance/appliance.conf":{"Is shell Enabled":false,"Shell Expiration Time":null,"TimeSync Mode (Host/NTP)":"NTP"},"/etc/sysconfig/clock":{"Time zone":""Europe/London"","UTC":"1"},"/usr/bin/systemctl/sshd.service":{"Enable SSH":"true"},"/etc/ntp.conf":{"Time servers":["uk.pool.ntp.org"]},"/etc/mail/sendmail.cf":{"SMTP Port":null,"Mail server":null},"/etc/vmware-syslog/syslog.conf":{"Port [2]":null,"Port [1]":null,"Port [0]":null,"Protocol [2]":null,"Remote Syslog Host [1]":null,"Protocol [1]":null,"Remote Syslog Host [0]":null,"Protocol \[0\]":null,"Remote Syslog Host [2]":null},"/etc/pam.d/system-auth":{"Deny Login after these many Unsuccessful Attempts.":"3","Unlock root after (seconds)":"300","On Error Login will be.":"fail","Include Root user for SSH lockout.":true,"Unlock user after (seconds)":"900"},"/etc/shadow":{"root":{"maximumDays":"","warningDays":"7"},"bin":{"maximumDays":"90","warningDays":"7"},"daemon":{"maximumDays":"90","warningDays":"7"},"messagebus":{"maximumDays":"90","warningDays":"7"},"systemd-bus-proxy":{"maximumDays":"90","warningDays":"7"},"systemd-journal-gateway":{"maximumDays":"90","warningDays":"7"},"systemd-journal-remote":{"maximumDays":"90","warningDays":"7"},"systemd-journal-upload":{"maximumDays":"90","warningDays":"7"},"systemd-network":{"maximumDays":"90","warningDays":"7"},"systemd-resolve":{"maximumDays":"90","warningDays":"7"},"systemd-timesync":{"maximumDays":"90","warningDays":"7"},"nobody":{"maximumDays":"90","warningDays":"7"},"rpc":{"maximumDays":"90","warningDays":"7"},"ntp":{"maximumDays":"90","warningDays":"7"},"sshd":{"maximumDays":"90","warningDays":"7"},"smmsp":{"maximumDays":"90","warningDays":"7"},"apache":{"maximumDays":"90","warningDays":"7"},"sso-user":{"maximumDays":"90","warningDays":"7"},"vpostgres":{"maximumDays":"","warningDays":"7"},"vapiEndpoint":{"maximumDays":"90","warningDays":"7"},"eam":{"maximumDays":"90","warningDays":"7"},"vlcm":{"maximumDays":"90","warningDays":"7"},"vsan-health":{"maximumDays":"90","warningDays":"7"},"vsm":{"maximumDays":"90","warningDays":"7"},"vsphere-ui":{"maximumDays":"90","warningDays":"7"},"wcp":{"maximumDays":"","warningDays":"7"},"content-library":{"maximumDays":"90","warningDays":"7"},"imagebuilder":{"maximumDays":"90","warningDays":"7"},"perfcharts":{"maximumDays":"90","warningDays":"7"},"vpgmonusr":{"maximumDays":"","warningDays":"7"},"vtsdbmonusr":{"maximumDays":"","warningDays":"7"},"Send Waring before this No of Days.":null,"Password validity (days)":null}},"name":"ApplianceManagement"}}}
At this point you can modify this file as needed. For example, you may need to modify the DNS configuration for a group of vCenter Servers to use a different one than that of the source vCenter, or you may want to remove all but the Appliance configuration.
Validating a Profile
Next we are looking at validating the profile against the target/remote vCenter that you want to apply it to. Be sure to get a session ID for the target vCenter Server to pass into this command!
1$destinationvcenter = "vm-vcsa-02.smt.com"
2$SessionHeaders = @{
3 "vmware-api-session-id" = "$($SessionID)"
4 "Content-type" = "application/json"
5}
6$body = Convertto-json @{
7 'config_spec' = Get-Content "C:\temp\vcenter-profile-export.json"
8}
9$validate = Invoke-RestMethod -Method POST -Uri "https://$($destinationvcenter)/api/appliance/infraprofile/configs?action=validate&vmw-task=true" -Headers $SessionHeaders -Body $body
10$validate
The below output confirms the file is good to go.
1912f7205-2e8f-429f-8b86-9610e5eac8f4:com.vmware.appliance.infraprofile.configs
Importing a Profile
Now to the good bit, importing the config! Like before, make sure to get a session ID for the target vCenter Server to pass into this command!
1$destinationvcenter = "vm-vcsa-02.smt.com"
2$SessionHeaders = @{
3 "vmware-api-session-id" = "$($SessionID)"
4 "Content-type" = "application/json"
5}
6$body = @{
7 'config_spec' = Get-Content "C:\temp\vcenter-profile-export.json"
8}
9$Import = Invoke-RestMethod -Method POST -Uri "https://$($destinationvcenter)/api/appliance/infraprofile/configs?action=import&vmw-task=true" -Headers $SessionHeaders -Body (Convertto-json $body)
10$Import
Before:
Output from running the import commands:
d843c731-c631-4b9b-87fe-4894134f433c:com.vmware.appliance.infraprofile.configs
After:
PowerShell Functions
Now to make this a bit easier (and to practice my PowerShell Function skills), I have made 5 PowerShell Functions that can be used. The code for each can be found here.
Get-vCenterAPISessionID
1Get-vCenterAPISessionID -vCenterFQDN vm-vcsa-02.smt.com -UserName administrator@vsphere.local -Password SecurePassword!
19ee52fe13c7ae8d42f777cadccf6b70d
Get-vCenterProfiles
1Get-vCenterProfiles -vCenterFQDN vm-vcsa-01.smt.com -SessionID 9ee52fe13c7ae8d42f777cadccf6b70d
Name | Info |
---|---|
ApplianceManagement | Appliance Mangment Service |
ApplianceNetwork | Appliance Network Configuration |
AuthManagement | Authentication & Authorization Management |
Export-vCenterProfiles
1Export-vCenterProfiles -vCenterFQDN vm-vcsa-02.smt.com -SessionID 9ee52fe13c7ae8d42f777cadccf6b70d -ExportPath C:\temp
Validate-vCenterProfiles
1Validate-vCenterProfiles -vCenterFQDN vm-vcsa-03.smt.com -SessionID 2b3fdd91604f67d124af041a23b46a1a -jsonPath C:\temp
121bfd471-95e3-48d3-841d-8452f2a09527:com.vmware.appliance.infraprofile.configs
Import-vCenterProfiles
1Import-vCenterProfiles -vCenterFQDN vm-vcsa-03.smt.com -SessionID 2b3fdd91604f67d124af041a23b46a1a -jsonPath C:\temp
14a742b45-c52e-4aa9-a67b-fe588084f02c:com.vmware.appliance.infraprofile.configs
Log File location on the vCenter Server: /var/log/vmware/infraprofile/infraprofile-svcs.log. This is were you need to be looking when troubleshooting!
Here’s a snippet:
12022-01-01T14:31:30.911Z [Thread-45 [] INFO com.vmware.appliance.infraprofilev1.core.ProfileOperations opId=] Complete importProfile ApplianceManagement
22022-01-01T14:31:31.072Z [Thread-45 [] INFO com.vmware.appliance.infraprofilev1.plugins.ApplianceManagementPlugin opId=] Start importing non generic format file /usr/bin/systemctl/sshd.service
32022-01-01T14:31:31.074Z [Thread-45 [] INFO com.vmware.appliance.infraprofilev1.util.MiscUtils opId=] Performing unmask operation on following System services: [[sshd.service]]
42022-01-01T14:31:31.439Z [Thread-45 [] INFO com.vmware.appliance.infraprofilev1.util.MiscUtils opId=] Performing enable operation on following System services: [[sshd.service]]
52022-01-01T14:31:31.864Z [Thread-45 [] INFO com.vmware.appliance.infraprofilev1.util.MiscUtils opId=] Performing start operation on following System services: [[sshd.service]]
62022-01-01T14:31:31.877Z [Thread-45 [] INFO com.vmware.appliance.infraprofilev1.plugins.ApplianceManagementPlugin opId=] Complete importing non generic format file /usr/bin/systemctl/sshd.service
72022-01-01T14:31:31.877Z [Thread-45 [] INFO com.vmware.appliance.infraprofilev1.plugins.ApplianceManagementPlugin opId=] Start importing non generic format file /etc/ntp.conf
82022-01-01T14:31:31.878Z [Thread-45 [] INFO com.vmware.appliance.infraprofilev1.plugins.ApplianceManagementPlugin opId=] Complete importing non generic format file /etc/ntp.conf
92022-01-01T14:31:31.878Z [Thread-45 [] INFO com.vmware.appliance.infraprofilev1.plugins.ApplianceManagementPlugin opId=] Start importing non generic format file /etc/mail/sendmail.cf
102022-01-01T14:31:31.882Z [Thread-45 [] INFO com.vmware.appliance.infraprofilev1.plugins.ApplianceManagementPlugin opId=] Complete importing non generic format file /etc/mail/sendmail.cf
112022-01-01T14:31:31.882Z [Thread-45 [] INFO com.vmware.appliance.infraprofilev1.plugins.ApplianceManagementPlugin opId=] Start importing non generic format file /etc/vmware-syslog/syslog.conf
122022-01-01T14:31:32.963Z [Thread-45 [] INFO com.vmware.appliance.infraprofilev1.plugins.ApplianceManagementPlugin opId=] Complete importing non generic format file /etc/vmware-syslog/syslog.conf
Thanks for reading!