2
votes

My question is a bit complex, so I will start with a short explanation of the context. The goal is to:

  • Create a new Windows instance on the Google Cloud Platform
  • Avoid the usage of the gcloud command line sdk and instead use the (REST) API
  • Connect to the VM via powershell (not rdp)

Problem

There is no API to create a new windows account and password, like it exists for the gcloud command line:

gcloud compute reset-windows-password

But of course an user is needed to connect to the vm.


My ideas

I tried to use a startup script which creates a new user. The powershell script already works like expected on a running machine (as administrator):

$ADSIComp =[adsi]"WinNT://test-remote"
$NewUser = $ADSIComp.Create('User','test')
$NewUser.SetPassword(('S€cur3P@ssword'))
$NewUser.SetInfo()
$Group = [ADSI]"WinNT://test-remote/Administrators,group"
$Group.Add("WinNT://test,user")

Google cloud provides different types of startup scripts (see here). I tried to use sysprep-specialize-script-ps1, so it only runs once. (Is this correct?). To test if this works, I created a new windows instance on the google cloud dashboard. In the metadata section I inserted sysprep-specialize-script-ps1 as metakey and the script lines in brackets as value.

Result

I created a new user on the dashboard to login on the windows machine. But there is no user created by the above script. So my approach failed.


Open Questions

Can you see (conceptual or technical) mistakes in my process?

Is there any other way to achieve the specified goal?

Thank you!

1

1 Answers

1
votes

You can look at the Python/Java example provided here which lets you use the Google Cloud Client libraries to generate a new password for your Windows VM and actually print it locally.

Automating Windows Password Generation

The gcloud compute reset-windows-password command allows a user with write access to the Compute Engine project to securely retrieve passwords for accounts on Windows instances.

The command does this by sending a username and an RSA public key to the instance. The agent running on the instance then either:

  • Creates an account on the instance for that username and generates a random password.
  • Resets the password to a random value if the account already exists.

The agent running on the instance encrypts the password with the provided public key and sends it back to the client to be decrypted by the corresponding private key.

The process works like this:

  1. You get to choose the username you pass.
  2. You pass in the public key of the RSA key pair used for encryption. You keep the private key of the RSA key pair with you locally.
  3. Overwrite the windows-keys metadata on the VM with the info mentioned in steps 1 and 2.
  4. The encrypted password is printed to COM4 serial port.
  5. You then pull the encrypted password and decrypt it locally on your machine.

There are Compute Engine APIs for updating an instance's metadata as well as reading an instance's Serial port output. The example I pointed out earlier using Client libraries uses those APIs.

So you could either build your script/application using the client library or directly invoke the APIs I mentioned above.

Reinventing the wheel

Since I do not know the exact reason why you want to avoid using gcloud, I wanted to point it out that the manual way using either the Client library of REST APIs is performing essentially the exact same steps done by a convenient gcloud compute reset-windows-password command.

In other words, you might be re-inventing the wheel here. There are legitimate cases for doing this, like you want to add this logic to your application and do not want to invoke external programs to do this. If you only intend to use this as part of scripting, I would recommend to reuse gcloud unless there is a strong argument against using it.