Skip to content

Shibboleth, CAS, ADFS Setup

Daniel Anner edited this page Feb 14, 2020 · 1 revision

MunkiReport can be integrated into a SAML solution that uses CAS as a login service, and Active Directory Federation Services in the background with Shibboleth. Below is an example of the configuration at a University.

Configuration - CAS

CAS is a straight-forward setup consisting of any CAS provider.

Configuration - ADFS

Active Directory can be configured as per standards call for, and Shibboleth just needs the proper mapping.

Configuration - Shibboleth

  1. First, add your metadata as provided from MunkiReport in your local metadata folder. Ours exists as {$SHIB_ROOT}/metadata/munkireport-metadata.xml
  2. If using CAS, you need to make sure CAS is a login component of Shibboleth. This is generic configuration.
  3. We have our NameID generation to include the users mail record, followed by other custom ID's that are unique to each user. The file you need to edit for this is {$SHIB_ROOT}/conf/saml-nameid.xml. Ours looks something like this:
<util:list id="shibboleth.SAML2NameIDGenerators">
        <ref bean="shibboleth.SAML2TransientGenerator" />

        <bean parent="shibboleth.SAML2AttributeSourcedGenerator"
              p:format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
              p:attributeSourceIds="#{ {'mail'} }" />

        <bean parent="shibboleth.SAML2AttributeSourcedGenerator"
              p:format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
              p:attributeSourceIds="#{ {'UNIQUE_ID'} }" />
    </util:list>
  1. Setup the ADFS integration in your {$SHIB_ROOT}/conf/relying-party.xml something like the following. For us, it is important that encryptAssertations and encryptNameIDs is set to false.
<bean parent="RelyingPartyByName" c:relyingPartyIds="http://adfs.domain.tld/adfs/services/trust">
    <property name="profileConfigurations">
        <list>
            <bean parent="SAML2.SSO" p:encryptAssertions="false" p:encryptNameIDs="false" />
        </list>
    </property>
</bean>
  1. Setup your metadata providers file {$SHIB_ROOT}/conf/metadata-providers.xml:
  • Remember your id here has to be unique, and persist across the entire configuration
<MetadataProvider id="MunkiReport"
                      xsi:type="FileBackedHTTPMetadataProvider"
                      backingFile="%{idp.home}/metadata/munkireport-metadata.xml"
                      metadataURL="https://munkireport.domain.tld/index.php?/auth/saml/metadata" />
  1. To integrate ADFS we use an LDAP data connector in {$SHIB_ROOT}/conf/attribute-resolver.xml. Remember, SAML integrations vary widely but this is how we have it setup. The configuration URL, DN, and others are set globally:
<resolver:DataConnector id="ADFS" xsi:type="dc:LDAPDirectory"
                            ldapURL="%{idp.attribute.resolver.LDAP.ldapURL}"
                            baseDN="%{idp.attribute.resolver.LDAP.baseDN}"
                            principal="%{idp.attribute.resolver.LDAP.bindDN}"
                            principalCredential="%{idp.attribute.resolver.LDAP.bindDNCredential}"
                            useStartTLS="%{idp.attribute.resolver.LDAP.useStartTLS:true}">
    <dc:FilterTemplate>
        <![CDATA[
            %{idp.attribute.resolver.LDAP.searchFilter}
        ]]>
    </dc:FilterTemplate>
    <dc:ReturnAttributes>%{idp.attribute.resolver.LDAP.returnAttributes}</dc:ReturnAttributes>
    <dc:StartTLSTrustCredential id="LDAPtoIdPCredential" xsi:type="sec:X509ResourceBacked">
        <sec:Certificate>%{idp.attribute.resolver.LDAP.trustCertificates}</sec:Certificate>
    </dc:StartTLSTrustCredential>
</resolver:DataConnector>
  1. (Extra) We also have the following to release the users Email address properly:
