cloudwindows-serveroracle-cloud-infrastructuresysprep

Generating a password for a generalized Windows Server instance on OCI


It is my understanding that the Oracle default Windows server images leverage Cloudbase-Init alongside an Unattend.xml file to generate a password for the user, but I am curious about the specifics of this as I am attempting to create my own images with additional software pre-installed. I want to generate a random password, and explicitly not require the user to change it. With that said here is what I have tried (I have only included the generalize portion of Unattend.xml files):

Attempt #1

For my first attempt, I did my best to imitate what I could (to the best of my knowledge) tell the default images were doing. This is the same unattend and cloubase config files as extracted from a generalized instance using Oracle's default Windows 2019 Standard image. Upon using these, the user is prompted to change their password on login.

Unattend.xml

  <settings pass="generalize">
    <component name="Microsoft-Windows-PnpSysprep" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <PersistAllDeviceInstalls>true</PersistAllDeviceInstalls>
    </component>
    <component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <RunSynchronous>
        <RunSynchronousCommand wcm:action="add">
          <Order>1</Order>
          <Path>cmd.exe /c ""c:\Program Files\Cloudbase Solutions\Cloudbase-Init\Python\Scripts\cloudbase-init.exe" --config-file "c:\Program Files\Cloudbase Solutions\Cloudbase-Init\conf\cloudbase-init-unattend.conf" &amp;&amp; exit 1 || exit 2"</Path>
          <Description>Run Cloudbase-Init to set the hostname</Description>
          <WillReboot>OnRequest</WillReboot>
        </RunSynchronousCommand>
      </RunSynchronous>
    </component>
  </settings>

cloudbase-init-unattend.conf

[DEFAULT]
username=opc
groups=Administrators
bsdtar_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\bsdtar.exe
mtools_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\
verbose=true
debug=true
logdir=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\log\
logfile=cloudbase-init-unattend.log
default_log_levels=comtypes=INFO,suds=INFO,iso8601=WARN,requests=WARN
logging_serial_port_settings=COM1,9600,N,8
local_scripts_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\LocalScripts\
metadata_services=cloudbaseinit.metadata.services.httpservice.HttpService
plugins=cloudbaseinit.plugins.windows.winrmlistener.ConfigWinRMListenerPlugin,cloudbaseinit.plugins.common.userdata.UserDataPlugin
allow_reboot=false
stop_service_on_exit=false
check_latest_version=false

Attempt #2

For my second attempt, I tried to add a command to the Unattend file that would cause the user not to be prompted to change their password. I used the same cloubase config files as in attempt #1. Upon generalization, the user was still prompted to choose a new password.

Unattend.xml

  <settings pass="generalize">
    <component name="Microsoft-Windows-PnpSysprep" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <PersistAllDeviceInstalls>true</PersistAllDeviceInstalls>
    </component>
    <component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <RunSynchronous>
        <RunSynchronousCommand wcm:action="add">
          <Order>1</Order>
          <Path>cmd.exe /c "net user opc /logonpasswordchg:no &amp;&amp; exit 1 || exit 2</Path>
          <Description>Ensure the opc user does not have to reset their password</Description>
          <WillReboot>Never</WillReboot>
        </RunSynchronousCommand>
        <RunSynchronousCommand wcm:action="add">
          <Order>2</Order>
          <Path>cmd.exe /c ""c:\Program Files\Cloudbase Solutions\Cloudbase-Init\Python\Scripts\cloudbase-init.exe" --config-file "c:\Program Files\Cloudbase Solutions\Cloudbase-Init\conf\cloudbase-init-unattend.conf" &amp;&amp; exit 1 || exit 2"</Path>
          <Description>Run Cloudbase-Init to set the hostname</Description>
          <WillReboot>OnRequest</WillReboot>
        </RunSynchronousCommand>
      </RunSynchronous>
    </component>
  </settings>

Attempt #3

For my third attempt, I changed the order of commands within the Unattend file such that the net user was told not to change their password on login after the cloudbase init configuration was processed. I once again used the same cloubase config files as in attempt #1 and #2. Upon generalization, the user was still prompted to choose a new password.

Unattend.xml

  <settings pass="generalize">
    <component name="Microsoft-Windows-PnpSysprep" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <PersistAllDeviceInstalls>true</PersistAllDeviceInstalls>
    </component>
    <component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <RunSynchronous>
        <RunSynchronousCommand wcm:action="add">
          <Order>1</Order>
          <Path>cmd.exe /c ""c:\Program Files\Cloudbase Solutions\Cloudbase-Init\Python\Scripts\cloudbase-init.exe" --config-file "c:\Program Files\Cloudbase Solutions\Cloudbase-Init\conf\cloudbase-init-unattend.conf" &amp;&amp; exit 1 || exit 2"</Path>
          <Description>Run Cloudbase-Init to set the hostname</Description>
          <WillReboot>OnRequest</WillReboot>
        </RunSynchronousCommand>
        <RunSynchronousCommand wcm:action="add">
          <Order>2</Order>
          <Path>cmd.exe /c "net user opc /logonpasswordchg:no &amp;&amp; exit 1 || exit 2</Path>
          <Description>Ensure the opc user does not have to reset their password</Description>
          <WillReboot>Never</WillReboot>
        </RunSynchronousCommand>
      </RunSynchronous>
    </component>
  </settings>

None of these approaches yielded what I was looking for. I also tried using a plugin within Cloudbase-Init to generate a password, but it seemed that perhaps the Oracle Cloud Agent overrode this, as I was completely unable to login via RDP, whereas without using the Cloudbase plugin I could login but was unable to access a desktop prior to setting a new password.

This begs the question: what isn't working here? Is this a configuration issue, or am I fundamentally misunderstanding how this process works?

I would appreciate any suggestions anybody may have, or example implementations others have created. Thanks!


Solution

  • Although I was unable to get the Unattend.xml file to automatically run my command, it turns out that the easiest solution was to use Cloudbase-Init userdata to supply my command. The final userdata script ended up looking like this:

    rem cmd
    net user opc /logonpasswordchg:no
    

    I hope this helps anybody who finds this question in the future.