hashicorp / packer

Packer is a tool for creating identical machine images for multiple platforms from a single source configuration.
http://www.packer.io
Other
14.99k stars 3.32k forks source link

OCI Windows Instance admin launch password - pass to winrm for provisioners #7033

Open Marcus-James-Adams opened 5 years ago

Marcus-James-Adams commented 5 years ago

This could be me not fully understanding the documentation and I think all the outstanding blockers are now resolved, and there seem to be a number of tickets about it, but I don't seem to see the one that pulls it all together.

So we want to create our own Gold Windows OS images based up the OCI provided images but that we have run windows-update and added a number of other core features that we then use as a base of our BAU packer processes. And this is currently the only non-automated part of our process now.

The now seems to be a way for the builder to get the auto-generated password and windows images now have winrm enabled by default along with cloud-init.

So how do I configure my builder/provisioner when working in OCI so that I can pass the automatically generated password into winrm so that I can provision builds?

sardm commented 5 years ago

Did you ever figure it out?

Were you able to test WinRM function on the image via + To use WinRM on an instance (https://docs.cloud.oracle.com/iaas/Content/Compute/References/images.htm). Testing this fails with the OCI images so far for me.

On the OCI provided images I've tried this in the builder section (and combos of this) with no dice, but also the remote PSSessions aren't working as described (verified connectivity and subnet acl):

  "communicator": "winrm",
  "winrm_username": "opc",
  "winrm_password": "{{.WinRMPassword}}",    (I think this should work)
  "winrm_use_ssl": true,
  "winrm_insecure": true,

Packer v1.3.2

SwampDragons commented 5 years ago

@sardm that's not quite right. You don't use the {{.WinRMPassword}} syntax when configuring the communicator; you just need to remove "winrm_password": "{{.WinRMPassword}}", from your config and Packer will handle the password setting for you.

Then to access the winrm password in the provisioners you use that "{{.WinRMPassword}}" syntax.

SwampDragons commented 5 years ago

@Marcus-James-Adams Does the example here help clarify how to use the template engine to pass in the winrm password? This engine doesn't work for all fields for all provisioners, but does work for various fields in the powershell and shell-local provisioners, as well as the ansible provisioner and maybe a couple of others. All of the provisioners which allow this functionality should have it documented on their docs pages.

Marcus-James-Adams commented 5 years ago

@SwampDragons I've gone through the various options of winrm_password with the oci build and get the following. This is using the latest original OCI windows image. it looks like wither it's not calling the api to get the password or it's not being passed forwards. Builders snipped to remove sensative TRY 1 - should fail No winrm_username or winrm_password line { "name": "TEST.us-ashburn-1.VM.STANDARD2.1", "availability_domain": "rqxq:US-ASHBURN-AD-2", "region": "us-ashburn-1", "base_image_ocid": "ocid1.image.oc1.iad.aaaaaaaazmb3mok4qsrfwrqmixswkla7jzxu5z6i554zhligizmufpnhb3za", "shape": "VM.Standard2.1", "communicator": "winrm", "type": "oracle-oci" } 1 error(s) occurred:

TRY 2 Set winrm_username to Oracle default, no winrm_password line { "name": "TEST.us-ashburn-1.VM.STANDARD2.1", "availability_domain": "rqxq:US-ASHBURN-AD-2", "region": "us-ashburn-1", "base_image_ocid": "ocid1.image.oc1.iad.aaaaaaaazmb3mok4qsrfwrqmixswkla7jzxu5z6i554zhligizmufpnhb3za", "shape": "VM.Standard2.1", "communicator": "winrm", "winrm_username": "opc", "type": "oracle-oci" } ==> TEST.us-ashburn-1.VM.STANDARD2.1: Instance 'RUNNING'. ==> TEST.us-ashburn-1.VM.STANDARD2.1: Instance has IP: 129.213.137.52. ==> TEST.us-ashburn-1.VM.STANDARD2.1: Using winrm communicator to connect: 129.213.137.52 ==> TEST.us-ashburn-1.VM.STANDARD2.1: Waiting for WinRM to become available... ==> TEST.us-ashburn-1.VM.STANDARD2.1: Timeout waiting for WinRM. ==> TEST.us-ashburn-1.VM.STANDARD2.1: Timeout waiting for WinRM.

TRY 3
Set winrm_username to Oracle default, set winrm_password to "" { "name": "TEST.us-ashburn-1.VM.STANDARD2.1", "availability_domain": "rqxq:US-ASHBURN-AD-2", "region": "us-ashburn-1", "base_image_ocid": "ocid1.image.oc1.iad.aaaaaaaazmb3mok4qsrfwrqmixswkla7jzxu5z6i554zhligizmufpnhb3za", "shape": "VM.Standard2.1", "shape": "VM.Standard2.1", "communicator": "winrm", "winrm_username": "opc", "winrm_password": "", "type": "oracle-oci" } => TEST.us-ashburn-1.VM.STANDARD2.1: Waiting for instance to enter 'RUNNING' state... => TEST.us-ashburn-1.VM.STANDARD2.1: Instance 'RUNNING'. => TEST.us-ashburn-1.VM.STANDARD2.1: Instance has IP: 132.145.170.37. => TEST.us-ashburn-1.VM.STANDARD2.1: Using winrm communicator to connect: 132.145.170.37 => TEST.us-ashburn-1.VM.STANDARD2.1: Waiting for WinRM to become available... => TEST.us-ashburn-1.VM.STANDARD2.1: Timeout waiting for WinRM. => TEST.us-ashburn-1.VM.STANDARD2.1: Timeout waiting for WinRM.

SwampDragons commented 5 years ago

Okay so you're having trouble getting it to connect to winrm at all. I checked my notes from when I was working on this. It looks like you're missing a user data file:

 "user_data_file": "./windows_auto_generated_winrm_pass.ps1"

Where that file contains code setting up winrm. I thought I'd gotten this working, but I have a note in this config that I hadn't gotten the winrmpassword thing figured out yet. My oracle credentials have expired so I'm going to have to try to track new ones down before I can do real life testing on this. I'll try to get back to you soon but I'm not sure I'm going to have time to get this figured out before the new year.

Marcus-James-Adams commented 5 years ago

@SwampDragons I'll try that on my creds as that was my "trying to avoid workaround" but according to this and blogs https://docs.cloud.oracle.com/iaas/images/windows-server-2012-r2-bm/ from Jul(ish) winrm has been enabled by default on images to make things a bit easier.

SwampDragons commented 5 years ago

Just a thought -- by default, Packer isn't messing around with ingress rules on the security lists for whatever subnet you're on; you need to make sure your port for winrm is open by adding a new ingress rule to that list. I've found some credentials, and I'm also stuck on getting winrm to connect. I'll see if I can figure it out.

Marcus-James-Adams commented 5 years ago

Hi Just to say in my example testing I also did a try 4 with an image that I had previously set the opc password to and set winrm to that. I used the same machine for all four tests and its one I know has full all ports/protocols access to the oci compartment That goes through fine and packer builds ok

Marcus-James-Adams commented 5 years ago

Just a further update on this, I've tried using user data as a way to get around this, using scripts that work for other provisioners ( changing to ps native ads said) but they don't seem to work either. it still hangs at the waiting at winrm. This is a pain as OCI now has a number of different hardware combos that all require their own base image so having to manually create images in order to create images is long and just feels so wrong

SwampDragons commented 5 years ago

Sounds like there's definitely something still wrong on the Packer side.

scross01 commented 5 years ago

To get WinRM working for remote provisioning OCI Windows images there are a few small hurdles to jump through:

The article https://medium.com/oracledevs/managing-oracle-cloud-infrastructure-iscsi-block-volume-attachments-with-terraform-16ae46fdf3b4 covers how I got this working with Terraform, the same approach may work for Packer.

  1. Create a security rule in the target subnet security list to enable port tcp/5986

  2. The initial password is expired in order to force a password change on first login, this however prevents any WinRM connection. Adding the following cloudbase-init script on instance launch will un-expire the initial password

    #ps1_sysnative
    cmd /C 'wmic UserAccount where Name="opc" set PasswordExpires=False'
  3. The initial password to access instance is autogenerated and can be fetched using the GetWindowsInstanceInitialCredentials API

emanuelgrama commented 5 years ago

Hello,

Any updates on this issue? I am facing the same problem and none of the workarounds mentioned are working for me.

Thanks

scross01 commented 5 years ago

The following example uses a cloudbase-init script when creating the builder instance to overrides the initial password and disable the password reset to allow connectivity over WinRM. The same password needs to be set in both the userdata.ps1 file and the packer json.

userdata.ps1

#ps1_sysnative
cmd /C 'wmic UserAccount where Name="opc" set PasswordExpires=False'
$opcUser = get-wmiobject win32_useraccount | Where-Object { $_.Name -match 'opc' }
([adsi]("WinNT://"+$opcUser.caption).replace("\","/")).SetPassword("myTemp#Pa55_Word")

packer.json

{
    "builders": [
        {
            "type": "oracle-oci",
            "availability_domain": "ilMx:CA-TORONTO-1-AD-1",
            "base_image_ocid": "ocid1.image.oc1....",
            "compartment_ocid": "ocid1.compartment.oc1.....",
            "subnet_ocid": "ocid1.subnet.oc1....",
            "shape": "VM.Standard2.1",
            "image_name": "MyWinImage",
            "communicator": "winrm",
            "winrm_username": "opc",
            "winrm_password": "myTemp#Pa55_Word",
            "winrm_insecure": true,
            "winrm_use_ssl": true,
            "winrm_port": 5986,
            "user_data_file": "./userdata.ps1"
        }
    ],
    "provisioners": [
        {
            "type": "windows-shell",
            "inline": [
                "dir c:\\"
            ]
        }
    ]
}
hatvik commented 5 years ago

(Thanks to Stephen)

Use userdata to set new a pw

cmd /C 'wmic UserAccount where Name="opc" set PasswordExpires=False'
$opcUser = get-wmiobject win32_useraccount | Where-Object { $_.Name -match 'opc' }
([adsi]("WinNT://"+$opcUser.caption).replace("\","/")).SetPassword("#Pa55_Word")

Use it in the builder:

            "type": "oracle-oci",
            "communicator": "winrm",
            "winrm_username": "opc",
            "winrm_password": "#Pa55_Word",
            "winrm_insecure": true,
            "winrm_use_ssl": true,
            "winrm_port": 5986,
            "user_data_file": "./userdata/windows.ps1"
anil-shenoy-in commented 4 years ago

Hi!

How do i run powershell scripts in provisioners with elevated privileges while building a Windows Image in OCI ?

Usage of provisioners as mentioned below, gives me error Failed to parse template: Error parsing JSON: invalid character '"' after object key:value pair

"provisioners":[ { "type": "powershell", "scripts": [ "../PSSCRIPTS/InvokeWebRequestPrereq.ps1", "../PSSCRIPTS/DownloadObjects.ps1" ] "elevated_user": "opc", "elevated_password": "{{.winrm_password}}" } ]

SwampDragons commented 4 years ago

Try {{ build `Password` }}instead. (docs: https://packer.io/docs/templates/engine.html#build)

anil-shenoy-in commented 4 years ago

Thank you for the reply. Using the 'Password' variable in Provisioners gives me the same error. Failed to parse template: Error parsing JSON: invalid character '"' after object key:value pair

   "elevated_user": "opc",
        "elevated_password": "{{ build 'Password'}}"

Any other suggestions that has worked ?

SwampDragons commented 4 years ago

you need to use backticks, not single quotes.

anil-shenoy-in commented 4 years ago

Thank you very much @SwampDragons . The below worked fine. "elevated_user": "opc", "elevated_password": "{{.WinRMPassword}}"

Digging into what went wrong the previous time.

mdf-ido commented 7 months ago

To get WinRM working for remote provisioning OCI Windows images there are a few small hurdles to jump through:

The article https://medium.com/oracledevs/managing-oracle-cloud-infrastructure-iscsi-block-volume-attachments-with-terraform-16ae46fdf3b4 covers how I got this working with Terraform, the same approach may work for Packer.

  1. Create a security rule in the target subnet security list to enable port tcp/5986
  2. The initial password is expired in order to force a password change on first login, this however prevents any WinRM connection. Adding the following cloudbase-init script on instance launch will un-expire the initial password
#ps1_sysnative
cmd /C 'wmic UserAccount where Name="opc" set PasswordExpires=False'
  1. The initial password to access instance is autogenerated and can be fetched using the GetWindowsInstanceInitialCredentials API

Thank you! I didn't have to specify a password and just used this

jmdoman commented 3 months ago

To get WinRM working for remote provisioning OCI Windows images there are a few small hurdles to jump through: The article https://medium.com/oracledevs/managing-oracle-cloud-infrastructure-iscsi-block-volume-attachments-with-terraform-16ae46fdf3b4 covers how I got this working with Terraform, the same approach may work for Packer.

  1. Create a security rule in the target subnet security list to enable port tcp/5986
  2. The initial password is expired in order to force a password change on first login, this however prevents any WinRM connection. Adding the following cloudbase-init script on instance launch will un-expire the initial password
#ps1_sysnative
cmd /C 'wmic UserAccount where Name="opc" set PasswordExpires=False'
  1. The initial password to access instance is autogenerated and can be fetched using the GetWindowsInstanceInitialCredentials API

Thank you! I didn't have to specify a password and just used this

Did you have to use an API at all to make the image? If not, did you just leave the winrm_password variable blank? Please share

luckeyca commented 1 week ago

To get WinRM working for remote provisioning OCI Windows images there are a few small hurdles to jump through: The article https://medium.com/oracledevs/managing-oracle-cloud-infrastructure-iscsi-block-volume-attachments-with-terraform-16ae46fdf3b4 covers how I got this working with Terraform, the same approach may work for Packer.

  1. Create a security rule in the target subnet security list to enable port tcp/5986
  2. The initial password is expired in order to force a password change on first login, this however prevents any WinRM connection. Adding the following cloudbase-init script on instance launch will un-expire the initial password
#ps1_sysnative
cmd /C 'wmic UserAccount where Name="opc" set PasswordExpires=False'
  1. The initial password to access instance is autogenerated and can be fetched using the GetWindowsInstanceInitialCredentials API

Thank you! I didn't have to specify a password and just used this

Did you have to use an API at all to make the image? If not, did you just leave the winrm_password variable blank? Please share

with the one-liner cloudbase-init script as below, only set winrm_username = "opc", but DO NOT set winrm_password.

#ps1_sysnative
cmd /C 'wmic UserAccount where Name="opc" set PasswordExpires=False'
jmdoman commented 1 day ago

To get WinRM working for remote provisioning OCI Windows images there are a few small hurdles to jump through: The article https://medium.com/oracledevs/managing-oracle-cloud-infrastructure-iscsi-block-volume-attachments-with-terraform-16ae46fdf3b4 covers how I got this working with Terraform, the same approach may work for Packer.

  1. Create a security rule in the target subnet security list to enable port tcp/5986
  2. The initial password is expired in order to force a password change on first login, this however prevents any WinRM connection. Adding the following cloudbase-init script on instance launch will un-expire the initial password
#ps1_sysnative
cmd /C 'wmic UserAccount where Name="opc" set PasswordExpires=False'
  1. The initial password to access instance is autogenerated and can be fetched using the GetWindowsInstanceInitialCredentials API

Thank you! I didn't have to specify a password and just used this

Did you have to use an API at all to make the image? If not, did you just leave the winrm_password variable blank? Please share

with the one-liner cloudbase-init script as below, only set winrm_username = "opc", but DO NOT set winrm_password.

#ps1_sysnative
cmd /C 'wmic UserAccount where Name="opc" set PasswordExpires=False'

This all works, but the resulting image is useless because it's not possible to know what the OPC password is. So any instance created from this image is not able to ever be logged onto. I know there's an API for retrieving the password but how on earth can I use that API within Packer? And then I suppose I can somehow store that password somewhere to be used later? To be clear, and to save time for anyone else reading this: in OCI, once you use any kind of custom image to make an instance, the opc password is gone permanently. you can't retrieve it at all, AFAIK. Not from the web console, and not from terraform ( I tried this datasource with no success). That auto-generated opc password is only available if you make an instance from Oracle's image library. Once you go to making instance from custom images, it's gone. it just uses the same password as the original instance had, which of course Packer has already deleted as part of its cleanup. You can probably reset the opc password with terraform but the original autogenerated password is gone.

luckeyca commented 1 day ago

@jmdoman. that would be the next and final step which depends on what type of the image you want. Check out this oracle documentation: https://docs.oracle.com/en-us/iaas/Content/Compute/References/windowsimages.htm. for specialized image, you have to set/hardcoded the initial password in the image. for generalized/syspreped image, the scripts will help you create an image which behaves like the OCI platform image which will create random password that can be seen on OCI console. You do need to modify the Generalize.cmd to remove the "ipconfig /release" command as these scripts are meant for manual process and will kill automated packer process.