I have Ubuntu 20.04 in WSL and Ansible installed. I'm trying to simply run a Windows update on my local machine. I've tried using my account, a service account, etc. I've run the kinit -C myuser#DOMAIN.LOCAL command and have a valid ticket. My computer is joined to an AD/Azure hybrid with the local domain being "domain.local", yet we login with myuser#domain.com to the computer.
I have the internal domain controllers listed in my /etc/resolv.conf so I can ping/access domain computers.
I've tried with ansible_user=myuser#DOMAIN.LOCAL, DOMAIN.COM, myuser, myuser#DOMAIN.COM
I keep getting errors when running "ansible-playbook -i hosts -vvvv win-update.yml":
TASK [Gathering Facts] ******************************************************************************************************************************************************************************************
task path: /home/gmeyer/ansible/win-update.yml:5
Using module file /usr/lib/python3/dist-packages/ansible/modules/windows/setup.ps1
Pipelining is enabled.
<10.20.30.174> ESTABLISH WINRM CONNECTION FOR USER: myuser on PORT 5986 TO 10.20.30.174
fatal: [10.20.30.174]: 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 ******************************************************************************************************************************************************************************************************`
10.20.30.174 : ok=0 changed=0 unreachable=1 failed=0 skipped=0 rescued=0 ignored=0
My /etc/krb5.conf:
[libdefaults]
default_realm = DOMAIN.LOCAL
[realms]
X-ISS.LOCAL = {
kdc = dc.domain.local
admin_server = dc.domain.local
default_domain = domain.local
}
[domain_realm]
.domain.local = DOMAIN.LOCAL
domain.local = DOMAIN.LOCAL
My hosts:
[win]
10.20.30.174
[win:vars]
ansible_user=myuser#DOMAIN.LOCAL
ansible_connection = winrm
ansible_winrm_server_cert_validation = ignore
ansible_password = [redacted]
ansible_winrm_transport = kerberos
ansible_winrm_kerberos_delegation = true
My playbook:
---
# DESCRIPTION
# Apply windows updates
- name: Apply windows updates
hosts: win
gather_facts: yes
vars:
initial_reboot: |-
{{ 86400 <
(( ((ansible_date_time.date+" "+ansible_date_time.time)|to_datetime('%Y-%m-%d %H:%M:%S')) -
ansible_facts.lastboot|to_datetime('%Y-%m-%d %H:%M:%SZ')).total_seconds())|abs }}
tasks:
# Reboot systems with if up longer then day
# this way we know that the system was able to come back
# up before updates were applied
- name: Reboot if system has a large uptime
win_reboot:
when: initial_reboot and not ansible_check_mode
tags:
- never
- reboot
- block:
- name: >
{{ 'Install' if 'install' in ansible_run_tags else 'Search' }} updates
{{ 'will automatically reboot' if 'reboot' in ansible_run_tags else 'no reboot' }}
win_updates:
category_names:
- SecurityUpdates
- CriticalUpdates
- UpdateRollups
- DefinitionUpdates
- Updates
reboot: "{{ 'yes' if 'reboot' in ansible_run_tags else 'no' }}"
state: "{{ 'installed' if 'install' in ansible_run_tags else 'searched' }}"
become: yes
become_method: runas
become_user: SYSTEM
register: update_results
tags:
- never
- install
- check
rescue:
- name: Windows update failed?
debug:
msg: "error: {{ update_results.msg }}"
when: update_results is failed and update_results.msg is defined
tags:
- always
- name: Server had pending reboots?
win_reboot:
when: not ansible_check_mode and
update_results is failed and
update_results.msg is search('A reboot is required')
tags:
- never
- reboot
always:
- name: Report results
debug:
var: update_results
tags:
- never
- install
- check
I have tried many different options for formatting the domain name while running Ansible in Ubuntu. I am expecting to get the script to connect to the Windows machine to run the Windows Updates, but keep getting Kerberos errors.
I figured out what the problem was. It was in my hosts file - I changed the lines to the fqdn and put the "ansible_host=IP ansible_connection=local" and it worked!
Related
New ansible user
Here is my playbook.
---
- name: Creating Local User Account on RHEL Systems.
hosts: hapansible05
become: true
vars:
passwd: WSXcde1234
tasks:
- name: Creating Local User
user:
name: svc_cldscp
password: "{{ passwd | password_hash('sha512') }}"
comment: svc_cldscp-ServiceAcct
shell: /bin/bash
Keep getting this message on RHEL server
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
PLAY [Creating Local User Account on RHEL Systems.] ********************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************
ok: [hapansible05]
TASK [Creating Local User] ***********************************************************************************************************************************
****fatal: [hapansible05]: FAILED! => {"changed": false, "msg": "usermod: user 'svc_cldscp' does not exist in /etc/passwd\n", "name": "svc_cldscp", "rc": 6}******
PLAY RECAP *************************************************************************************************************************************************
hapansible05 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
A working practice example for creating and configuring local users via user module with a filter for Hashing and encrypting strings and passwords is
---
- name: Create local user account on RHEL System
hosts: rhel.example.com
become: true
vars:
pwd: "WSXcde1234"
tasks:
- name: Create and configure user in local system
user:
name: "svc_cldscp"
password: "{{ pwd | password_hash('sha512') }}"
system: false # Defaults to no
createhome: true # Defaults to yes
uid: '1234' #
group: '1234' # Need to exist before
shell: /bin/bash # Defaults to /bin/bash
comment: "Service Account"
state: present
I am trying to create new users and groups using Ansible playbook. Below is my folder structure.
tree
.
├── create-users.yaml
└── ubuntu
create-users.yaml playbook contains create user and group tasks. Note, I am not having any group (admin_group) and users (Rajini, Kamal) in my target machine, instead they will be created when running the playbook.
---
- name: Create Users & Groups
hosts: target1
gather_facts: false
tasks:
- name: Create Users Task
user:
name: "{{ item }}"
state: present
password: "{{ 'default_user_password' | password_hash('sha512','A512') }}"
shell: /bin/bash
groups: "{{ admin_group }}"
loop:
- Rajini
- Kamal
I have another file called ubuntu to pick group name and password. When running the playbook I am getting below error.
ansible-playbook --vault-id #prompt create-users.yaml -K
BECOME password:
Vault password (default):
PLAY [Create Users & Groups] *****************************************************************************************************************************************************************
TASK [Create Users Task] *********************************************************************************************************************************************************************
fatal: [target1]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'admin_group' is undefined\n\nThe error appears to be in '/home/osboxes/Ansible_Project/web_deployment/Ansible/groups_vars/create-users.yaml': line 6, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n tasks:\n - name: Create Users Task\n ^ here\n"}
PLAY RECAP ***********************************************************************************************************************************************************************************
target1 : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
admin_group: admin
default_user_password: Password1
Can somebody please help me on this?
Updating Output after getting help from user Moon.
ansible-playbook --vault-id #prompt create-users.yaml -K
BECOME password:
Vault password (default):
PLAY [Create Users & Groups] *****************************************************************************************************************************************************************
TASK [Create Users Task] *********************************************************************************************************************************************************************
changed: [target1] => (item=Rajini)
changed: [target1] => (item=Kamal)
PLAY RECAP ***********************************************************************************************************************************************************************************
target1 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
ssh Kamal#192.168.0.1
Kamal#192.168.0.1's password:
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 5.0.0-23-generic x86_64)
Kamal#Ansible_Target1:~$ id
uid=1005(Kamal) gid=1001(admin) groups=1001(admin)
Couple of things:
To use variables from ubuntu file you need specify the vars file in playbook.
To use default_user_password as a variable, remove the quotes '
If you want admin as the users primary group then use group attribute instead. groups on the other hand takes a list and add the users to the listed groups.
And, if the group isn't created yet on the target machine then first create the group using group module.
Playbook after the above changes.
---
- name: Create Users & Groups
hosts: target1
gather_facts: false
vars_files: ubuntu
tasks:
- name: Create group
group:
name: "{{ admin_group }}"
state: present
- name: Create Users Task
user:
name: "{{ item }}"
state: present
password: "{{ default_user_password | password_hash('sha512','A512') }}"
shell: /bin/bash
group: "{{ admin_group }}"
loop:
- Rajini
- Kamal
This will help you make your playbook more dynamic:
create a secret.yml file for storing user password using below command:
ansible-vault create secret.yml
#sample:
user_password: mypass#155
create userlist.yml to specify the list of user and their department:
vim userlist.yml
#sample:
##user matching job role mentioned in create-user.yml playbook will be created
- users:
- name: "user1"
job: "developer"
- name: "user2"
job: "devops"
- name: "user3"
job: "developer"
Now create your playbook as follows:
vim user-create.yml
- hosts: appserver1
vars_files:
- secret.yml
- userlist.yml
tasks:
- name: "create group"
group:
name: "{{ item }}"
loop:
- "dev"
- "devops"
- name: "create user when Job=developer from userlist.yml file with password from secret.yml file and add to secondary group 'dev' "
user:
name: "{{ item['name'] }}"
password: "{{ user_password | password_hash('sha512') }}"
update_password: on_create
groups: "dev"
append: yes
loop: "{{ users }}"
when: "item['job'] == 'developer'"
- name: "create user when Job=devops from userlist.yml file with password from secret.yml file and add to secondary group 'devops' "
user:
name: "{{ item['name'] }}"
password: "{{ user_password | password_hash('sha512') }}"
update_password: on_create
groups: "devops"
append: yes
loop: "{{ users }}"
when: "item['job'] == 'devops'"
Run the playbook
ansible-playbook -i inventory user-create.yml --ask-vault-pass
Things to remember
If you do not specify the update_password: on_create option, Ansible re-sets the user password every time the playbook is run: if the user has changed the password since the last time the playbook was run, Ansible re-sets password.
I get list of IP address in test.text file from which I am trying to get the IP in loop
and then try to get in group or variable and use it as hosts (dynamic_groups)
Below is my playlist
---
- name: provision stack
hosts: localhost
connection: local
gather_facts: no
serial: 1
tasks:
- name: Get Instance IP Addresses From File
shell: cat /home/user/test.text
register: serverlist
- debug: msg={{ serverlist.stdout_lines }}
- name: Add Instance IP Addresses to temporary inventory groups
add_host:
groups: dynamic_groups
hostname: "{{item}}"
with_items: serverlist.stdout_lines
- hosts: dynamic_groups
become: yes
become_user: root
become_method: sudo
gather_facts: True
serial: 1
vars:
ansible_connection: "{{ connection_type }}"
ansible_ssh_user: "{{ ssh_user_name }}"
ansible_ssh_private_key_file: "{{ ssh_private_key_file }}"
tasks:
.....
.....
After running above playbbok I am getting below error
TASK [debug] *****************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
"192.168.1.10",
"192.168.1.11",
"192.168.1.50"
]
}
TASK [Add Instance IP Addresses to temporary inventory groups] ***************************************************************************************************************************************************************************
changed: [localhost] => (item=serverlist.stdout_lines)
PLAY [dynamic_groups] *********************************************************************************************************************************************************************************************************************
TASK [Some Command] **********************************************************************************************************************************************************************************************************************
fatal: [serverlist.stdout_lines]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: Could not resolve hostname serverlist.stdout_lines: Name or service not known", "unreachable": true}
What Am I missing here?
Below is correct way to use variable
- name: Add Instance IP Addresses to temporary inventory groups
add_host:
groups: working_hosts
hostname: "{{item}}"
with_items: "{{ serverlist.stdout_lines }}"
It should solve your problem.
As reported in fatal error message "Failed to connect to the host via ssh: ssh: Could not resolve hostname serverlist.stdout_lines", it is trying to connect to "serverlist.stdout_lines", not to a valid IP.
This is caused by an error when passing variable to with_items. In your task:
with_items: serverlist.stdout_lines
it is passing serverlist.stdout_lines string and not its value.
With_items requires variable definition using "{{ ... }}" (https://docs.ansible.com/ansible/2.7/user_guide/playbooks_loops.html#with-items).
This is the correct way for your task:
- name: Add Instance IP Addresses to temporary inventory groups
add_host:
groups: dynamic_groups
hostname: "{{item}}"
with_items: "{{ serverlist.stdout_lines }}"
You can simply use ansible-playbook -i inventory_file_name playbook.yaml for this. inventory_file is the file containing your groups and ips.
I am trying to use ansible to telnet into cisco switches and apply a copy startup-config disk0 command.
Ansible seems to never be able to pass
(?i)"Destination filename": "work please" through the expect command
---
- hosts: all
gather_facts: false
connection: local
tasks:
- name: telnet,login and execute command
ignore_errors: true
expect:
command: telnet "{{ inventory_hostname }}"
responses:
(?i)password: "{{ password}}"
(?i)#: copy startup-config disk0
(?i)"Destination filename": "{{ lookup('pipe','date') }"
echo: yes
register: telnet_output
What i am getting as an output
ansible-playbook 2.7.6
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible-playbook
python version = 2.7.5 (default, Oct 30 2018, 23:45:53) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)]
Using /etc/ansible/ansible.cfg as config file
/var/lib/awx/projects/6500/hosts did not meet host_list requirements, check plugin documentation if this is unexpected
/var/lib/awx/projects/6500/hosts did not meet script requirements, check plugin documentation if this is unexpected
PLAYBOOK: copy-startup.yml *************************************************************************************************************************************************************************************************************
1 plays in copy-startup.yml
PLAY [all] *****************************************************************************************************************************************************************************************************************************
META: ran handlers
TASK [telnet,login and execute command] ************************************************************************************************************************************************************************************************
task path: /var/lib/awx/projects/6500/copy-startup.yml:6
fatal: [66.90.19.18]: FAILED! => {"changed": true, "cmd": "telnet \"66.90.19.18\"", "delta": "0:00:30.370396", "end": "2019-02-12 10:09:41.473716", "msg": "command exceeded timeout", "rc": null, "start": "2019-02-12 10:09:11.103320", "stdout": "Trying 66.90.19.18...\r\r\nConnected to 66.90.19.18.\r\r\nEscape character is '^]'.\r\r\n\r\n\r\nUser Access Verification\r\n\r\nPassword: \r\nLAB-6500-SUP2T#copy startup-config disk0\r\nDestination filename [disk0]? ", "stdout_lines": ["Trying 66.90.19.18...", "", "Connected to 66.90.19.18.", "", "Escape character is '^]'.", "", "", "", "User Access Verification", "", "Password: ", "LAB-6500-SUP2T#copy startup-config disk0", "Destination filename [disk0]? "]}
...ignoring
PLAY RECAP *****************************************************************************************************************************************************************************************************************************
66.90.19.18 : ok=2 changed=1 unreachable=0 failed=0
It seems to never want to write the Destination Filename[disk0]?
Any ideas
(?i)"Destination filename" matches for string with double quotes.
You need:
responses:
'(?i)password': "{{ password}}"
'(?i)#': copy startup-config disk0
'(?i)Destination filename': "{{ lookup('pipe','date') }"
---
- hosts: '6500'
gather_facts: true
connection: local
tasks:
- name: telnet,login and execute command
ignore_errors: true
expect:
command: telnet "{{ inventory_hostname }}"
responses:
(?i)Password: {{ password }}
(?i)Destination filename [disk0]? : "{{ lookup('pipe','date +%Y-%m-%d-%H-%M') }} {{ inventory_hostname }}"
(?i)#: copy startup-config disk0
(?i){{COMMAND}}: exit
echo: yes
register: telnet_output
This seems to be the best solution to what I need. I changed the order of operations and it was rocking,
I have an Ansible playbook as shown below. The only problem is every time I run it is just skipping/ignoring the task.
Can you please help me figure out what is the problem?
- name: Register Host to Dynamic Inventory
hosts: localhost
gather_facts: false
tasks:
- add_host:
name: "{{ myhost }}"
- name: Enabling the services
hosts: "{{ myhost }}"
gather_facts: true
tasks:
- name: Make the service available persistently after a reboot for SLES11
command: systemctl enable after.local
with_items: "{{ ansible_distribution_major_version }}"
when: ansible_distribution_major_version == 11
- name: Make the service available persistently after a reboot for SLES12
command: systemctl enable after.local
with_items: "{{ ansible_distributioni_major_version }}"
when: ansible_distribution_major_version == 12
TASK [add_host] ****************************************************************03:22:06
changed: [localhost]
PLAY [Enabling the services] ***************************************************03:22:06
TASK [Gathering Facts] *********************************************************03:22:06
ok: [hostname]
TASK [Make the service available persistently after a reboot for SLES11] ******03:22:10
skipping: [hostname] => (item=12)
TASK [Make the service available persistently after a reboot for SLES12] ******03:22:10
skipping: [hostname]
The tasks get skipped because ansible_distribution_major_version is a string and you compare it to an integer value.
You should either fix your conditions to:
when: ansible_distribution_major_version == "12"
Or cast the value:
when: ansible_distribution_major_version | int == 12
Having fixed that, the remaining code makes little sense and will produce a syntax error.