Fixes #29187 - using winrm on EC2

This commit is contained in:
Trevor Hammond 2015-11-25 18:36:11 +00:00
parent 11d68f7b1c
commit 48e0edd0d2
3 changed files with 97 additions and 9 deletions

View file

@ -75,7 +75,50 @@ profile configuration as `userdata_file`. For instance:
userdata_file: /etc/salt/windows-firewall.ps1
If you are using WinRM on EC2 the HTTPS port for the WinRM service must also be enabled
in your userdata. By default EC2 Windows images only have insecure HTTP enabled. To
enable HTTPS and basic authentication required by pywinrm consider the following
userdata example:
.. code-block:: powershell
<powershell>
New-NetFirewallRule -Name "SMB445" -DisplayName "SMB445" -Protocol TCP -LocalPort 445
New-NetFirewallRule -Name "WINRM5986" -DisplayName "WINRM5986" -Protocol TCP -LocalPort 5986
winrm quickconfig -q
winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="300"}'
winrm set winrm/config '@{MaxTimeoutms="1800000"}'
winrm set winrm/config/service/auth '@{Basic="true"}'
$SourceStoreScope = 'LocalMachine'
$SourceStorename = 'Remote Desktop'
$SourceStore = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store -ArgumentList $SourceStorename, $SourceStoreScope
$SourceStore.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly)
$cert = $SourceStore.Certificates | Where-Object -FilterScript {
$_.subject -like '*'
}
$DestStoreScope = 'LocalMachine'
$DestStoreName = 'My'
$DestStore = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store -ArgumentList $DestStoreName, $DestStoreScope
$DestStore.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
$DestStore.Add($cert)
$SourceStore.Close()
$DestStore.Close()
winrm create winrm/config/listener?Address=*+Transport=HTTPS `@`{Hostname=`"($certId)`"`;CertificateThumbprint=`"($cert.Thumbprint)`"`}
Restart-Service winrm
</powershell>
No certificate store is available by default on EC2 images and creating
one does not seem possible without an MMC (cannot be automated). To use the
default EC2 Windows images the above copies the RDP store.
Configuration
=============
@ -102,7 +145,8 @@ Setting the installer in ``/etc/salt/cloud.providers``:
The default Windows user is `Administrator`, and the default Windows password
is blank.
If WinRM is to be used ``use_winrm`` needs to be set to `True`.
If WinRM is to be used ``use_winrm`` needs to be set to `True`. ``winrm_port``
can be used to specify a custom port (must be HTTPS listener).
Auto-Generated Passwords on EC2

View file

@ -2125,6 +2125,10 @@ def wait_for_instance(
win_deploy_auth_retry_delay = config.get_cloud_config_value(
'win_deploy_auth_retry_delay', vm_, __opts__, default=1
)
use_winrm = config.get_cloud_config_value(
'use_winrm', vm_, __opts__, default=False
)
if win_passwd and win_passwd == 'auto':
log.debug('Waiting for auto-generated Windows EC2 password')
while True:
@ -2151,20 +2155,55 @@ def wait_for_instance(
vm_['win_password'] = win_passwd
break
# SMB used whether winexe or winrm
if not salt.utils.cloud.wait_for_port(ip_address,
port=445,
timeout=ssh_connect_timeout):
raise SaltCloudSystemExit(
'Failed to connect to remote windows host'
)
if not salt.utils.cloud.validate_windows_cred(ip_address,
username,
win_passwd,
retries=win_deploy_auth_retries,
retry_delay=win_deploy_auth_retry_delay):
raise SaltCloudSystemExit(
'Failed to authenticate against remote windows host'
# If not using winrm keep same winexe behavior
if not use_winrm:
log.debug('Trying to authenticate via SMB using winexe')
if not salt.utils.cloud.validate_windows_cred(ip_address,
username,
win_passwd,
retries=win_deploy_auth_retries,
retry_delay=win_deploy_auth_retry_delay):
raise SaltCloudSystemExit(
'Failed to authenticate against remote windows host (smb)'
)
# If using winrm
else:
# Default HTTPS port can be changed in cloud configuration
winrm_port = config.get_cloud_config_value(
'winrm_port', vm_, __opts__, default=5986
)
# Wait for winrm port to be available
if not salt.utils.cloud.wait_for_port(ip_address,
port=winrm_port,
timeout=ssh_connect_timeout):
raise SaltCloudSystemExit(
'Failed to connect to remote windows host (winrm)'
)
log.debug('Trying to authenticate via Winrm using pywinrm')
if not salt.utils.cloud.wait_for_winrm(ip_address,
winrm_port,
username,
win_passwd,
timeout=ssh_connect_timeout):
raise SaltCloudSystemExit(
'Failed to authenticate against remote windows host'
)
elif salt.utils.cloud.wait_for_port(ip_address,
port=ssh_port,
timeout=ssh_connect_timeout,

View file

@ -463,6 +463,9 @@ def bootstrap(vm_, opts):
deploy_kwargs['use_winrm'] = salt.config.get_cloud_config_value(
'use_winrm', vm_, opts, default=False
)
deploy_kwargs['winrm_port'] = salt.config.get_cloud_config_value(
'winrm_port', vm_, opts, default=5986
)
# Store what was used to the deploy the VM
event_kwargs = copy.deepcopy(deploy_kwargs)
@ -810,6 +813,7 @@ def wait_for_winrm(host, port, username, password, timeout=900):
host, port, trycount
)
)
time.sleep(1)
def validate_windows_cred(host,
@ -932,6 +936,7 @@ def deploy_windows(host,
opts=None,
master_sign_pub_file=None,
use_winrm=False,
winrm_port=5986,
**kwargs):
'''
Copy the install files to a remote Windows box, and execute them
@ -956,7 +961,7 @@ def deploy_windows(host,
winrm_session = None
if HAS_WINRM and use_winrm:
winrm_session = wait_for_winrm(host=host, port=5986,
winrm_session = wait_for_winrm(host=host, port=winrm_port,
username=username, password=password,
timeout=port_timeout * 60)
if winrm_session is not None: