Freeipa One-way Trust with Active Directory

Hello all! This week’s post is all about freeipa and how to integrate one-way trust with Active Directory. The goal? A lowly Windows user can login to our Linux (CentOS 6.5 x64) box, get a home directory, and even execute a sudo command. Let’s get started!


In this post, we create two Kerberos Key Distribution Centers. One is a Windows domain named ad.example.local and the other is a Linux (CentOS) install of the FreeIPA system named example.local. We’ll further complicate (simplify??) matters by referencing a common DNS server to which we will add required service records. Our goal is to permit a one-way trust between the AD and the Linux boxes; a Windows user should be able to login to the freeipa side and perform authorized actions based on Active Directory group memberships.

The FreeIPA domain is defined and managed by a FreeIPA server which is essentially a domain controller. There can be multiple domain controllers within a domain for load-balancing and failover tolerance. These additional servers are called replicas of the master FreeIPA server.

In this article, we will use freeipa to manage the local KDC and use this server for Kerberos / LDAP integration. Our use cases:


  • Create user in freeipa realm and assign to an “Admin” LDAP group.


  • Integrate Linux box with freeipa KDC and LDAP.
  • Logon to Linux box using the freeipa realm. Have home directory automatically created and verify correct sudo operation.


  • Integrate Windows AD controller with freeipa KDC (service principal integration).
  • Integrate Windows AD controller with freeipa LDAP (federation).
  • Logon to Linux box using Windows realm (domain). Have home directory created automatically and verify correct sudo operation.

Let’s get started!

FreeIPA Server Setup


