New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suppport for kerberos\domain authentication for winrm #8345

Closed
wants to merge 1 commit into
base: devel
from

Conversation

Projects
None yet
@bennojoy
Contributor

bennojoy commented Jul 30, 2014

This patch allows ansible to authenticate to winrm server via kerberos for Domain users.

Pre-requisite steps on Ansible host:

  1. kinit user@domain.com [The user gets a valid kerberos ticket to authenticate]

  2. Set the windows variables in ansible.
    ansible_ssh_user: ansible_kerberos
    ansible_ssh_pass: ansible_kerberos
    ansible_ssh_port: 5986
    ansible_connection: winrm
    Please make sure the username and password is set to 'ansible_kerberos' which tells ansible to use the kerberos ticket for authentication.

Pre-requisite steps on Windows host:

  1. Follow the steps on http://docs.ansible.com/intro_windows.html under the section "Window sys prep"

  2. Make sure that Kerberos and Negotiate authentication is enabled on WinRm service.
    'winrm g winrm/config/service/auth'

  3. Verify connection with WinRM service using Kerberos.
    'winrm id -r:hostname.somedomain.com -a:Kerberos -u:domainusername@somedomain.com -p:'

  4. Make sure there are no firewall blocking access to winrm service from ansible host.
    on ansible host: 'telnet 5986/5'

Notes:
kinit is provided with the package 'krb5-workstation' in centos/Rhel

An example /etc/krb5.conf file

