Category: Active Directory

Feb 21

Linux Kerberos Auhtentication

I am jotting down my recipe for RedHat 7.3 Linux and providing user logins from Microsoft's Active Directory. This was tested with two AWS instances and Microsoft AD 2016. There are many articles around the Interwebs but in short things became a lot easier with SSSD in most major distributions.

Out of scope:
- Add AD role to Windows 2016 server
- Add DNS entry and reverse entry for client
- Make sure DNS and reverse DNS works!

# more /etc/redhat-release 
Red Hat Enterprise Linux Server release 7.3 (Maipo)

# domainname
(none)

# hostname
ip-172-31-22-140.ec2.internal

# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
172.31.22.140 ip-172-31-22-140.ec2.internal 
172.31.16.163 ec2amaz-82floju.iqonda.com ec2amaz-82floju

Install packages.

# yum install realmd sssd adcli

Ensure you are pointing to the AD/DNS server for name resolution. I made sure resolv.conf can't be updated on boot since this is a dynamic EC2 instance.

 
# cat /etc/resolv.conf 
search iqonda.com
nameserver 172.31.16.163

# chattr +i /etc/resolv.conf

# ping 172.31.16.163
PING 172.31.16.163 (172.31.16.163) 56(84) bytes of data.
64 bytes from 172.31.16.163: icmp_seq=37 ttl=128 time=0.653 ms
64 bytes from 172.31.16.163: icmp_seq=38 ttl=128 time=0.522 ms
^C
--- 172.31.16.163 ping statistics ---
38 packets transmitted, 2 received, 94% packet loss, time 36999ms
rtt min/avg/max/mdev = 0.522/0.587/0.653/0.069 ms

# nslookup 172.31.16.163
Server:		172.31.16.163
Address:	172.31.16.163#53

Non-authoritative answer:
163.16.31.172.in-addr.arpa	name = ip-172-31-16-163.ec2.internal.

Authoritative answers can be found from:

# hostname
ip-172-31-22-140.ec2.internal

# nslookup ip-172-31-22-140.ec2.internal
Server:		172.31.16.163
Address:	172.31.16.163#53

Non-authoritative answer:
Name:	ip-172-31-22-140.ec2.internal
Address: 172.31.22.140

# nslookup 172.31.22.140
Server:		172.31.16.163
Address:	172.31.16.163#53

140.22.31.172.in-addr.arpa	name = ip-172-31-22-140.ec2.internal.iqonda.com.

# nslookup iqonda.com
Server:		172.31.16.163
Address:	172.31.16.163#53

Name:	iqonda.com
Address: 172.31.16.163

# dig -t SRV _ldap._tcp.ad.iqonda.com @172.31.16.163

; <<>> DiG 9.9.4-RedHat-9.9.4-38.el7_3.2 <<>> -t SRV _ldap._tcp.ad.iqonda.com @172.31.16.163
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 51524
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4000
;; QUESTION SECTION:
;_ldap._tcp.ad.iqonda.com.	IN	SRV

;; AUTHORITY SECTION:
iqonda.com.		3600	IN	SOA	ec2amaz-82floju.iqonda.com. hostmaster.iqonda.com. 95 900 600 86400 3600

;; Query time: 0 msec
;; SERVER: 172.31.16.163#53(172.31.16.163)
;; WHEN: Tue Feb 21 13:02:58 EST 2017
;; MSG SIZE  rcvd: 126

Now lets check if we can join the AD domain.

# realm discover
realm: No default realm discovered

# realm discover ec2amaz-82floju
iqonda.com
  type: kerberos
  realm-name: IQONDA.COM
  domain-name: iqonda.com
  configured: no
  server-software: active-directory
  client-software: sssd
  required-package: oddjob
  required-package: oddjob-mkhomedir
  required-package: sssd
  required-package: adcli
  required-package: samba-common-tools

# realm join ec2amaz-82floju
Password for Administrator: 

# realm list
iqonda.com
  type: kerberos
  realm-name: IQONDA.COM
  domain-name: iqonda.com
  configured: kerberos-member
  server-software: active-directory
  client-software: sssd
  required-package: oddjob
  required-package: oddjob-mkhomedir
  required-package: sssd
  required-package: adcli
  required-package: samba-common-tools
  login-formats: %U@iqonda.com
  login-policy: allow-realm-logins

Add login permission to a specific AD group.

# realm permit -g webadmins@iqonda.com

Test a client login.