Follow these steps:

  1. We are using OpenStack to run our virtual environment, and we have a standard VM image we use. So we create the VM using these steps:
    • Setup Security Group. There are a number of ports that must be opened at the Guest VM level and they must also be opened at the OpenStack level. Here is the result:
      [n75029@isgmj2chg3qp rc_scripts(lvosksclu100-rc-admin)]$ nova --os-tenant-name=infrastructure secgroup-list-rules infrastructure-freeipa
      | IP Protocol | From Port | To Port | IP Range  | Source Group |
      | tcp         | 9701      | 9701    | |              |
      | udp         | 464       | 464     | |              |
      | udp         | 123       | 123     | |              |
      | udp         | 445       | 445     | |              |
      | tcp         | 138       | 138     | |              |
      | udp         | 139       | 139     | |              |
      | tcp         | 636       | 636     | |              |
      | tcp         | 9180      | 9180    | |              |
      | udp         | 88        | 88      | |              |
      | tcp         | 9443      | 9446    | |              |
      | udp         | 138       | 138     | |              |
      | tcp         | 389       | 389     | |              |
      | udp         | 389       | 389     | |              |
      | tcp         | 88        | 88      | |              |
      | tcp         | 443       | 443     | |              |
      | tcp         | 80        | 80      | |              |
      | tcp         | 445       | 445     | |              |
      | tcp         | 53        | 53      | |              |
      | tcp         | 139       | 139     | |              |
      | tcp         | 464       | 464     | |              |
      | udp         | 53        | 53      | |              |
      | tcp         | 7389      | 7389    | |              |
    • Create standard VM image. As indicated above, you can pull down an OpenStack-ready image or you can build your own (as we did…but that’s another article). Once you have your image, you can get the ID for it; our image is named lxoscentc065.qcow2; it’s very small (minimal CentOS image):
      [n75029@isgmj2chg3qp rc_scripts(lvosksclu100-rc-admin)]$ nova --os-tenant-name=infrastructure image-show lxoscentc065.qcow2
      | Property             | Value                                |
      | OS-EXT-IMG-SIZE:size | 498663424                            |
      | created              | 2014-11-19T14:59:43Z                 |
      | id                   | 500bd635-d9d0-45a3-a523-4b6bfdbf6f85 |
      | minDisk              | 0                                    |
      | minRam               | 0                                    |
      | name                 | lxoscentc065.qcow2                   |
      | progress             | 100                                  |
      | status               | ACTIVE                               |
      | updated              | 2014-11-19T15:00:38Z                 |
    • Boot VM from image.. Now that we know our information, we can boot the VM image. In this case, we’ve already created Neutron networking and we won’t cover that here. We’ve also created a strong public/private keypair that we will use. We’ll name our freeipa server lvinfripa100, make is a “small” flavor (1 vCPU, 2GB RAM, 20GB HDD), add our security groups (including one for ping (ICMP) and SSH support):
      nova --os-tenant-name=infrastructure boot --flavor 2 \
        --image 500bd635-d9d0-45a3-a523-4b6bfdbf6f85 --key-name sadmin-keypair \
        --security-groups default,infrastructure-icmp-ssh,infrastructure-freeipa \
        --nic net-id=88513920-091b-4bee-a47c-5636593c69f5 lvinfripa100
    • Setup external floating IP. We are using Neutron GRE per-tenant networking so our new VM will boot into its own private little hell. For us to get to it externally, we need to apply an IP address to it. We won’t cover the steps to do this (nova floating-ip-create, nova floating-ip-add) but instead take it as read we have it. We are using for our freeipa server.
    • Configure VM. After first boot, boot *again* to get the hostname / FQDN correct. In our case, we use puppet to automate / configure our managed VMs. So we setup puppet on our shiny new server:
      puppet agent -t
      chkconfig puppet on
      service puppet start
  2. Create entry in DNS; we are using dnsmasq so we use the following:
    # /etc/dnsmasq.hosts     lvinfripa100.example.local

    This is not enough; the freeipa server is running NAT’ed so the local tenant IP address must match on the freeipa server itself:

    # /etc/hosts     lvinfripa100.example.local lvinfripa100
  3. Install the freeipa server:
    yum -y install ipa-server

    If you use a local yum repository the install will go very quickly. Then configure the freeipa server (fill in your own passwords):

    ipa-server-install --debug --domain=example.local --realm=EXAMPLE.LOCAL \
      -p [PASSWORD] -a [_PASSWORD] \
      --no-ntp | tee ~/freeipa.log --unattended

    This takes about 10 minutes on my underpowered VM. Setup services to auto-start:

    chkconfig httpd on
    chkconfig krb5kdc on
    chkconfig ipa on
  4. Setup firewall; these commands can be run directly from command line. (The below matches the Security Group we showed above.)
    iptables -I 2 INPUT -p tcp -m state --state NEW -m tcp --dport 53 \
      -m comment --comment "FreeIPA: DNS-TCP" -j ACCEPT
    iptables -I 2 INPUT -p udp -m state --state NEW -m udp --dport 53 \
      -m comment --comment "FreeIPA: DNS-UDP" -j ACCEPT
    iptables -I 2 INPUT -p tcp -m state --state NEW -m tcp --dport 80 \
      -m comment --comment "FreeIPA: HTTP" -j ACCEPT
    iptables -I 2 INPUT -p tcp -m state --state NEW -m tcp --dport 88 \
      -m comment --comment "FreeIPA: Kerberos-TCP" -j ACCEPT
    iptables -I 2 INPUT -p udp -m state --state NEW -m udp --dport 88 \
      -m comment --comment "FreeIPA: Kerberos-UDP" -j ACCEPT
    iptables -I 2 INPUT -p tcp -m state --state NEW -m tcp -m multiport --dports 138,139,445 \
      -m comment --comment "FreeIPA: NetBIOS/SMB-TCP" -j ACCEPT
    iptables -I 2 INPUT -p udp -m state --state NEW -m udp -m multiport --dport 138,139,445 \
      -m comment --comment "FreeIPA: NetBIOS/SMB-UDP" -j ACCEPT
    iptables -I 2 INPUT -p tcp -m state --state NEW -m tcp --dport 389 \
      -m comment --comment "FreeIPA: LDAP-TCP" -j ACCEPT
    iptables -I 2 INPUT -p udp -m state --state NEW -m udp --dport 389 \
      -m comment --comment "FreeIPA: LDAP-UDP" -j ACCEPT
    iptables -I 2 INPUT -p tcp -m state --state NEW -m tcp --dport 443 \
      -m comment --comment "FreeIPA: HTTPS" -j ACCEPT
    iptables -I 2 INPUT -p tcp -m state --state NEW -m tcp --dport 464 \
      -m comment --comment "FreeIPA: Kerberos-TCP" -j ACCEPT
    iptables -I 2 INPUT -p udp -m state --state NEW -m udp --dport 464 \
      -m comment --comment "FreeIPA: Kerberos-UDP" -j ACCEPT
    iptables -I 2 INPUT -p tcp -m state --state NEW -m tcp --dport 636 \
      -m comment --comment "FreeIPA: LDAPS" -j ACCEPT
    iptables -I 2 INPUT -p tcp -m state --state NEW -m tcp --dport 7389 \
      -m comment --comment "FreeIPA: Dogtag: LDAP database" -j ACCEPT
    iptables -I 2 INPUT -p tcp -m state --state NEW -m tcp --dport 9180 \
      -m comment --comment "FreeIPA: Dogtag: OCSP responder" -j ACCEPT
    iptables -I 2 INPUT -p tcp -m state --state NEW -m tcp --dport 9443:9446 \
      -m comment --comment "FreeIPA: Dogtag: agents/users (SSL)/admins/users (AUTH)" -j ACCEPT
    iptables -I 2 INPUT -p tcp -m state --state NEW -m tcp --dport 9701 \
      -m comment --comment "FreeIPA: Dogtag: Tomcat" -j ACCEPT
    service iptables save
  5. By default, anonymous binds are disallowed to freeipa. This can be a problem if you are monitoring your underlying 389 Directory Server that is used by freeipa. So we enable replication monitoring from anonymous bind. Create file:
    # grant_anonymous_replication_view.ldif
    dn: cn="dc=example,dc=local",cn=mapping tree,cn=config
    changetype: modify
    add: aci
    aci: (targetattr=*)(targetfilter="(|(objectclass=nsds5replicationagreement)(objectclass=nsDSWindowsReplicationAgreement))")(version 3.0; aci "permission:Read Replication Agreements"; allow (read, search, compare) groupdn = "ldap:///anyone";)

    Then run command:

    ldapmodify -x -D "cn=directory manager" -W -f grant_anonymous_replication_view.ldif \
      -h lvinfripa100.example.local

    Verify output as follows:

    ldapsearch -x -h lvinfripa100.example.local \
      -b cn=config '(objectclass=nsds5replicationagreement)'

    This should return the following:

    # extended LDIF
    # LDAPv3
    # base <cn=config> with scope subtree
    # filter: (objectclass=nsds5replicationagreement)
    # requesting: ALL
    # search result
    search: 2
    result: 0 Success
    # numResponses: 1


  6. By default, non-freeipa clients cannot access the FreeIPA Web interface. You can work around this as follows:
    # /etc/httpd/conf.d/ipa.conf
    <Location "/ipa">
    KrbMethodK5Passwd on

    Then, restart the Web server:

    service httpd restart

Your freeipa server is now configured.


1.3     FreeIPA Client Setup

A freeipa client uses (by default) SSSD to do all Kerberos login integration. So we’ll install it on a local laptop (Mac) via VirtualBox. Created Redmine entry for this; see


  1. Set the hostname:




Continue to the next step.

  1. Install freeipa client and all graphical tools. We use the graphical tools so we can connect to the freeipa Web server from Firefox on the client.


yum install ipa-client

only if you want graphical environment: BEGIN

yum install “@Desktop Platform”

yum install “@X Window System”

yum install “@Fonts”

yum install “@Graphical Administration Tools”

yum install “@Internet Browser”

yum install “@General Puprose Desktop”

only if you want graphical environment: END


Next, set the system to boot to graphical environment – only if you installed the graphical environment:




Continue to the next step.

  1. Reboot the system to set the hostname (so DNS will work) and verify graphical login (if you installed graphical tools).
  2. Update DNS so that the freeipa server can resolve the freeipa client. Remember that this is more complex if you’re running the test with Vagrant as a locally NAT’ed VM within your laptop (host).
  3. If running a VM with quick snapshots (unlike OpenStack): Shutdown the VM. Then take a snapshot of the VM to enable easy rollback. Restart the VM.
  4. Install the freeipa client:

[root@lvinipacl010 ~]# ipa-client-install –domain hlsdev.local \

–server lvinfripa100.hlsdev.local –realm HLSDEV.LOCAL \

–mkhomedir –hostname=$(hostname) –unattended –no-ntp –force \

-p admin –password=”[2s]”| tee ipa-client-install.log


Note in the above that you must put in the username / password for binding to the freeipa server. Update the command accordingly.

The system then installs freeipa client and should respond with a number of successful messages:

Hostname: lvinipacl010.hlsdev.local


DNS Domain: hlsdev.local

IPA Server: lvinfripa100.hlsdev.local

BaseDN: dc=hlsdev,dc=local

Synchronizing time with KDC…

Unable to sync time with IPA NTP server, assuming the time is in sync. Please check that 123 UDP port is opened.

Successfully retrieved CA cert

   Subject:     CN=Certificate Authority,O=HLSDEV.LOCAL

   Issuer:     CN=Certificate Authority,O=HLSDEV.LOCAL

   Valid From: Wed Nov 19 18:13:47 2014 UTC

   Valid Until: Sun Nov 19 18:13:47 2034 UTC

Enrolled in IPA realm HLSDEV.LOCAL

Created /etc/ipa/default.conf

New SSSD config will be created

Configured sudoers in /etc/nsswitch.conf

Configured /etc/sssd/sssd.conf

Configured /etc/krb5.conf for IPA realm HLSDEV.LOCAL

trying https://lvinfripa100.hlsdev.local/ipa/xml

Forwarding ‘env’ to server u’https://lvinfripa100.hlsdev.local/ipa/xml’

Adding SSH public key from /etc/ssh/

Adding SSH public key from /etc/ssh/

Adding SSH public key from /etc/ssh/

Forwarding ‘host_mod’ to server u’https://lvinfripa100.hlsdev.local/ipa/xml’

Could not update DNS SSHFP records.

SSSD enabled

Configuring hlsdev.local as NIS domain

Configured /etc/openldap/ldap.conf

Configured /etc/ssh/ssh_config

Configured /etc/ssh/sshd_config

Client configuration complete.


  1. In our test, we had one additional change required in anticipation of cross-domain trusts:


dns_lookup_kdc = true


Initially, this value was set to “false” which will break things later on. So change it now.

With that, you can now login to the freeipa server from the client and check the status of the install.


1.4     Sudo Setup

Sudo was complex to get working, it appears that there is a bug between freeipa client and freeipa server in getting sudo rules when working in straight sssd mode.

1.4.1  Setup Commands / Hosts / Users

Sudo works by taking applying requested commands to hosts and users and finding a match. For a command to be valid, it needs to be unambiguously resolved for a requesting user. Let’s setup some common commands:

ipa sudocmd-add –desc “For reading log files” /usr/bin/less

ipa sudocmd-add –desc “For editing files” /bin/vi


We won’t apply individual commands to users or hosts…that won’t scale. So we’ll apply commands to sudo “Command Groups”. These can be separated by function (e.g. Apache for httpd access) and also we need to keep in mind that different commands have meaning only on particular Linux flavors (e.g. “service” command isn’t on Ubuntu) or different paths (e.g. “/usr/bin/vim” doesn’t exist on CentOS). For our basic commands we’ll just say they are RHEL-based, so we’ll create a Command Group to apply them to:

ipa sudocmdgroup-add –desc “RHEL-based commands” rhel-commands

ipa sudocmdgroup-add-member –sudocmds /usr/bin/less rhel-commands

ipa sudocmdgroup-add-member –sudocmds /bin/vi rhel-commands


We have a single sudo rule named “rhel-rule” that we can apply to RHEL-based Linux distros. But what are the servers we’ll actually apply them to? We could apply the rule, server by server, but – again – that doesn’t scale to production environment. Instead, we want to create a freeipa hostgroup for our target servers. In our case, we have a standard naming convention so we can build a hostgroup based on the FQDN for the freeipa client node:

ipa hostgroup-add –desc “Infrastructure servers” grp.infrastructure

ipa automember-add –desc “LMIL Infrastructure” –type=hostgroup grp.infrastructure

ipa automember-add-condition –desc “Standard infrastructure node naming” –key=fqdn \

–type=hostgroup –inclusive-regex=”^l[vp]in…..[0-9][0-9][0-9].” grp.infrastructure

A couple of points:

  • We already know that any host added to this hostgroup will be of a RHEL-based Linux distro. Otherwise, we’d have to create different sudo rule types and use different rules in the hostgroup to assign the sudo rule. (True, we haven’t assigned a sudo rule yet, but that will change soon).
  • Any time we add a new host to our freeipa domain, if its FQDN matches the expression above then it will automatically be added to our “grp.infrastructure” set of hosts.
  • While this doesn’t work for hosts already in place (you must add those manually), it’s a nice feature to automate the process of creating new hosts.

The next step is to create the user groups to which we’ll apply our sudo rule.

ipa group-add –desc “Infra admins”

ipa group-add-member –users sa.admin


To add more members, just use the same command.

Now we glue the pieces together so sudo will work:

ipa sudorule-add-allow-command –sudocmdgroups rhel-commands rhel-rule

ipa sudorule-add-host –hostgroups=grp.infrastructure rhel-rule