[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 default_realm = BENNO.COM
 dns_lookup_kdc = false
 ticket_lifetime = 24h
 renew_lifetime = 7d
 forwardable = true
 udp_preference_limit = 1

[realms]
 BENNO.COM = {
  kdc = WIN-EUO6PCEBU37.benno.com
  admin_server = WIN-EUO6PCEBU37.benno.com
  default_domain = benno.com
 }

[appdefaults]
validate=false

[domain_realm]
 .benno.com = BENNO.COM
 benno.com = BENNO.COM

Please also make sure the hostnames given in ansible are available in both FORWARD and REVERSE DNS lookups.

@trondhindenes

This comment has been minimized.

Show comment
Hide comment
@trondhindenes

trondhindenes Jul 30, 2014

Contributor

+1

Contributor

trondhindenes commented Jul 30, 2014

+1

@mpdehaan

This comment has been minimized.

Show comment
Hide comment
@mpdehaan

mpdehaan Jul 30, 2014

Contributor

Somebody on the list was also asking about this, I'll share with them so we can get some joint review.

I think the PR should also add the above to the Windows setup docs in a "Kerberos" section, ideally, as this may be hard for people to guess.

Thanks!!!

Contributor

mpdehaan commented Jul 30, 2014

Somebody on the list was also asking about this, I'll share with them so we can get some joint review.

I think the PR should also add the above to the Windows setup docs in a "Kerberos" section, ideally, as this may be hard for people to guess.

Thanks!!!

@mpdehaan mpdehaan added P2 labels Jul 30, 2014

@walthowd

This comment has been minimized.

Show comment
Hide comment
@walthowd

walthowd Jul 30, 2014

I tested this with ansible 1.7 (devel 189824d) under Ubuntu 14.04.1 and it worked against a large selection of Windows machines over the type of SSL endpoint currently recommended in the documentation.

The only issue I saw is that I receive 20 to 25 lines of the following every time I run a win_ping:
User username@DOMAIN.COM authenticated successfully using Kerberos authentication (EDIT -- Looks like that is coming from pywinrm here - https://github.com/diyan/pywinrm/blob/master/winrm/transport.py#L164 )

If the PR includes the docsite changes, you should include the fact that you need python-dev and libkrb5-dev installed on Debian based systems, and that you need the Python Kerberos module (pip install kerberos).

walthowd commented Jul 30, 2014

I tested this with ansible 1.7 (devel 189824d) under Ubuntu 14.04.1 and it worked against a large selection of Windows machines over the type of SSL endpoint currently recommended in the documentation.

The only issue I saw is that I receive 20 to 25 lines of the following every time I run a win_ping:
User username@DOMAIN.COM authenticated successfully using Kerberos authentication (EDIT -- Looks like that is coming from pywinrm here - https://github.com/diyan/pywinrm/blob/master/winrm/transport.py#L164 )

If the PR includes the docsite changes, you should include the fact that you need python-dev and libkrb5-dev installed on Debian based systems, and that you need the Python Kerberos module (pip install kerberos).

@bennojoy

This comment has been minimized.

Show comment
Hide comment
@bennojoy

bennojoy Jul 31, 2014

Contributor

yeah.. those lines are due to the print statement in transport.py of winrm, i will try to send in a patch upsteam.

Contributor

bennojoy commented Jul 31, 2014

yeah.. those lines are due to the print statement in transport.py of winrm, i will try to send in a patch upsteam.

@ianclegg

This comment has been minimized.

Show comment
Hide comment
@ianclegg

ianclegg Jul 31, 2014

Contributor

Great see this is being worked on! All, a number of engineers will be operating in regulated sectors where they may need different credentials for different hosts. One thing I would like to see in this feature is a way to specify the identity of the user to be used.

I believe that it we 'shore up' pywinrm it should be possible without any changes whatsoever to ansible. Of course this will depend on the pywinrm's appetite for enhancement.

Ultimately, thinking about desired behaviour, may I suggest the following:

Kerberos single sign on
ansible_ssh_user: <not specified>
ansible_ssh_pass: <not specified>

Its safe to say the only sensible thing we can do here is try kerberos with the current users UPN aka Single Sign On (this what you were doing with 'ansible_kerberos' / 'ansible_kerberos' combination).

Kerberos with a specific user (UPN)
ansible_ssh_user: user@realm
ansible_ssh_pass:

This is not a valid local windows username, but is a valid UPN, so its kerb. There is no password so we cant acquire a TGT. So check the ticket cache. If do not have a valid TGT for that identify we should prompt or fail.

Kerberos with a specific username password
ansible_ssh_user: user@realm
ansible_ssh_pass: password

We have a password this time so we can silently acquire a TGT if a valid one does not already exist.

pywinrm doe not yet distinguish very well between transports and authentication, if we can address this there it would be a more elegant solution. I will look into this now.

Contributor

ianclegg commented Jul 31, 2014

Great see this is being worked on! All, a number of engineers will be operating in regulated sectors where they may need different credentials for different hosts. One thing I would like to see in this feature is a way to specify the identity of the user to be used.

I believe that it we 'shore up' pywinrm it should be possible without any changes whatsoever to ansible. Of course this will depend on the pywinrm's appetite for enhancement.

Ultimately, thinking about desired behaviour, may I suggest the following:

Kerberos single sign on
ansible_ssh_user: <not specified>
ansible_ssh_pass: <not specified>

Its safe to say the only sensible thing we can do here is try kerberos with the current users UPN aka Single Sign On (this what you were doing with 'ansible_kerberos' / 'ansible_kerberos' combination).

Kerberos with a specific user (UPN)
ansible_ssh_user: user@realm
ansible_ssh_pass:

This is not a valid local windows username, but is a valid UPN, so its kerb. There is no password so we cant acquire a TGT. So check the ticket cache. If do not have a valid TGT for that identify we should prompt or fail.

Kerberos with a specific username password
ansible_ssh_user: user@realm
ansible_ssh_pass: password

We have a password this time so we can silently acquire a TGT if a valid one does not already exist.

pywinrm doe not yet distinguish very well between transports and authentication, if we can address this there it would be a more elegant solution. I will look into this now.

@bennojoy

This comment has been minimized.

Show comment
Hide comment
@bennojoy

bennojoy Jul 31, 2014

Contributor

Totally agree, we should support all the three options also as said the logic should rather be in pywinrm than Ansible.
The reason for choosing 'ansible_kerberos/ansible_kerberos' as username/password rather than null was becuase there is a caching mechanism in our winm connection plugin which caches the transport/authentication object based on the username/password and i didnt want to bypass that.

Contributor

bennojoy commented Jul 31, 2014

Totally agree, we should support all the three options also as said the logic should rather be in pywinrm than Ansible.
The reason for choosing 'ansible_kerberos/ansible_kerberos' as username/password rather than null was becuase there is a caching mechanism in our winm connection plugin which caches the transport/authentication object based on the username/password and i didnt want to bypass that.

@ianclegg

This comment has been minimized.

Show comment
Hide comment
@ianclegg

ianclegg Jul 31, 2014

Contributor

@bennojoy I hadn't seen that caching, but it shouldn't be hard to address

Contributor

ianclegg commented Jul 31, 2014

@bennojoy I hadn't seen that caching, but it shouldn't be hard to address

@cchurch

This comment has been minimized.

Show comment
Hide comment
@cchurch

cchurch Aug 3, 2014

Member

@bennojoy It wouldn't be a big deal to remove the winrm caching. It only works for a single host (i.e. forks=1) anyways at the moment.

I've updated my fork of pywinrm (https://github.com/cchurch/pywinrm) to comment out the print statement. Upstream pywinrm hasn't yet accepted my pull request for Python 2.6 compatibility either, so I'm not sure how actively he's maintaining that library.

Member

cchurch commented Aug 3, 2014

@bennojoy It wouldn't be a big deal to remove the winrm caching. It only works for a single host (i.e. forks=1) anyways at the moment.

I've updated my fork of pywinrm (https://github.com/cchurch/pywinrm) to comment out the print statement. Upstream pywinrm hasn't yet accepted my pull request for Python 2.6 compatibility either, so I'm not sure how actively he's maintaining that library.

@trondhindenes

This comment has been minimized.

Show comment
Hide comment
@trondhindenes

trondhindenes Aug 4, 2014

Contributor

I'm not sure I agree with the logic around deciding whether to use Basic or Kerberos.
A local (e.g. non-domain) user in Windows has the Netbios form "REALM\UserName" (where realm is the local computer), for example 'SERVER1\Administrator'.
A Domain user in windows can be specified using either netbios (DOMAIN\UserName) or UPN (username@subdomain.domain.tld)

A UPN-form domain user can use either kerberos or basic auth. If I was designing this I would attempt kerberos first (given that the username specified is UPN-style) (or possible check whether we have a kerb ticket), and then failing that fallback to basic and attempt that.

The USER@REALM form proposed above doesn't really belong anywhere in windows, as it's a mix between netbios and upn-style usernames. I doesn't feel right to me.

Contributor

trondhindenes commented Aug 4, 2014

I'm not sure I agree with the logic around deciding whether to use Basic or Kerberos.
A local (e.g. non-domain) user in Windows has the Netbios form "REALM\UserName" (where realm is the local computer), for example 'SERVER1\Administrator'.
A Domain user in windows can be specified using either netbios (DOMAIN\UserName) or UPN (username@subdomain.domain.tld)

A UPN-form domain user can use either kerberos or basic auth. If I was designing this I would attempt kerberos first (given that the username specified is UPN-style) (or possible check whether we have a kerb ticket), and then failing that fallback to basic and attempt that.

The USER@REALM form proposed above doesn't really belong anywhere in windows, as it's a mix between netbios and upn-style usernames. I doesn't feel right to me.

@ianclegg

This comment has been minimized.

Show comment
Hide comment
@ianclegg

ianclegg Aug 4, 2014

Contributor

@trondhindenes
Your reasoning is sound, but I'm not so sure about the facts and I hope to dissuade you :)

A UPN-form domain user can use either kerberos or basic auth.

This is not the case, I have tried. WinRM will not authenticate a domain user with basic auth. This the main reason for implementing support for kerberos. See the constant 'WSManFlagUseBasic' on
http://msdn.microsoft.com/en-us/library/aa384293(v=vs.85).aspx

The USER@REALM form proposed above doesn't really belong anywhere in windows

Having worked at Microsoft and being MSCE certified, this is news to me. The UPN form is the preferred format for logon's since the adoption of Kerberos in Windows 2000. See 'userPrincipalName' description (2nd paragraph) at http://msdn.microsoft.com/en-us/library/ms677605(v=vs.85).aspx. See MSCE Training 'MCSE Planning, Implementing, and Maintaining a Microsoft Windows Server 2003 Active Directory Infrastructure'. It is a fact that the SAM based Domain/User form is retained for mainly for compatibility.

Does this change anything?

Contributor

ianclegg commented Aug 4, 2014

@trondhindenes
Your reasoning is sound, but I'm not so sure about the facts and I hope to dissuade you :)

A UPN-form domain user can use either kerberos or basic auth.

This is not the case, I have tried. WinRM will not authenticate a domain user with basic auth. This the main reason for implementing support for kerberos. See the constant 'WSManFlagUseBasic' on
http://msdn.microsoft.com/en-us/library/aa384293(v=vs.85).aspx

The USER@REALM form proposed above doesn't really belong anywhere in windows

Having worked at Microsoft and being MSCE certified, this is news to me. The UPN form is the preferred format for logon's since the adoption of Kerberos in Windows 2000. See 'userPrincipalName' description (2nd paragraph) at http://msdn.microsoft.com/en-us/library/ms677605(v=vs.85).aspx. See MSCE Training 'MCSE Planning, Implementing, and Maintaining a Microsoft Windows Server 2003 Active Directory Infrastructure'. It is a fact that the SAM based Domain/User form is retained for mainly for compatibility.

Does this change anything?

@trondhindenes

This comment has been minimized.

Show comment
Hide comment
@trondhindenes

trondhindenes Aug 4, 2014

Contributor

Bad explanation on my part. Given AD domain "xyz.com" which has a netbios domain name of "xyz", I would consider the following username forms valid:
XYZ\administrator
administrator@xyz.com

and the following username form not valid (or at least very weird):
administrator@xyz

Contributor

trondhindenes commented Aug 4, 2014

Bad explanation on my part. Given AD domain "xyz.com" which has a netbios domain name of "xyz", I would consider the following username forms valid:
XYZ\administrator
administrator@xyz.com

and the following username form not valid (or at least very weird):
administrator@xyz

@ianclegg

This comment has been minimized.

Show comment
Hide comment
@ianclegg

ianclegg Aug 4, 2014

Contributor

@trondhindenes
I was proposing
user@realm

where realm would naturally be the kerberos realm (the FQDN) rather than a netbios name. So don't worry: administrator@xyz would not be valid anyway.

The salient point here is to implement support for netbios domains, as in your example:
netbios domain\user

There are a lot of Windows Administrators who are used to this form and I agree it would make sense. However, performing kerberos with netbios names is a Microsoft extension. I would not like to 'assume' the netbios name is the same as the realm since there are many situations (after a business merges) where this may not be the case.

Do you know if netbios naming is supported by the underlying python kerberos package (which basically wraps the MIT krb5 library) or how we would go about this?

Contributor

ianclegg commented Aug 4, 2014

@trondhindenes
I was proposing
user@realm

where realm would naturally be the kerberos realm (the FQDN) rather than a netbios name. So don't worry: administrator@xyz would not be valid anyway.

The salient point here is to implement support for netbios domains, as in your example:
netbios domain\user

There are a lot of Windows Administrators who are used to this form and I agree it would make sense. However, performing kerberos with netbios names is a Microsoft extension. I would not like to 'assume' the netbios name is the same as the realm since there are many situations (after a business merges) where this may not be the case.

Do you know if netbios naming is supported by the underlying python kerberos package (which basically wraps the MIT krb5 library) or how we would go about this?

@trondhindenes

This comment has been minimized.

Show comment
Hide comment
@trondhindenes

trondhindenes Aug 5, 2014

Contributor

I'm trying to test this on my system. I'm guessing I need the Kerberos python package, which fails to install on my (ubuntu) node. Has anyone seen this error?
Command /usr/bin/python -c "import setuptools, tokenize;file='/tmp/pip_build_root/kerberos/setup.py';exec(compile(getattr(tokenize, 'open', open)(file).read().replace('\r\n', '\n'), file, 'exec'))" install --record /tmp/pip-UmWh_C-record/install-record.txt --single-version-externally-managed --compile failed with error code 1 in /tmp/pip_build_root/kerberos
Storing debug log for failure in /home/azureuser/.pip/pip.log
azureuser@ansible-tower:~$

Contributor

trondhindenes commented Aug 5, 2014

I'm trying to test this on my system. I'm guessing I need the Kerberos python package, which fails to install on my (ubuntu) node. Has anyone seen this error?
Command /usr/bin/python -c "import setuptools, tokenize;file='/tmp/pip_build_root/kerberos/setup.py';exec(compile(getattr(tokenize, 'open', open)(file).read().replace('\r\n', '\n'), file, 'exec'))" install --record /tmp/pip-UmWh_C-record/install-record.txt --single-version-externally-managed --compile failed with error code 1 in /tmp/pip_build_root/kerberos
Storing debug log for failure in /home/azureuser/.pip/pip.log
azureuser@ansible-tower:~$

@bennojoy

This comment has been minimized.

Show comment
Hide comment
@bennojoy

bennojoy Aug 5, 2014

Contributor

@trondhindenes did you try installing it via apt instead of pip ?

apt-get update
apt-get install python-kerberos

Contributor

bennojoy commented Aug 5, 2014

@trondhindenes did you try installing it via apt instead of pip ?

apt-get update
apt-get install python-kerberos

@ianclegg

This comment has been minimized.

Show comment
Hide comment
@ianclegg

ianclegg Aug 5, 2014

Contributor

Hmm...just looking into this - so pywinrm uses: https://pypi.python.org/pypi/kerberos
Except its not really a kerberos library, but a GSS-API implementation (SPNEGO) - looks like its built on an some 2010 source's from Apple. The sources indicate it is not possible to set a specific UPN.

PyKerberos (https://pypi.python.org/pypi/pykerberos)
Looks a little more promising, the sources look more up to date (2013 Apple sources) and it has support for setting a specific the principal.

maj_stat = gss_import_name(&min_stat, &principal_token, GSS_C_NT_USER_NAME, &name);

There is a mention of an NT username, I guess we need to check that out

Contributor

ianclegg commented Aug 5, 2014

Hmm...just looking into this - so pywinrm uses: https://pypi.python.org/pypi/kerberos
Except its not really a kerberos library, but a GSS-API implementation (SPNEGO) - looks like its built on an some 2010 source's from Apple. The sources indicate it is not possible to set a specific UPN.

PyKerberos (https://pypi.python.org/pypi/pykerberos)
Looks a little more promising, the sources look more up to date (2013 Apple sources) and it has support for setting a specific the principal.

maj_stat = gss_import_name(&min_stat, &principal_token, GSS_C_NT_USER_NAME, &name);

There is a mention of an NT username, I guess we need to check that out

@trondhindenes

This comment has been minimized.

Show comment
Hide comment
@trondhindenes

trondhindenes Aug 5, 2014

Contributor

Yup, got it working. So, one problem I'm seing straight away in the as-is code is that ansible tries to use https even if the port specified is 5985 (http).

Contributor

trondhindenes commented Aug 5, 2014

Yup, got it working. So, one problem I'm seing straight away in the as-is code is that ansible tries to use https even if the port specified is 5985 (http).

@trondhindenes

This comment has been minimized.

Show comment
Hide comment
@trondhindenes

trondhindenes Aug 5, 2014

Contributor

@ianclegg
I completely agree that for Kerberos support, UPN-style usernames (user@domain.com) would be the only supported form. Windows folks won't have a problem with that.

Contributor

trondhindenes commented Aug 5, 2014

@ianclegg
I completely agree that for Kerberos support, UPN-style usernames (user@domain.com) would be the only supported form. Windows folks won't have a problem with that.

@bennojoy

This comment has been minimized.

Show comment
Hide comment
@bennojoy

bennojoy Aug 5, 2014

Contributor

@trondhindenes According to code logic if port is 4985 it will first try http and kerberos and if it fails it would try https.
can you please run it with -vvvv and check if a connection with http is tried ?

Contributor

bennojoy commented Aug 5, 2014

@trondhindenes According to code logic if port is 4985 it will first try http and kerberos and if it fails it would try https.
can you please run it with -vvvv and check if a connection with http is tried ?

@jhawkesworth

This comment has been minimized.

Show comment
Hide comment
@jhawkesworth

jhawkesworth Aug 13, 2014

Contributor

Just been testing this out against a win 2008 r2 sp1 box and hit System.OutOfMemory error when running win_ping. Turns out this is a winrm issue - there's a hotfix for it here: http://support.microsoft.com/kb/2842230

I am still getting to know ansible but I wondered if instead of the 'magic' ansible_kerberos username and password it would be possible to add a new ansible_connection type, something like 'winrm-domain' which would leave the ansible_ssh_user and ansible_ssh_pass settings free to specify relevant credentials. I imagine in big setups you might need to use different domains and users for different environments, so I think it would be necessary to have a way of selecting user/domain/realm to be used for a given host group.

I pulled ansible from source this morning and manually applied this patch and found if port=4985 then http is tried and if port=4986 then https was tried.

Contributor

jhawkesworth commented Aug 13, 2014

Just been testing this out against a win 2008 r2 sp1 box and hit System.OutOfMemory error when running win_ping. Turns out this is a winrm issue - there's a hotfix for it here: http://support.microsoft.com/kb/2842230

I am still getting to know ansible but I wondered if instead of the 'magic' ansible_kerberos username and password it would be possible to add a new ansible_connection type, something like 'winrm-domain' which would leave the ansible_ssh_user and ansible_ssh_pass settings free to specify relevant credentials. I imagine in big setups you might need to use different domains and users for different environments, so I think it would be necessary to have a way of selecting user/domain/realm to be used for a given host group.

I pulled ansible from source this morning and manually applied this patch and found if port=4985 then http is tried and if port=4986 then https was tried.

@trondhindenes

This comment has been minimized.

Show comment
Hide comment
@trondhindenes

trondhindenes Aug 20, 2014

Contributor

Maybe some retry logic should be done here as well, similar to the ssh connection types. On Windows, PowerShell defaults to Kerberos, but lets you override that by specifying the "-Authentication" parameter. The downside would be (I'm guessing here) an even longer time to set up the WinRM connection (which is already more than slow enough compared to the blazing speed of ssh - that's WIndows' fault and not Ansible's tho).

Contributor

trondhindenes commented Aug 20, 2014

Maybe some retry logic should be done here as well, similar to the ssh connection types. On Windows, PowerShell defaults to Kerberos, but lets you override that by specifying the "-Authentication" parameter. The downside would be (I'm guessing here) an even longer time to set up the WinRM connection (which is already more than slow enough compared to the blazing speed of ssh - that's WIndows' fault and not Ansible's tho).

@nicodeslandes

This comment has been minimized.

Show comment
Hide comment
@nicodeslandes

nicodeslandes Sep 16, 2014

Just to let everyone know, I started a topic on this subject on ansible-devel: https://groups.google.com/forum/#!topic/ansible-devel/TYMdAoN9IK8

nicodeslandes commented Sep 16, 2014

Just to let everyone know, I started a topic on this subject on ansible-devel: https://groups.google.com/forum/#!topic/ansible-devel/TYMdAoN9IK8

@themalkolm

This comment has been minimized.

Show comment
Hide comment
@themalkolm

themalkolm Feb 16, 2015

So.. is it possible to use kerberos/domain authentication in ansible?

themalkolm commented Feb 16, 2015

So.. is it possible to use kerberos/domain authentication in ansible?

@jhawkesworth

This comment has been minimized.

Show comment
Hide comment
@jhawkesworth

jhawkesworth Feb 16, 2015

Contributor

I have not tested this yet, but it appears this has recently been added to
latest dev version of ansible now via this pull request:

#10202

Jon

On Mon, Feb 16, 2015 at 10:30 AM, Alexander Krasnukhin <
notifications@github.com> wrote:

So.. is it possible to use kerberos authentication in ansible?


Reply to this email directly or view it on GitHub
#8345 (comment).

Contributor

jhawkesworth commented Feb 16, 2015

I have not tested this yet, but it appears this has recently been added to
latest dev version of ansible now via this pull request:

#10202

Jon

On Mon, Feb 16, 2015 at 10:30 AM, Alexander Krasnukhin <
notifications@github.com> wrote:

So.. is it possible to use kerberos authentication in ansible?


Reply to this email directly or view it on GitHub
#8345 (comment).

@bcoca

This comment has been minimized.

Show comment
Hide comment
@bcoca

bcoca Feb 20, 2015

Member

closing this in favor of the merged #10202, we can add features on top of that

Member

bcoca commented Feb 20, 2015

closing this in favor of the merged #10202, we can add features on top of that

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment