Playbook that Converts Local to AD Users

If you like removing local users in favor of the domain users, check out how to do that in shell at my post Convert Local to AD Users.

If you want to do it at scale, you can wrap it with a bit of ansible. Check out the full thing with syntax highlighting on gitlab: https://gitlab.com/bgstack15/former-gists/blob/master/cladu.yml/cladu.yml

---
# Only use one thisuser at a time, for the fail/changed logic to work correctly!
# usage: ansible-playbook -l targethost1 /etc/ansible/books/stable/cladu.yml -v -e 'thisuser=joneill'

- name: book that runs cladu
  hosts: all
  become: yes
  become_user: root
  become_method: sudo
  tasks:

  - name: copy in rpm
    copy:
      src: /etc/ansible/files/bgscripts-core-1.3-9.noarch.rpm
      dest: /tmp/
      mode: 0644

  - shell: rpm -U --nodeps /tmp/bgscripts-core-1.3-9.noarch.rpm
    args:
      warn: no
    register: this_rpm
    failed_when:
    - 'not ("is already installed" in this_rpm.stdout or "is already installed" in this_rpm.stderr or this_rpm.rc == 0)'
    changed_when:
    - 'not ("is already installed" in this_rpm.stdout or "is already installed" in this_rpm.stderr)'

  - shell: /usr/share/bgscripts/work/cladu.sh -r -g '{{ thisuser }}'
    args:
      warn: no
    register: this_shell
    changed_when:
    - 'not ("Skipped" in this_shell.stdout or "Failed" in this_shell.stdout)'
    failed_when:
    - '"Failed" in this_shell.stdout'
Advertisements

Playbook that resets user password

As an admin, it’s my job to reset user passwords who still use local accounts. I’m working on converting users to domain accounts, but in the mean time, here’s my little book.
Check it out with context highlighting at https://gitlab.com/bgstack15/former-gists/blob/master/reset-password.yml/reset-password.yml

---
# Dependencies: pwhashgen.py from bgscripts-core, installed on ansible server
- name: book that resets password for thisuser
  hosts: all
  become: yes
  become_user: root
  become_method: sudo
  tasks:

  - name: generate pw hash
    shell: /usr/share/bgscripts/py/pwhashgen.py "{{ thispw | default('TEMP_PASSWORD_HERE') }}"
    register: thispw
    delegate_to: localhost
    changed_when: false
    run_once: true

  - user:
      name: "{{ thisuser }}"
      password: "{{ thispw.stdout }}"

  - shell: passwd -e "{{ thisuser }}"
    args:
      warn: no

getent passwd -s sss LOCALUSER shows local user

tl;dr

I want to easily and quickly tell if a user is local or domain (don’t care which domain).

Environment

  • freeipa-client-4.6.1-3.fc27.x86_64
  • sssd-1.16.0-4.fc27.x86_64

Full story

I am writing a userinfo.sh script that will show if a user is local, sssd, can ssh, and is permitted by sssd.

Currently I am doing the check for if the user is from the domain with the getent passwd -s sss $USERNAME command. But I ran into an issue where checking the sssd database returns a local user!

# getent passwd -s sss 'bgstack15-local'
bgstack15-local:x:1000:1000:bgstack15-local:/home/bgstack15-local:/bin/bash

Checking the contents of the database (cache) for sss shows sssd apparently caches all sorts of information about the local user.

# sudo su root -c 'strings /var/lib/sss/db/* | grep bgstack15-local' | sort | uniq
name=bgstack15-local@implicit_files,cn=groups,cn=ih
name=bgstack15-local@implicit_files,cn=groups,cn=implicit_files,cn=sysdb
name=bgstack15-local@implicit_files,cn=users,cn=implicit_files,cn=sysdb
[...output truncated]

I tried clearing the sssd cache overall, and just for the user. Neither made a difference.

# sss_cache -U
# sss_cache -u bgstack15-local

The user does show up as a local user, and I promise it is only a local user!

getent passwd -s files 'bgstack15-local'
bgstack15-local:x:1000:1000:bgstack15-local:/home/bgstack15-local:/bin/bash

The man pages for getent(1) and getpwent(3) don’t help me understand what could be going on. sssd(8) shows me that sssd can cache local users, which actually goes against what I want! The nss section of sssd.conf(5) doesn’t help, but maybe I didn’t take enough time to read it. I’m a little stuck.