$ ssh -l user1@iqonda.com ec2-107-21-198-224.compute-1.amazonaws.com
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).

Allow SSHD passwords.

# grep PasswordA /etc/ssh/sshd_config 
PasswordAuthentication yes
# systemctl restart sshd

Try client login again. And test sudo as well.

$ ssh -l user1@iqonda.com ec2-107-21-198-224.compute-1.amazonaws.com
user1@iqonda.com@ec2-107-21-198-224.compute-1.amazonaws.com's password: 
Creating home directory for user1@iqonda.com.

$ id
uid=234601107(user1@iqonda.com) gid=234600513(domain users@iqonda.com) groups=234600513(domain users@iqonda.com),234601104(webadmins@iqonda.com) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

$ pwd
/home/user1@iqonda.com

$ sudo systemctl status sshd

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for user1@iqonda.com: 
user1@iqonda.com is not in the sudoers file.  This incident will be reported.

Allow AD group sudo perms.

# tail -2 //etc/sudoers
%webadmins@iqonda.com ALL=(ALL) ALL
#%Domain\ Admins@example.com ALL=(ALL:ALL) ALL  

$ sudo systemctl status sshd
[sudo] password for user1@iqonda.com: 
● sshd.service - OpenSSH server daemon
   Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)
[..]
# systemctl status sssd
● sssd.service - System Security Services Daemon
   Loaded: loaded (/usr/lib/systemd/system/sssd.service; enabled; vendor preset: disabled)
  Drop-In: /etc/systemd/system/sssd.service.d
           └─journal.conf
   Active: active (running) since Tue 2017-02-21 13:05:42 EST; 3min 46s ago
  Process: 2276 ExecStart=/usr/sbin/sssd -D -f (code=exited, status=0/SUCCESS)
 Main PID: 2277 (sssd)
   CGroup: /system.slice/sssd.service
           ├─2277 /usr/sbin/sssd -D -f
           ├─2278 /usr/libexec/sssd/sssd_be --domain iqonda.com --uid 0 --gid 0 --debug-to-files
           ├─2279 /usr/libexec/sssd/sssd_nss --uid 0 --gid 0 --debug-to-files
           └─2280 /usr/libexec/sssd/sssd_pam --uid 0 --gid 0 --debug-to-files