<resolver:AttributeDefinition id="mail" xsi:type="ad:Simple" sourceAttributeID="mail">
    <resolver:Dependency ref="ADFS" />
    <resolver:AttributeEncoder xsi:type="enc:SAML1String" name="urn:mace:dir:attribute-def:mail" encodeType="false" />
    <resolver:AttributeEncoder xsi:type="enc:SAML2String" name="urn:oid:0.9.2342.19200300.100.1.3" friendlyName="mail" encodeType="false" />
</resolver:AttributeDefinition>
<resolver:AttributeDefinition id="adfs_mail" xsi:type="ad:Simple" sourceAttributeID="mail">
    <resolver:Dependency ref="mail" />
    <resolver:AttributeEncoder xsi:type="enc:SAML2String" name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" friendlyName="mail" />
</resolver:AttributeDefinition>
  1. Lastly, you need to configure your {$SHIB_ROOT}/conf/attribute-filter.xml
<AttributeFilterPolicy id="MunkiReport">
    <PolicyRequirementRule xsi:type="Requester" value="https://munkireport.domain.tld/index.php?/auth/saml/metadata" />

    <AttributeRule attributeID="mail">
        <PermitValueRule xsi:type="ANY" />
    </AttributeRule>

    <AttributeRule attributeID="memberOf">
        <PermitValueRule xsi:type="ValueRegex" regex="^CN=.*,OU=Munki,OU=Groups,OU=Root,DC={SUBDOMAIN},DC={DOMAIN}$" />
    </AttributeRule>
</AttributeFilterPolicy>

The memberOf is completely different between every setup. Ask your AD administrator what this path would be, if you are unsure. When configuring the memberOf, remember the following:

  • CN is used for Container
  • OU is used for Organizational Unit
  • DC is used for Domain Controller (you may not have a subdomain)
  1. Once you are confident that you setup everything correctly, you can call the reload-service functions delievered with Shibboleth. If you want, you can just restart the entire service and it will reload everything as well. Refer to the Shibbolleth Wiki of reloadable services if you need a full list. This is an example of how we access them, without restarting the machine service:
wget -qSO- http://localhost:8080/idp/profile/admin/reload-service?id=shibboleth.MetadataResolverService

wget -qSO- http://localhost:8080/idp/profile/admin/reload-service?id=shibboleth.AttributeFilterService
  1. When releasing data, the SAML response should include something like the following
<saml2:AttributeStatement>
    <saml2:Attribute FriendlyName="mail" Name="urn:oid:0.9.2342.19200300.100.1.3" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
        <saml2:AttributeValue>mail.address@domain.tld</saml2:AttributeValue>
    </saml2:Attribute>
    <saml2:Attribute FriendlyName="memberOf" Name="http://schemas.xmlsoap.org/claims/Group" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
        <saml2:AttributeValue>CN=MRAdmins,OU=Munki,OU=Groups,OU=Root,DC={SUBDOMAIN},DC={DOMAIN}</saml2:AttributeValue>
    </saml2:Attribute>
</saml2:AttributeStatement>

Configuration - MunkiReport

Here is an example of our MunkiReport .env file. As a note, in the 5.2.0 release, all commas in the memberOf group role are replaced by _. See troubleshooting for more information on this.

AUTHORIZATION_DELETE_MACHINE="admin, manager"
AUTHORIZATION_GLOBAL="admin, manager, user"
ROLES_ADMIN="administrator, data_api, @CN=MRAdmins_OU=Munki_OU=Groups_OU=Root_DC={SUBDOMAIN}_DC={DOMAIN}"
ROLES_MANAGER="@CN=MRManagers_OU=Munki_OU=Groups_OU=Root_DC={SUBDOMAIN}_DC={DOMAIN}"
AUTH_SECURE="TRUE"

AUTH_METHODS="SAML"
AUTH_SAML_DEBUG="FALSE"
AUTH_SAML_SP_NAME_ID_FORMAT=urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
AUTH_SAML_IDP_ENTITY_ID=https://cas.domain.tld/idp/shibboleth
AUTH_SAML_IDP_SSO_URL=https://cas.domain.tld/idp/profile/SAML2/Redirect/SSO
AUTH_SAML_IDP_SLO_URL=https://cas.domain.tld/idp/profile/SAML2/Redirect/SLO
AUTH_SAML_IDP_X509CERT={YOUR_CERT - can be found in the SAML response}

AUTH_SAML_USER_ATTR=urn:oid:0.9.2342.19200300.100.1.3
AUTH_SAML_ALLOWED_USERS=""
AUTH_SAML_GROUP_ATTR="http://schemas.xmlsoap.org/claims/Group"
AUTH_SAML_ALLOWED_GROUPS="CN=MRAdmins_OU=Munki_OU=Groups_OU=Root_DC={SUBDOMAIN}_DC={DOMAIN}, CN=MRManagers_OU=Munki_OU=Groups_OU=Root_DC={SUBDOMAIN}_DC={DOMAIN}, CN=MRUsers_OU=Munki_OU=Groups_OU=Root_DC={SUBDOMAIN}_DC={DOMAIN}"

Once you have the SAML config setup, you should be able to access MunkiReport (as long as you are in the proper group).

Troubleshooting SAML

The first thing you should do, is decode the SAML response and make sure the data sent to MunkiReport is correct. To do this:

  1. In a Chrome Incognito Window, open developer tools.
    1. Navigate to the Network Tab
  2. In the URL bar, go to your MunkiReport URL which should redirect you to your authentication portal.
    1. Login to your SSO account
  3. After successfully logging in, it should redirect you back to MunkiReport.
    1. Look in the network tab, find the item Request URL: index.php?/auth/saml/acs
    2. At the bottom of the details pane, you should see a SAMLResponse
    3. Copy that data to a SAML decoder, there are plenty of decoders on Google or you can find an offline one as well. As always, be careful putting sensitive data into a webpage.
    4. In the decoded data, look for the <saml2:AttributeStatement> and make sure both your UID (mail) and memberOf is defined. In SAML configuration, under #9 there is an example of a proper response.
  4. If all of the data is correct, continue to the steps below for Troubleshooting MunkiReport; Otherwise open a ticket on the Google Groups page and someone will try to assist you.

Troubleshooting MunkiReport

Sometimes the issue is as simple as a misconfiguration in MunkiReport. To easily know if your configuration is correct, do the following:

  1. Add your mail/unique ID to the AUTH_SAML_ALLOWED_USERS config in your .env
  2. After logging in successfully, change your URL to https://munkireport.domain.tld/index.php?/auth/set_session_props/1
    1. This will show you your session variables. Check your samlUserData and verify it matches what is in your config.
    {
        "samlUserdata": {
            "urn:oid:0.9.2342.19200300.100.1.3": [ "your.email@domain.tld" ],
            "http:\/\/schemas.xmlsoap.org\/claims\/Group": [
                "CN=MRAdmins,OU=Munki,OU=Groups,OU=Root,DC={SUBDOMAIN},DC={DOMAIN}"
            ]
        },
        "samlNameId": "your.email@domain.tld",
        "samlNameIdFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
        "samlSessionIndex": "_cb75c406d54c9ad12ee6072abb946aed",
        "user": "your.email@domain.tld",
        "groups": [ "CN=MRAdmins_OU=Munki_OU=Groups_OU=Root_DC={SUBDOMAIN}_DC={DOMAIN}" ],
        "auth": "saml",
        "role": "admin",
        "role_why": "member of @CN=MRAdmins_OU=Munki_OU=Groups_OU=Root_DC={SUBDOMAIN}_DC={DOMAIN}",
        "machine_groups": { "0": "1", "1": "3", "2": "4", "4": "2", "7": "5" },
        "initialized": true,
        "theme": "Default"
    }
    1. Use the groups object as your config string.
  3. If you are still having issues, open a ticket on the Google Groups page and someone will try to assist you. Please provide all troubleshooting details explained here.
Clone this wiki locally