My sssd.conf

[domain/ipa.example.com]
id_provider = ipa
ipa_server = _srv_, dns1.ipa.example.com
ipa_domain = ipa.example.com
ipa_hostname = fc27c-01a.ipa.example.com
auth_provider = ipa
chpass_provider = ipa
access_provider = ipa
cache_credentials = True
ldap_tls_cacert = /etc/ipa/ca.crt
krb5_store_password_if_offline = True
[sssd]
services = nss, pam, ssh, sudo
domains = ipa.example.com
[nss]
homedir_substring = /home
[pam]
[sudo]
[autofs]
[ssh]
[pac]
[ifp]
[secrets]
[session_recording]

Last resort

I can try doing my checks against ${USERNAME}@${DOMAIN} when doing the -s sss check, but that means I then have to iterate over all domains in sssd.conf and that would slow the process down.


Answer

The option that controls this behavior is buried in sssd.conf(5) on CentOS 7 and Fedora, but not in the online man page.

sssd.conf

[sssd]
enable_files_domain = false

Reference 3 shows that sssd makes a “fast cache for local users.”

From man sssd.conf(5) on my Fedora system:

   enable_files_domain (boolean)
       When this option is enabled, SSSD prepends an implicit domain with
       “id_provider=files” before any explicitly configured domains.

       Default: true

Disabling this behavior lets me make a simple check to see if it is a local user or domain user.

References

  1. ddg: sssd disable caching local users
  2. https://bugzilla.redhat.com/show_bug.cgi?id=1357418
  3. https://fedoraproject.org/wiki/Changes/SSSDCacheForLocalUsers
  4. Fedora 27 sssd.conf(5)

Custom userinfo.sh

History

I needed to query certain information about a user on a Linux system. Specifically this output:

user: bgstack15
getent: YES
getent_type: sss
can_ssh: YES
can_sss: YES

I wanted to know if a user is defined (getent), and if so, in which database (local or in Active Directory). Also, is the user in the AllowUsers list of the sshd_config, or a member of a group in the AllowGroups list. And then the same question for the sssd config file.

The script

List outbound ssh sessions

tl;dr

sudo netstat -Watp | grep 'ESTABLISHED.*ssh' | awk '{print $5}' | sed 's/:ssh//;' | sort | uniq | while read line; do ps -ef | grep -o "ssh\s.*${line}"; done | sort | uniq | sed -r -e 's/ssh //g;' -e 's/-l (\w*) /\1@/;'

Backstory

During other work, it came up that I was interested in seeing what outbound ssh sessions I was using. Now I don’t even know why it came up, because I was just writing a shell script to programmatically adjust my xfce settings using its xfconf-query API.

Walking through the command

sudo netstat -Watp | grep 'ESTABLISHED.*ssh' | awk '{print $5}' | sed 's/:ssh//;' | sort | uniq | while read line; do ps -ef | grep -o "ssh\s.*${line}"; done | sort | uniq | sed -r -e 's/ssh //g;' -e 's/-l (\w*) /\1@/;'

This whole statement lists the established ssh connections and then finds the running processes for those and tries to identify the usernames for them.
Step by step:
Everything before the while collects the list of established ssh connections.
sudo netstat -Watp | grep ‘ESTABLISHED.*ssh’ gets the list of ssh connections, and awk | sed | sort | uniq just gets the information we want from each row and removes duplicates.
The while read line; do :; done loop iterates over the list. So for each line in the list, search all running processes for that name on the same line as the expression ‘ssh.’
sort | uniq removes duplicates (apparently qemu+kvm in virt-manager uses a lot of separate ssh processes).
sed -r -e ‘s/ssh //g;’ -e ‘s/-l (\w*) /\1@/;’ trims extra characters and also converts compatible outputs into “username@hostname.”

Improvements to be made

This snippet as is only works if the ssh command issued matches exactly the description of the output of netstat. If dns reverse zones are not configured correctly, so that the netstat shows an IP address but the ssh command was a hostname, this snippet will not find it. I need to improve that, which will probably require a fancier script and not just a oneliner.

References

Weblinks

  1. https://serverfault.com/questions/431034/getting-list-of-opened-ssh-connections-by-name