Tech Blog

As you may have surmised by now, I am a big fan of SSSD.  One recent addition to this utility was the ability to control SSH access via an active directory group policy.  Yes, you read that right.  You can control SSH access by the placement of the system's computer account within active directory which can then determine what group policies are applied.  In the heterogeneous environments that most of us work in, this just might make your life a bit easier AND impress your Windows admin friends!

To get started, I am going to use the same CentOS 7 system with SSSD configured as discussed in a previous blog post here.  For the sake of clarity, here are the config files again:

Kerberos config (/etc/krb5.conf)

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

[libdefaults]
default_realm = THEHARRISHOME.LAN
dns_lookup_realm = true
dns_lookup_kdc = true
ticket_lifetime = 24h
renew_lifetime = 7d
rdns = false
forwardable = yes

[realms]

[domain_realm]

Note above that the domain name is in all capital letters.  This is important.

Samba config (/etc/samba/smb.conf)

[global]
   workgroup = THEHARRISHOME
   client signing = yes
   client use spnego = yes
   kerberos method = secrets and keytab
   log file = /var/log/samba/%m.log
   password server = *
   realm = THEHARRISHOME.LAN
   security = ads

Again note that the domain is in all capital letters.

SSSD config (/etc/sssd/sssd.conf)

[sssd]
config_file_version = 2
domains = theharrishome.lan
services = nss, pam
debug_level = 0

[nss]

[pam]

[domain/theharrishome.lan]
debug_level = 0

enumerate = false
id_provider = ldap
auth_provider = krb5
chpass_provider = krb5
access_provider = ldap
ldap_idmap_range_size = 800000
ldap_idmap_range_min = 200000
ldap_idmap_range_max = 2000200000

ldap_id_mapping = true
# ldap_access_filter = (memberOf=cn=LinuxAdmins,ou=Groups,dc=theharrishome,dc=lan)
default_shell = /bin/bash
fallback_homedir = /home/%u
ldap_access_order = filter

ldap_sasl_mech = GSSAPI
ldap_schema = ad
# ldap_user_search_base = dc=theharrishome,dc=lan
# ldap_group_search_base = ou=Groups,dc=theharrishome,dc=lan
ldap_user_object_class = user
ldap_user_home_directory = unixHomeDirectory
ldap_user_principal = nosuchattribute
ldap_group_object_class = group
ldap_access_order = expire
ldap_account_expire_policy = ad
ldap_force_upper_case_realm = true
krb5_realm = THEHARRISHOME.LAN
krb5_canonicalize = false

# systemctl stop sssd;rm -f /var/log/sssd/*;rm -f /var/lib/sss/db/*;systemctl start sssd

We don't need to change the config file for Kerberos config (/etc/krb5.conf) or Samba config (/etc/samba/smb.conf) but we will need to make a few changes to the SSSD config (/etc/sssd/sssd.conf).

The previous settings for the following will need to be changed to "ad" as shown:

id_provider = ad
auth_provider = ad
chpass_provider = ad
access_provider = ad

Next, we need to enable GPO access control by adding the following to the SSSD config file:

ad_gpo_access_control = enforcing

Finally, restart SSSD so the changes will take effect (# systemctl restart sssd).  Here is a copy of the new SSSD config file (/etc/sssd/sssd.conf):

[sssd]
config_file_version = 2
domains = theharrishome.lan
services = nss, pam
debug_level = 0

[nss]

[pam]

[domain/theharrishome.lan]
debug_level = 0

enumerate = false
id_provider = ad
auth_provider = ad
chpass_provider = ad
access_provider = ad
ldap_idmap_range_size = 800000
ldap_idmap_range_min = 200000
ldap_idmap_range_max = 2000200000

ldap_id_mapping = true
# ldap_access_filter = (memberOf=cn=LinuxAdmins,ou=Groups,dc=theharrishome,dc=lan)
default_shell = /bin/bash
fallback_homedir = /home/%u
ldap_access_order = filter

ldap_sasl_mech = GSSAPI
ldap_schema = ad
# ldap_user_search_base = dc=theharrishome,dc=lan
# ldap_group_search_base = ou=Groups,dc=theharrishome,dc=lan
ldap_user_object_class = user
ldap_user_home_directory = unixHomeDirectory
ldap_user_principal = nosuchattribute
ldap_group_object_class = group
ldap_access_order = expire
ldap_account_expire_policy = ad
ldap_force_upper_case_realm = true
krb5_realm = THEHARRISHOME.LAN
krb5_canonicalize = false

ad_gpo_access_control = enforcing
# systemctl stop sssd;rm -f /var/log/sssd/*;rm -f /var/lib/sss/db/*;systemctl start sssd 

Now we can turn our attention to creating a group policy in active directory.  The two settings we will be working with can be found in the Group Policy Management Editor under Computer Configuration -> Windows Settings ->Security Settings -> Local Policies -> User Rights Assignment.  They are as follows:

  • Allow log on through Remove Desktop Services - Believe it or not, this setting controls SSH access.  This is not particularly clear but it is somewhat logical.
  • Allow log on locally - Just as you might expect, this controls who can log on the local machine (NOT via SSH).

The intent of this article is not to get into all the nuances of active directory and group policies, but here are some guidelines for testing this functionality:

  • Launch Active Directory Users and Computers and create a new organization unit (OU).  I called mine RootOU
  • Under the RootOU created above, create 2 additional OU's, one named user1 and one named user2
  • Create the 2 users, user1 and user2 and put them directly under the RootOU
  • Put the computer account of your CentOS/RHEL system that you previously joined to the domain under the RootOU/user1 organizational unit
  • Launch Group Policy Management Editor and create a group policy for both the user1 and user2 OU's
  • Actually, for the rest of this, we can just use the group policy that was created and attached to the user1 OU created above.  I created the user2 OU just to have another one.
  • Depending on which policy you need to use above, simply allow or deny the appropriate user the ability to log on with that policy and then test to verify it works.

Any change you make to the group policy within active directory should take effect immediately assuming the policy has had time to propagate to all domain controllers within your domain.  For testing purposes, I have found it handy to install mlocate (# yum -y install mlocate) followed by updating it (# updatedb).  Then once you have logged in or attempted to log in (note that causes the policy to update), you should be able to find the group policy file by first update mlocate's database again (# updatedb) followed by running # locate GptTmpl.inf.  It should be located under /var/lib/sss/gpo_cache/{your domain name}/Policies/{A unique GUID}/Machine/Microsoft/Windows NT/SecEdit.  Here is a screenshot of what mine looks like and note that I had to escape the space in "Windows NT" with "Windows\ NT":

gpo

Perhaps it is because this functionality is so new but unfortunately I haven't found it to be well documented.  The best information I have found that does cover some of the other features of this functionality can be found at https://fedoraproject.org/wiki/Changes/SssdGpoBasedAccessControl.  As always, I'm just covering the basics but it can do a lot more so do check it out.

Thanks for reading.

- Kyle H.