Feb 21 13:05:42 ip-172-31-22-140.ec2.internal sssd[nss][2279]: Starting up
Feb 21 13:05:42 ip-172-31-22-140.ec2.internal systemd[1]: Started System Security Services Daemon.
Feb 21 13:05:42 ip-172-31-22-140.ec2.internal sssd_be[2278]: GSSAPI client step 1
Feb 21 13:05:42 ip-172-31-22-140.ec2.internal sssd_be[2278]: GSSAPI client step 1
Feb 21 13:05:42 ip-172-31-22-140.ec2.internal sssd_be[2278]: GSSAPI client step 1
Feb 21 13:05:42 ip-172-31-22-140.ec2.internal sssd_be[2278]: GSSAPI client step 2
Feb 21 13:07:58 ip-172-31-22-140.ec2.internal sssd_be[2278]: GSSAPI client step 1
Feb 21 13:07:58 ip-172-31-22-140.ec2.internal sssd_be[2278]: GSSAPI client step 1
Feb 21 13:07:58 ip-172-31-22-140.ec2.internal sssd_be[2278]: GSSAPI client step 1
Feb 21 13:07:58 ip-172-31-22-140.ec2.internal sssd_be[2278]: GSSAPI client step 2
[/bash


For reference sssd config created automatically by realm join.


# cat /etc/sssd/sssd.conf 

[sssd]
domains = iqonda.com
config_file_version = 2
services = nss, pam

[domain/iqonda.com]
ad_server = ec2amaz-82floju
ad_domain = iqonda.com
krb5_realm = IQONDA.COM
realmd_tags = manages-system joined-with-adcli 
cache_credentials = True
id_provider = ad
krb5_store_password_if_offline = True
default_shell = /bin/bash
ldap_sasl_authid = IP-172-31-22-14$
ldap_id_mapping = True
use_fully_qualified_names = True
fallback_homedir = /home/%u@%d
access_provider = simple
simple_allow_groups = webadmins@iqonda.com

Comments Off on Linux Kerberos Auhtentication
comments

Nov 12

CIFS ACLs on ZFS Problem

Recently had an issue with a CIFS share on a Solaris 11 box.  Still not sure how this happened but it turned out there was a weird Idmap mapping.  Active Directory Group and members were correct and group had correct members.  Yet still the users in this group could not write to the folder.

 How to check identities in idmap:

# idmap show -cv rrosso@domain.com
winuser:rrosso@domain.com -> uid:2147483651
Source: Cache
Method: Ephemeral

# idmap show -cv DFS_Corp-CA-Dept-IT_rw@domain.com
wingroup:DFS_Corp-CA-Dept-IT_rw@domain.com -> gid:2147483667
Source: Cache
Method: Ephemeral

Lets just see how the mapping rules look:

# idmap list
add     winuser:*@domain.com  unixuser:*
add     wingroup:*@domain.com unixgroup:*
add     winuser:administrator@domain.com      unixuser:root
add     "wingroup:Domain Users@domain.com"    unixgroup:smbusers

The Active Directory Read-Write group that is not allowing the members to write to the folder:

# idmap show -cv DFS_Eng-CA-Dirs-Engineering-Bugzilla_rw@domain.com
wingroup:DFS_Eng-CA-Dirs-Engineering-Bugzilla_rw@domain.com -> gid:2147484149
Source: Cache
Method: Ephemeral

Looking at the folder called Bugzilla:
Current (broken) acl must be this one user:2147483813 if I look at the gid above.  Not to mention the mapping is not for a group but for a user.

root@zfs001:/tank/dfs/engdirs/engineering/engineering# /bin/ls -v | more
d---------+ 16 2147483650 smbusers      17 Oct 12 14:14 Bugzilla
0:user:2147483813:list_directory/read_data/add_file/write_data
/add_subdirectory/append_data/read_xattr/write_xattr/execute
/read_attributes/write_attributes/delete/read_acl/synchronize
:file_inherit/dir_inherit:allow
1:group:2147483763:list_directory/read_data/add_file/write_data
/add_subdirectory/append_data/read_xattr/write_xattr/execute
/delete_child/read_attributes/write_attributes/delete/read_acl
/synchronize:file_inherit/dir_inherit:allow
2:group:2147483660:list_directory/read_data/read_xattr/execute
/read_attributes/read_acl/synchronize:file_inherit/dir_inherit
:allow

Looking at above something looks odd.  Looking at the windows side we expect three groups to have permission here but spot the "user" listed in the first ACL.

Lets find the three id's.  Left the grep wide open to find all uid and gid matching the number. But really we are just after the gid's:

# idmap dump -n | grep 2147483813
wingroup:Guests@BUILTIN ==      gid:2147483813
wingroup:DFS_Eng-CA-Dirs-Engineering-Bugzilla_rw@domain.com   ==      uid:2147483813

# idmap dump -n | grep 2147483763
winuser:Homey@domain.com     ==      uid:2147483763
wingroup:DFS_Eng-CA-Dirs-Engineering_rw@domain.com    ==      gid:2147483763

# idmap dump -n | grep 2147483660
winuser:Stewey@domain.com     ==      uid:2147483660
wingroup:DFS_Eng-CA-Dirs-Engineering_ro@domain.com    ==      gid:2147483660

# idmap dump -n | grep 2147484149
wingroup:DFS_Eng-CA-Dirs-Engineering-Bugzilla_rw@domain.com   ==      gid:2147484149

 

After we removed and  recreated the group in AD.  Might take a little bit to show up:

# idmap show -cv DFS_Eng-CA-Dirs-Engineering-Bugzilla_rw@domain.com
wingroup:DFS_Eng-CA-Dirs-Engineering-Bugzilla_rw@domain.com -> gid:2147484149
Source: Cache
Method: Ephemeral

# idmap dump -n | grep 2147483813
wingroup:Guests@BUILTIN ==      gid:2147483813
usid:S-1-5-21-1977730361-3076317898-4166923938-22371    ==      uid:2147483813

# idmap dump -n | grep 147484149
wingroup:DFS_Eng-CA-Dirs-Engineering-Bugzilla_rw@domain.com   ==      gid:2147484149

Permissions after re-applying from Windows:

# /bin/ls -dv Bugzilla/
d---------+ 17 2147483650 smbusers      18 Nov 12 20:12 Bugzilla/
     0:group:2147483763:list_directory/read_data/add_file/write_data
         /add_subdirectory/append_data/read_xattr/write_xattr/execute
         /delete_child/read_attributes/write_attributes/delete/read_acl
         /synchronize:file_inherit/dir_inherit:allow
     1:group:2147483660:list_directory/read_data/read_xattr/execute
         /read_attributes/read_acl/synchronize:file_inherit/dir_inherit
         :allow
     2:group:2147484149:list_directory/read_data/add_file/write_data
         /add_subdirectory/append_data/read_xattr/write_xattr/execute
         /read_attributes/write_attributes/delete/read_acl/synchronize
         :file_inherit/dir_inherit:allow

Just checking a new file we just created for good measure:

# /bin/ls -v | grep Test
d---------+  2 2147483740 smbusers       2 Nov 12 20:12 Test

Comments Off on CIFS ACLs on ZFS Problem
comments

Nov 06

Python-ldap Query MS Active Directory

I use Python to pull Active Directory information sometimes. In my case mainly to report or view information but also to create files in a LDIF or PowerShell format.  These can be manually run on the Domain Controller later. For instance find all users in a Distribution List or Group and create a rule or ldif entry that can manually be executed line by line. Off course there is also ways with PowerShell and vbscript to do this, but I prefer Python for text manipulation and it is not too cumbersome for me to batch run these files manually later.

I noticed on Ubuntu 12.10 that my query failed with the following error:

ldap.LDAP_CONTROL_PAGE_OID,True,(page_size,'')
AttributeError: 'module' object has no attribute 'LDAP_CONTROL_PAGE_OID'

I found a comment from the developers saying that with python-ldap 2.4
"there have been changes in the API for LDAPv3 extended controls. Please see Demo/page_control.py (and Demo/paged_search_ext_s.py) how to use the simple paged control with 2.4."

I found the source here: http://python-ldap.cvs.sourceforge.net/viewvc/python-ldap/python-ldap/Demo/page_control.py?view=log

I made a new script and tested as shown below:
** Note the following first:

  1. This is a "paged" query meaning you should not have issues if LDAP return a limted number of results.  More detail here: http://support.microsoft.com/kb/315071
  2. You need to install python-ldap of course.  apt-get install python-ldap should work on apt systems.
  3. Check comment about using 512 as userAccountControl.
DistributionList = "CN=IT Infrastructure,CN=Distribution Lists,CN=Users,DC=domain,DC=com"

url = "ldap://usdc101"
base = "dc=domain,dc=com"
#  search_flt = r'(objectClass=*)'
##  I used userAccountControl=512 but that would most certainly exclude some 
##  user accounts in your domain. For instance "66048 Enabled, Password Doesn't Expire"
##  values listed here: http://www.netvision.com/ad_useraccountcontrol.php
search_flt = r'(&(objectCategory=user) (userAccountControl=512) )'

page_size = 10

import ldap,pprint
from ldap.controls import SimplePagedResultsControl

searchreq_attrlist=["displayName","cn","distinguishedName","mail","memberOf"]

ldap.set_option(ldap.OPT_REFERRALS, 0)
l = ldap.initialize(url,trace_level=0)
l.protocol_version = 3
l.simple_bind_s("ADaccount@domain.com", "passsword")

req_ctrl = SimplePagedResultsControl(True,size=page_size,cookie='')

known_ldap_resp_ctrls = {
SimplePagedResultsControl.controlType:SimplePagedResultsControl,
}

# Send search request
msgid = l.search_ext(
base,
ldap.SCOPE_SUBTREE,
search_flt,
attrlist=searchreq_attrlist,
serverctrls=[req_ctrl]
)

pages = 0
i = 0
print "listing users in the list:" + DistributionList

while True:
  pages += 1
  rtype, rdata, rmsgid, serverctrls = l.result3(msgid,resp_ctrl_classes=known_ldap_resp_ctrls)

  for dn, entry in rdata:
    ##  Lets check if the user is a member of the AD List / Group
    try:
      membership = entry['memberOf']
    except:
      membership = 'none'
    if DistributionList in membership:
      i += 1
      print " \"%d\" | \"%s\" " % (i , dn)

  pctrls = [
    c
    for c in serverctrls
    if c.controlType == SimplePagedResultsControl.controlType
  ]
  if pctrls:
    if pctrls[0].cookie:
      # Copy cookie from response control to request control
      req_ctrl.cookie = pctrls[0].cookie
      msgid = l.search_ext(
        base,
        ldap.SCOPE_SUBTREE,
        search_flt,
        attrlist=searchreq_attrlist,
        serverctrls=[req_ctrl]
      )
    else:
      break
  else:
    print "Warning: Server ignores RFC 2696 control."
    break

l.unbind_s()

Comments Off on Python-ldap Query MS Active Directory
comments