ipa sudorule-add-user – rhel-rule


With all the basic pieces in place, we can execute a sudo command for a client.


1.4.2  How sudo is Supposed to Work

Setup is straightforward for sssd integration, but we ran into problems. Basically, it should just be a matter of modifying the sssd configuration file:



cache_credentials = True

krb5_store_password_if_offline = True

ipa_domain = hlsdev.local

id_provider = ipa

auth_provider = ipa

access_provider = ipa

ipa_hostname = lvinipacl020.hlsdev.local

chpass_provider = ipa

ipa_server = srv, lvinfripa100.hlsdev.local

ldap_tls_cacert = /etc/ipa/ca.crt



sudo_provider = ldap

ldap_uri = ldap://lvinfripa100.hlsdev.local

ldap_sudo_search_base = ou=sudoers,dc=example,dc=com

ldap_sasl_mech = GSSAPI

ldap_sasl_authid = host/lvinipacl020.hlsdev.local

ldap_sasl_realm = HLSDEV.LOCAL

krb5_server = lvinfripa100.hlsdev.local




services = nss, sudo, pam, ssh

config_file_version = 2

domains = hlsdev.local


Most of the above is already set, but some things must be configured manually. The problem is that sudo does not support sssd as a provider so we need to specify additional settings. Adapt the SUDO_LDAP section to the local machine.

However, when you run a sudo command as a valid user (such as sa.admin included above), it won’t work. It will say that sa.admin is not a user in the sudoers file and that the incident will be reported. If you spend a bunch of time debugging the issue and turn up logging you’ll (eventually) find output similar to the following:


(Mon Dec 1 14:27:27 2014) [sssd[sudo]] [sudosrv_get_sudorules_query_cache] (0x0200): Searching sysdb with [(&(objectClass=sudoRule)(|(sudoUser=ALL)(name=defaults)(sudoUser=sa.abruce)(sudoUser=#249800005)(sudoUser=%ipausers)(*))(&(dataExpireTimestamp<=1417462047)))]

(Mon Dec 1 14:27:27 2014) [sssd[sudo]] [sudosrv_get_rules] (0x2000): About to get sudo rules from cache

(Mon Dec 1 14:27:27 2014) [sssd[sudo]] [sudosrv_get_sudorules_query_cache] (0x0200): Searching sysdb with [(&(objectClass=sudoRule)(|(name=defaults)))]

(Mon Dec 1 14:27:27 2014) [sssd[sudo]] [sudosrv_get_sudorules_from_cache] (0x0400): Returning 0 rules for [<default options>@hlsdev.local]


The last lines indicate that zero records are being returned. Let’s take a look at that query run on the freeipa server:

[root@lvinfripa100 sssd]# ldapsearch -Y GSSAPI ‘(objectClass=sudoRule)’

SASL/GSSAPI authentication started

SASL username: admin@HLSDEV.LOCAL


SASL data security layer installed.

extended LDIF



base <dc=hlsdev,dc=local> (default) with scope subtree

filter: (objectClass=sudoRule)

requesting: ALL



search result

search: 4

result: 0 Success


numResponses: 1


Don’t be fooled by the last lines indicating that “Success” occurred…we got zero records back. It turns out that in the freeipa LDAP schema the records are stored with a different objectClass:

[root@lvinfripa100 sssd]# ldapsearch -Y GSSAPI ‘(objectClass=sudoRole)’

SASL/GSSAPI authentication started

SASL username: admin@HLSDEV.LOCAL


SASL data security layer installed.

extended LDIF



base <dc=hlsdev,dc=local> (default) with scope subtree

filter: (objectClass=sudoRole)

requesting: ALL



rhel-rule, sudoers, hlsdev.local

dn: cn=rhel-rule,ou=sudoers,dc=hlsdev,dc=local

objectClass: sudoRole


sudoHost: +grp.infrastructure

sudoCommand: /usr/bin/less

sudoCommand: /bin/vi

cn: rhel-rule


search result

search: 4

result: 0 Success


numResponses: 2

numEntries: 1


Hmmm, look at that! We get our sudo commands, user groups, and host groups.

According to this is probably a bug in sssd for CentOS. So leave all your configuration just as you have it now, and continue to the next section.

1.4.3  Workaround to Integrate LDAP

The problem above is that sssd is returning zero matching sudo rules from the backing directory server. That isn’t correct, and the workaround is pretty simple:

  1. The freeipa installation already has a legacy “sudo” user that can be used to get sudo rule information. Let’s set the password for it; run this on the freeipa server.

ldappasswd -x -S -W -h $(hostname) -ZZ -D “cn=Directory Manager” \



Be sure to use the exact command above.

  1. Modify the sudo LDAP configuration file:


binddn uid=sudo,cn=sysaccounts,cn=etc,dc=hlsdev,dc=local

bindpw [password]

tls_cacertfile /etc/ipa/ca.crt

uri ldap://lvinfripa100.hlsdev.local

sudoers_base ou=sudoers,dc=hlsdev,dc=local


We’ve shown only the changed files above.

  1. Finally, modify the nsswitch file to indicate that we want to use LDAP before SSSD:


sudoers: files ldap sss


Continue to the next step.

Now we can run a sudo command as one of our domain users and it will work on the CentOS target node.

For the sudo user uid=sudo,cn=sysaccounts,cn=etc,dc=hlsdev,dc=local used password abcd1234!!

1.5     Active Directory Trust Integration


Our goal is to setup a one-way trust between freeipa and AD. However, we will start with the official freeipa guide which uses transitive trusts, but we will adapt to use one-way trust.

Follow these steps:

  1. Recommended freeipa version is 3.3.3; from CentOS repos we get 3.0.0. We will try this version first to keep yum updates simpler.
  2. Setup ipv6, which is required by Samba. We simply need the ipv6 stack enabled; Samba does not require ipv6 addresses:


Disable IPv6

net.ipv6.conf.all.disable_ipv6 = 1

net.ipv6.conf.eth0.disable_ipv6 = 1



sysctl -p


Continue to the next step.

  1. Setup packages for AD install:

yum install -y “ipa-server” “ipa-server-trust-ad” bind bind-dyndb-ldap


Continue to the next step.

  1. Become admin and install the AD trust modules:

ipa-adtrust-install –netbios-name=HLSDEV –no-msdcs -a ‘[2s-password]’


Note that we do not install DNS records as we are using the shared dnsmasq on timmy. To account for this, we have records we must add to DNS to match the AD records already in place:

/etc/dnsmasq.conf on timmy (shared DNS server)









Verify that the required records exist:

[root@lvinfripa100 ~]# nslookup -query=srv << EOL








_ldap._tcp.hlsdev.local      service = 0 100 389 lvinfripa100.hlsdev.local.

[…output cut…]


Verify this information on both sides (freeipa and AD controller). Then continue to the next step.

  1. Establish cross-realm trust. On the freeipa server:

[root@lvinfripa100 ~]# ipa trust-add –type=ad “ad.hlsdev.local” –trust-secret

Shared secret for the trust: [2s password]

Added Active Directory trust for realm “ad.hlsdev.local”

Realm name: ad.hlsdev.local

Domain NetBIOS name: AD

Domain Security Identifier: S-1-5-21-1888062492-1239996146-1891570897

Trust direction: Two-way trust

Trust type: Active Directory domain

Trust status: Waiting for confirmation by remote side


Now on the AD domain controller:

  • Open Active Directory Domains and Trusts (%windir%\system32\domain.msc)
  • Goto Properties for the AD domain, click on Trusts tab, and click New Trust…
  • Follow the wizard; enter the freeipa domain name (hlsdev.local for us), then select “Forest Trust”, “1-way Incoming”, enter the same trust password you used above.
  • At the end you can choose to verify the 1-way incoming trust by entering credentials on the freeipa domain (e.g. admin@hlsdev.local).

Continue to the next step.

  1. Back on the freeipa server, add these lines to Kerberos configuration:




auth_to_local = RULE:1:$1@$0s/@AD.HLSDEV.LOCAL/@ad.hlsdev.local/

auth_to_local = DEFAULT


Then restart services:

service krb5kdc restart

service sssd restart


Continue to the next step.

  1. Now we need to perform mappings from the AD groups to one or more local groups. For now, we’ll just create mappings for all AD “Domain Users” to be a member of a freeipa (POSIX) group.

ipa group-add –desc=’ad.hlsdev.local Users external map’ ad_users_external –external

ipa group-add-member ad_users_external –external ‘AD\Domain Users’


ipa group-add –desc=’ad.hlsdev.local Users’ ad_users

ipa group-add-member ad_users –groups ad_users_external


Continue to the next step.

  1. To verify the process, on the freeipa server and on the client, verify you can create a Kerberos ticket for a service principal from the AD domain. Since we created a mapping for Domain Users, we’ll use a lowly user account “” for this test:

[root@lvinfripa100 sssd]# kinit

Password for [AD password]

[root@lvinfripa100 sssd]# klist

Ticket cache: FILE:/tmp/krb5cc_0

Default principal:


Valid starting     Expires           Service principal

12/02/14 15:28:37 12/03/14 01:28:44 krbtgt/AD.HLSDEV.LOCAL@AD.HLSDEV.LOCAL

       renew until 12/03/14 15:28:37

[root@lvinfripa100 sssd]# id

uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023


Assuming the above works, try logging into a freeipa domain client using SSH as a lowly AD user:

isgmj2chg3qp:rc_scripts n75029$ ssh ‘’@lvinipacl020.hlsdev.local

Warning: Permanently added ‘lvinipacl020.hlsdev.local,’ (RSA) to the list of known hosts.’s password: [AD password]

Last login: Tue Dec 2 14:55:23 2014 from ad.hlsdev.local

-sh-4.1$ ls -la

total 20

drwxr-xr-x. 2 4096 Dec 2 14:55 .

drwx–x–x. 3 root                   root                   4096 Dec 2 14:55 ..

-rw-r–r–. 1   18 Dec 2 14:55 .bash_logout

-rw-r–r–. 1 176 Dec 2 14:55 .bash_profile

-rw-r–r–. 1 124 Dec 2 14:55 .bashrc



All good? Then continue to the next step.

Next step is to verify sudo across domains.

1.6     Sudo Integration with Cross-Domain Trust

Using the Active Directory above as a starting point we will provide sudo privileges based on AD group membership.

  1. Setup a new group in AD “grp.hlsdev-local.infrastructure” and add the low-privilege user to it.
  2. Setup group mappings in freeipa to our “Infrastructure” administrative group. Remember that this is a group which is allowed to run – thus far – the “vi” and the “less” commands J

ipa group-add –desc ‘ad.hlsdev.local Infrastructure admins’ \ –external

ipa group-add-member \

–external ‘AD\grp.hlsdev-local.infrastructure’


In the above, we create an external group on the freeipa side, add the AD group we created above, then add the external group to our existing freeipa SysAdmin Infrastructure group. To verify group membership and sudo rules:

[root@lvinfripa100 bak]# ipa group-show

Group name:

Description: Infra admins

GID: 249800004

Member users: sa.admin, sa.abruce

Member groups:

Member of Sudo rule: rhel-rule


We can see correct setup from the above.

1.7     Original Setup

These were the steps followed in July, 2014 during the initial test.

Follow these steps:

  1. Planning:

Freeipa will run (Kerberos) in conjunction with the existing dnsmasq process. This makes certain things harder (freeipa likes to run everything for you) but will work in our environment better.

Freeipa will not have its own subdomain; we will tie everything into


  1. Prior to installing VM, setup the supporting infrastructure (stuff that Kerberos runs in):

Update timmy: Runs DNS and NTP.

/etc/dnsmasq.hosts on timmy:

  • Hostname entry sadmin-freeipa with the OpenStack-assigned floating IP (168.1.105)
  • Hostname entry to timmy (

/etc/dnsmasq.conf on timmy for Kerberos-required DNS entries as follows:










Note that was added as part of this setup.

Be sure to verify ntpd is running or you will be sad.

Update jimmy: This server runs LDAP.

Verify that plain hostname command returns FQDN. Update /etc/sysconfig/network if necessary.

  1. General OpenStack VM:

Create Security Group to permit TCP/UDP access for the following ports:

  • 88 (kerberos) – UDP / TCP
  • 749 (kerberos-adm) – UDP / TCP
  • 464 (kpasswd) – UDP/TCP
  • 53 (DNS) – UDP/TCP
  • 80/443 – TCP – webserver
  • 9447-9447 – TCP – dogtag PKI
  • For reference, have some shell commands:


export OS_TENANT_NAME=$krb_tenant



nova secgroup-create $krb_rule “Kerberos Rules”

for i in 53 88 749 464; do for j in tcp udp; do

nova secgroup-add-rule $krb_rule $j $i $i

done; done

nova secgroup-add-rule $krb_rule tcp 80 80

nova secgroup-add-rule $krb_rule tcp 443 443

nova secgroup-add-rule $krb_rule tcp 9443 9447

nova add-secgroup $krb_server $krb_rule


Create new VM sadmin-freeipa, which was assigned floating IP Perform following steps:

sudo yum install ntp bind-utils wget links lynx -y


Those last two are for local command-line based web clients if necessary; used them during debug sessions on freeipa setup.


  • Crucial point: Edit /etc/ntp.conf and set the server to point to; comment out others. If clock time is not synchronized to max of 5 minutes skew between participating servers, Kerberos fails.

Use public servers from the project.

Please consider joining the pool (


#server iburst

#server iburst

#server iburst

#server iburst


Set time and auto-start the ntpd daemon:

sudo ntpdate

sudo service ntpd start && sudo chkconfig ntpd on


  • Verify that required DNS records exist:

[cloud-user@sadmin-freeipa ~]$ nslookup -query=srv << EOL






Address: service = 0 100 88


Address: service = 0 100 88


Address: service = 0 100 464


The above queries for several of the SRV records that must exist; note they point to the freeipa VM we are setting up.

  • Setup iptables:

Generated by iptables-save v1.4.7 on Mon Aug 11 20:45:30 2014




:OUTPUT ACCEPT [34:4824]


-A INPUT -p icmp -j ACCEPT

-A INPUT -i lo -j ACCEPT

-A INPUT -p tcp -m state –state NEW -m tcp –dport 80 -j ACCEPT

-A INPUT -p tcp -m state –state NEW -m tcp –dport 443 -j ACCEPT

-A INPUT -p tcp -m state –state NEW -m tcp –dport 9443:9447 -j ACCEPT

-A INPUT -p tcp -m state –state NEW -m tcp –dport 53 -j ACCEPT

-A INPUT -p udp -m state –state NEW -m udp –dport 53 -j ACCEPT

-A INPUT -p tcp -m state –state NEW -m tcp –dport 88 -j ACCEPT

-A INPUT -p udp -m state –state NEW -m udp –dport 88 -j ACCEPT

-A INPUT -p tcp -m state –state NEW -m tcp –dport 749 -j ACCEPT

-A INPUT -p udp -m state –state NEW -m udp –dport 749 -j ACCEPT

-A INPUT -p tcp -m state –state NEW -m tcp –dport 464 -j ACCEPT

-A INPUT -p udp -m state –state NEW -m udp –dport 464 -j ACCEPT

-A INPUT -p tcp -m state –state NEW -m tcp –dport 22 -j ACCEPT

-A INPUT -j REJECT –reject-with icmp-host-prohibited

-A FORWARD -j REJECT –reject-with icmp-host-prohibited


Completed on Mon Aug 11 20:45:30 2014

Reboot / snapshot the VM before continuing.


  1. Preparing to install freeipa. Up to this point the VM is clean and setup for quick restart. Now we get to a point where some significant packages must be installed.
  • Java: We need to install this prior to installing a required pki-symkey

sudo yum install java jpackage-utils jss


  • pki-symkey: the version in EPEL is 1.3.2 while freeipa requires 9.0.3. We get this from the CentOS repository but must have the Java requisite installed first:


sudo rpm -iva pki-symkey-9.0.3-32.el6.x86_64.rpm


  • Verify freeipa will install:

sudo yum install ipa-server


You should be prompted to install, just Ctrl+C.

Reboot / snapshot the VM as now all bits are setup.


  1. Install freeipa. Simply use sudo yum install ipa-server; reboot and snapshot the image.


  1. Now for the patches:

“The IPA Server Hostname cannot be a CNAME, only A and AAAA names are allowed.” – this error is returned because apparently dnsmasq does not play nicely with freeipa. So we edit /usr/lib/python2.6/site-packages/ipaserver/install/, search for AAAA, and comment out that section of code.

Error 404 when configuring CA. The dogtag PKI provided by freeipa fails on step 11 when invoked by pkisilent. So we can create our own That is simply a wrapper for a JAR file so we make sure we can disassemble it. First sudo yum install jdk so you get javap.



Leaving this one alone for now…will return if have time later…


Team-oriented systems mentor with deep knowledge of numerous software methodologies, technologies, languages, and operating systems. Excited about turning emerging technology into working production-ready systems. Focused on moving software teams to a higher level of world-class application development. Specialties:Software analysis and development...Product management through the entire lifecycle...Discrete product integration specialist!

Leave a Reply

Your email address will not be published.


Human Verification: In order to verify that you are a human and not a spam bot, please enter the answer into the following box below based on the instructions contained in the graphic.