Skip to content
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

Access denied after renaming windows host : Server not found in Kerberos database #607

Closed
Gisele-Nos opened this issue Apr 24, 2024 · 10 comments

Comments

@Gisele-Nos
Copy link

Gisele-Nos commented Apr 24, 2024

SUMMARY

Hello,
I'm new to ansible so i'm trying to learn as much as i can, if you have some documents don't hesitate to share!

I'm having trouble with the accessin the host. I renamed the window host using ansible. The window host belong to the domain "DOMAIN.LOCAL", so i'm using KERBEROS.
I succeded renaming the host and then i lost access to it. i can't ping the host anymore

  • task : rename the computer

I'm using an account that belong to the domain "[email protected]"

ISSUE TYPE
  • Bug Report
COMPONENT NAME

win_shell
win_reboot

ANSIBLE VERSION

``
$ ansible --version
ansible [core 2.16.5]
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/ansible/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3/dist-packages/ansible
ansible collection location = /home/ansible/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible
python version = 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] (/usr/bin/python3)
jinja version = 3.0.3
libyaml = True


##### COLLECTION VERSION
<!--- Paste verbatim output from "ansible-galaxy collection list <namespace>.<collection>"  between the quotes
for example: ansible-galaxy collection list community.general
-->
```paste below

CONFIGURATION
CONFIG_FILE() = /etc/ansible/ansible.cfg
OS / ENVIRONMENT
  • Host : Windows 10 professionnel 22H2
  • DC : Windows Server 2019
  • Ansible : Ubuntu 22.04.4
STEPS TO REPRODUCE
---
-  name: Change the name of computer
   hosts: windows
   tasks:
     -  name: Rename Computer
        win_shell: Rename-Computer -NewName "TEST03"
     -  name: reboot
        win_reboot:

EXPECTED RESULTS

Expected The host to be renamed and rebooted

ACTUAL RESULTS
ansible-playbook [core 2.16.5]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/ansible/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  ansible collection location = /home/ansible/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible-playbook
  python version = 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] (/usr/bin/python3)
  jinja version = 3.0.3
  libyaml = True
Using /etc/ansible/ansible.cfg as config file
setting up inventory plugins
Loading collection ansible.builtin from
host_list declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
script declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
auto declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Parsed /etc/ansible/hosts inventory source with ini plugin
redirecting (type: modules) ansible.builtin.win_shell to ansible.windows.win_shell
Loading collection ansible.windows from /usr/lib/python3/dist-packages/ansible_collections/ansible/windows
redirecting (type: action) ansible.builtin.win_reboot to ansible.windows.win_reboot
Loading callback plugin default of type stdout, v2.0 from /usr/lib/python3/dist-packages/ansible/plugins/callback/default.py
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.

PLAYBOOK: rename_win.yml ********************************************************************************************************************************************************************************************************************
Positional arguments: rename_win.yml
verbosity: 4
connection: ssh
become_method: sudo
tags: ('all',)
inventory: ('/etc/ansible/hosts',)
forks: 5
1 plays in rename_win.yml

PLAY [Change the name of computer] **********************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************
task path: /etc/ansible/playbooks/rename_win.yml:2
redirecting (type: modules) ansible.builtin.setup to ansible.windows.setup
Using module file /usr/lib/python3/dist-packages/ansible_collections/ansible/windows/plugins/modules/setup.ps1
Pipelining is enabled.
<xx.xx.xx.xx> ESTABLISH WINRM CONNECTION FOR USER: [email protected] on PORT 5985 TO xx.xx.xx.xx
calling kinit with pexpect for principal [email protected]
fatal: [xx.xx.xx.xx]: UNREACHABLE! => {
    "changed": false,
    "msg": "kerberos: authGSSClientStep() failed: (('Unspecified GSS failure.  Minor code may provide more information', 851968), ('Server not found in Kerberos database', -1765328377))",
    "unreachable": true
}

PLAY RECAP **********************************************************************************************************************************************************************************************************************************
xx.xx.xx.xx              : ok=0    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0
@jborean93
Copy link
Collaborator

One key component of Kerberos authentication is to be able to identify the target host you are using for authentication. This is done through a Service Principal Name (SPN). When Ansible goes to build the Kerberos ticket it builds the SPN for the host requested which is http/{{ ansible_host }} and if the domain controller cannot find that SPN registered to any host you will get the error message

Server not found in Kerberos database

You can manually set the hostname portion of the SPN when using the winrm connection plugin through the ansible_winrm_kerberos_hostname_override variable allowing you to set it to whatever you want. In your example output Ansible is failing to connect altogether to the Windows host as it's failing on the fact gathering task. A few things you could do to get this working is

  • Ensure you are connecting with the host fully qualified host name so the SPN works
  • Set the FQDN with ansible_winrm_kerberos_hostname if connecting through an IP
  • Don't use Kerberos auth

Unfortunately another wrinkle in your task is taht when you rename the host the SPN is most likely going to be invalid on the subsequent tasks as they will also be renamed with the host. To avoid this you would have to add a custom SPN to the computer account and set Ansible to use that SPN to ensure it works before and after the rename.

@Gisele-Nos
Copy link
Author

Hello @jborean93

Thank you for your response.

I'm using Kerberos because i read it was a secure way of auth without using certificate (am on HTTP port). So when you say "Don't use Kerberos auth" what do you mean by that ?

Regarding the SPN, as my goal is to rename all my hosts, is there a way i can use one SPN for all my hosts or i have to set a costom SPN for each computer ? Is the settings with the ansible hostname in KDC or it's on ansible using KDC hostname. I read a lot of doc but it still confusing on the set SPN.

i'm connecting using IP because later on i'll have to change the name of the hosts, so i figured it woulld be best until i find a way to use FQDN.

Also i'm having this issue, i don't know if it's releated to the SPN

Here is the playbook that i'm running. The first task are being executed but when it comes to the win_package module, it fails.
image

and i get this error : "msg": "Unexpected failure during module execution: the specified credentials were rejected by the server.

The accound i'm using belongs to the domain and it has an admin privilege. I can't figure out why i get to do the 2 first tasks but not the third one.

in case needed :

image

@Gisele-Nos
Copy link
Author

Also is it normal that i lost winrm connection after rebooting my ansible server ? It is tring to reach the host by SSH now.

@jborean93
Copy link
Collaborator

I'm using Kerberos because i read it was a secure way of auth without using certificate (am on HTTP port). So when you say "Don't use Kerberos auth" what do you mean by that ?

It is definitely the most secure way you can use WinRM over HTTP, the other auth methods have problems that are only really resolved by using HTTPS to secure the connection instead. The only thing I meant by that suggestion is more that one way to avoid the SPN problem is to not use Kerberos itself. It's not a great suggestion but it's still a suggestion.

Regarding the SPN, as my goal is to rename all my hosts, is there a way i can use one SPN for all my hosts or i have to set a costom SPN for each computer ?

Unfortunately SPNs must be unique and it can only be registered to one principal in the domain so you would need an SPN per host.

Is the settings with the ansible hostname in KDC or it's on ansible using KDC hostname. I read a lot of doc but it still confusing on the set SPN.

You tell Ansible how to connect, in your case you are connecting using an IP address. You can use ansible_winrm_kerberos_hostname_override to change what the hostname portion of an SPN is instead of just reusing the connection hostname (your IP). The SPNs are registered on the computer account in the KDC/Domain Controller.

Also is it normal that i lost winrm connection after rebooting my ansible server ? It is tring to reach the host by SSH now.

A reboot won't change how Ansible tries to connect to a host, only a change in vars will do that. You'll have to share a full reproducer with the output to understand what might be going on there.

Unfortunately what you are trying to do by renaming hosts is not a simple thing to achieve in Ansible as it's not an idempotent operation and due to the Kerberos SPN lookup it is going to be difficult to do without either using a HTTPS listener or falling back to a more insecure authentication protocol like NTLM.

@Gisele-Nos
Copy link
Author

Gisele-Nos commented Apr 29, 2024

Hello @jborean93

Thank you for getting back to me again.

It is definitely the most secure way you can use WinRM over HTTP, the other auth methods have problems that are only really resolved by using HTTPS to secure the connection instead. The only thing I meant by that suggestion is more that one way to avoid the SPN problem is to not use Kerberos itself. It's not a great suggestion but it's still a suggestion.

Could using Kerberos over HTTPS with a self-signed certificate be a solution to avoide the SPN problem ? If not what can be the best methode to use with a domain account to manage a lot of hosts ?
I chose kerberos because it uses one account for all the hosts and i don't have to do any local config beside running the config script on the nodes.

Unfortunately SPNs must be unique and it can only be registered to one principal in the domain so you would need an SPN per host.

What if i create the SPN for the ansible account in the domain, will it solve the issue ?

You tell Ansible how to connect, in your case you are connecting using an IP address. You can use ansible_winrm_kerberos_hostname_override to change what the hostname portion of an SPN is instead of just reusing the connection hostname (your IP). The SPNs are registered on the computer account in the KDC/Domain Controller.

I used IP because the hostname will change after the rename

A reboot won't change how Ansible tries to connect to a host, only a change in vars will do that. You'll have to share a full reproducer with the output to understand what might be going on there.

i find the error : it was the name of vars.yml and that caused the error.
However i still have an issue while trying to install 7-zip uzing "win_package"

Here's the playbook i'm try to run
image

The first two task are executed while and after waiting for more than 4 hours dor the 3rd task i get this error :
"msg": "Unexpected failure during module execution: the specified credentials were rejected by the server.

And for the vars

image

And for the Asible.cfg

image

Unfortunately what you are trying to do by renaming hosts is not a simple thing to achieve in Ansible as it's not an idempotent operation and due to the Kerberos SPN lookup it is going to be difficult to do without either using a HTTPS listener or falling back to a more insecure authentication protocol like NTLM.

So if i'm using HTTPS it'll be more doable ? and what if i use a PowerShell script that i run using Ansible, would it be easer ?

@jborean93
Copy link
Collaborator

Could using Kerberos over HTTPS with a self-signed certificate be a solution to avoide the SPN problem ? If not what can be the best methode to use with a domain account to manage a lot of hosts ?

No, Kerberos even over HTTPS still does the SPN check. If you want to use a domain account it's either Kerberos or NTLM. I wouldn't say NTLM is the best method but using NTLM with HTTPS does paper over a few of the problems with NTLM in general and NTLM doesn't use SPNs for validation. Keep in mind NTLM is an older authentication method that some orgs are starting to disable for security reasons.

What if i create the SPN for the ansible account in the domain, will it solve the issue ?

The SPN is not for the connection user but is registered on the server/computer account in AD. Each SPN needs to be unique and only registered to only one principal. The tricky thing with your goal here is a rename operation isn't easy to pull off when the name of the host itself is used as part of validating the server.

In the end I don't think renaming a server this way makes sense from an already provisioned host. Why not ensure the host is renamed properly before it is joined to the domain so that you don't need to mess around with IP addresses in Ansible or any of this SPN complexity.

"msg": "Unexpected failure during module execution: the specified credentials were rejected by the server.

That unfortunately doesn't make sense, there is nothing in your tasks that would change the connection vars Ansible is using. I recommend you look into our Ansible forum or IRC for more help there and share more information like the output with -vvv.

@Gisele-Nos
Copy link
Author

Could using Kerberos over HTTPS with a self-signed certificate be a solution to avoide the SPN problem ? If not what can be the best methode to use with a domain account to manage a lot of hosts ?

No, Kerberos even over HTTPS still does the SPN check. If you want to use a domain account it's either Kerberos or NTLM. I wouldn't say NTLM is the best method but using NTLM with HTTPS does paper over a few of the problems with NTLM in general and NTLM doesn't use SPNs for validation. Keep in mind NTLM is an older authentication method that some orgs are starting to disable for security reasons.

So i'll have to stick to the use of Kerberos then, because i'll be using a domain account for Ansible. I tried Kerberos on HTTPs with a self-signed certificate but i'm getting this error

image

What if i create the SPN for the ansible account in the domain, will it solve the issue ?

The SPN is not for the connection user but is registered on the server/computer account in AD. Each SPN needs to be unique and only registered to only one principal. The tricky thing with your goal here is a rename operation isn't easy to pull off when the name of the host itself is used as part of validating the server.

In the end I don't think renaming a server this way makes sense from an already provisioned host. Why not ensure the host is renamed properly before it is joined to the domain so that you don't need to mess around with IP addresses in Ansible or any of this SPN complexity.

The server are already provisioned, but since we're redoing our envetory, we have to change some servers' hostname, that's why i'm doing this.

"msg": "Unexpected failure during module execution: the specified credentials were rejected by the server.

That unfortunately doesn't make sense, there is nothing in your tasks that would change the connection vars Ansible is using. I recommend you look into our Ansible forum or IRC for more help there and share more information like the output with -vvv.

i wrote a request in Ansible forum and it was closed right the way.

@jborean93
Copy link
Collaborator

So i'll have to stick to the use of Kerberos then, because i'll be using a domain account for Ansible. I tried Kerberos on HTTPs with a self-signed certificate but i'm getting this error

When using HTTPS and Kerberos you now have to deal with certificate verification as well as SPN. You can still use HTTPS with NTLM if you are happy to fallback to the older auth method but you still need to content with certificate verification and whether to ignore the certs or not.

i wrote a request in Ansible forum and it was closed right the way.

They should be sending people to GitHub for bugs, having credentials reject is unfortunately not a bug and is more of a question/configuration setup problem. If you have a link to your post I'm happy to comment more info there.

@Gisele-Nos
Copy link
Author

So i'll have to stick to the use of Kerberos then, because i'll be using a domain account for Ansible. I tried Kerberos on HTTPs with a self-signed certificate but i'm getting this error

When using HTTPS and Kerberos you now have to deal with certificate verification as well as SPN. You can still use HTTPS with NTLM if you are happy to fallback to the older auth method but you still need to content with certificate verification and whether to ignore the certs or not.

I'm trying to use HTTPs with Kerberos but i struggle to find articles about it. Most of articles are dealing with basic authentication over HTTPs. They are using a local account and not a domain account !

So i tried winrm with Basic authentication over HTTPs, I used a self signe certificate but i can't get the host to trust it, i have to "ignore" the validation. Do you have suggestion on how i can get the host to trust the certificate ?

They should be sending people to GitHub for bugs, having credentials reject is unfortunately not a bug and is more of a question/configuration setup problem. If you have a link to your post I'm happy to comment more info there.

@jborean93
Copy link
Collaborator

I'm trying to use HTTPs with Kerberos but i struggle to find articles about it. Most of articles are dealing with basic authentication over HTTPs. They are using a local account and not a domain account

It's the same as Kerberos over HTTP just with HTTPS certificate validation.

So i tried winrm with Basic authentication over HTTPs, I used a self signe certificate but i can't get the host to trust it, i have to "ignore" the validation. Do you have suggestion on how i can get the host to trust the certificate ?

Same as any HTTPS endpoint, you need to explicitly trust the cert using whatever OS mechanism is there. For Linux it would be putting the CA the server cert was issued with in the trust path location for your Linux distro (the path differs from distro to distro).

Using HTTPS has the same problem as Kerberos when it comes to renaming the host. The certificate must be issued by a trusted CA but the hostname you are connecting with must also match the CN/SAN in the certificate itself. What you want to do is not going to be easily done without either ignoring the validation or setting up the SPNs so that it has both the old and new hostname.

As this is getting into more questions about how Ansible works I'm going to close this issue as we try to direct those questions to the mailing list/IRC/forum. The issue tracker on GitHub is more for actual bugs/problems that need to be fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants