Collaboration SSO

After configuring SSO in our internal Collaboration-environment, a few things to remember;

Cross-check time-sync (!!!). It costed me quite some time in troubleshooting when expecting that the AD was synchronized. Don’t do that. Seriously.

Be careful with the Claim Rules. The documentation may be misleading in terms of the namequalifier, probably due to versioning differences between ADFS 2 and 3.

Claim Rules should consist of the following;
1.) Send LDAP Attributes as Claims, store Active Directory and map SAM-Account-Name to uid.
2.) Send Claims Using a Custom Rule, paste the following;

c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"] => issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType, Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"] = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient", Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/namequalifier"] = "Note1*", Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/spnamequalifier"] = "Note2*");

Note1) EntityID of the ADFS (pull from entityID in FederationMetaData.xml, i.e. http://fqdn/adfs/services/trust for ADFS 3.0)
Note2) EntityID of the Collaboration-host (pull from entityID in SPMetadata_fqdn.xml, i.e. fqdn)
…also, be careful with linebreaks when copying the custom rule, it should just be one line.

If needed to debug, the option to modify log-level for SAML is missing in CCMService. Use CLI-command to change level;

admin:set samltrace level DEBUG

Thanks to CSCul45929 for pointing this out.

Next step will be to convince our Netscaler to become an ADFS-proxy and deploy this to the Expressway as well. šŸ™‚

  

NeTS failure on call from Jabber Softphone

NeTS version 5.8.2.9 will not accept calls from Jabber in softphone-mode. Failure from NeTS is a bit cryptic;

|SIP           |SipNclaHandler::ExtractCallInfo          |D0828412 |<-- EXITING METHOD THROUGH NICEEXCEPTION:NICEEXCEPTION: 0XFFFFE052 INVALID SIP ADDRESS, SIPADDRESS=  ||SipNclaHandler.cpp|388
|SIP           |.x1_D0828412-csmState::UpdateContextFrom |         |<-- EXITING METHOD THROUGH NICEEXCEPTION:NICEEXCEPTION: 0XFFFFE052 INVALID SIP ADDRESS, SIPADDRESS=  ||SIPCallCtrlSM.cpp|947
|SIP           |csmsuper::HandleEvent                    |         |CAUGHT EXCEPTION HANDLING SIPREQUEST. NICEEXCEPTION: 0XFFFFE052 INVALID SIP ADDRESS, SIPADDRESS= ||SIPCallCtrlSM.cpp|585
|SIP           |TrProcessSipProviderMessage              |         |_COM_ERROR: _COM_ERROR: HRESULT: 0X80004003(INVALID POINTER  ), INVALID POINTER,  ||TrProcessSipProviderMessage.cpp|85

When comparing the SIP INVITE from a Jabber softphone and a 9951, the following difference was encountered in the header;

Contact: <sip:7009@10.x.y.z:5060;transport=tcp>;video;audio;+u.sip!devicename.ccm.cisco.com="CSFMLUNDBOM";bfcp

The INVITE from the 9951 had only;

Contact: <sip:7009@10.x.y.z:5060;transport=tcp>;video;audio

Most likely, the +-sign is not interpreted correctly. The easy workaround here is to utilize the SIP-normalization rules and clean up the Contact-header (I can’t see any cases where this information would be relevant for NeTS).

Within CCMAdmin, go to Device, Device Settings and SIP Normalization Script. Click Add New. Give it a name, description and enter the following in Content;

M = {}
 
function M.outbound_INVITE(msg)
    local contact = msg:getHeader("Contact")
    local uri = string.match(contact, "(<.+>)")
    msg:modifyHeader("Contact", uri)
end

return M

Apply the script to your SIP-trunk heading to NeTS;

Capture

..and reset the trunk.

The result here is that regardless what extra flags is present in your Contact-header, only the content included within <> is sent over the trunk.

With this workaround, NeTS accepted the Jabber calls without issues.

Managed File Transfer in IM&P

From getting MFT to work in IM&P and Jabber, I’ve discoveredĀ that it is really important to configure everything in the right order.

DO have the database completely configured before attempting to perform the configuration within cupadmin (See my previous blog-post for notes on Oracle-configuration).

Prepare the file-server (I’m using the same Linux-host that I have for receiving backups, hosting ISOs for upgrade, etc).

Make sure that RSAAuthentication and PubkeyAuthentication is enabled in /etc/ssh/sshd_config. Prepare a user / directory as follows;

[root@HOSTNAME mlundbom]# useradd -m chatfile
[root@HOSTNAME mlundbom]# passwd chatfile
Changing password for user chatfile.
New password: 
Retype new password: 
passwd: all authentication tokens updated successfully.
[root@HOSTNAME mlundbom]# mkdir -p /home/mftFileStore/
[root@HOSTNAME mlundbom]# chown chatfile:chatfile /home/mftFileStore/
[root@HOSTNAME mlundbom]# chmod 700 /home/mftFileStore/
[root@HOSTNAME mlundbom]# su chatfile
[chatfile@HOSTNAME mlundbom]$ mkdir ~/.ssh/
[chatfile@HOSTNAME mlundbom]$ touch ~/.ssh/authorized_keys
[chatfile@HOSTNAME mlundbom]$ chmod 700 ~chatfile
[chatfile@HOSTNAME mlundbom]$ chmod 700 ~/.ssh
[chatfile@HOSTNAME mlundbom]$ chmod 700 ~/.ssh/authorized_keys
[chatfile@HOSTNAME mlundbom]$ mkdir /home/mftFileStore/IMPHOSTNAME
[chatfile@HOSTNAME mlundbom]$ exit
[root@HOSTNAME mlundbom]# ssh-keyscan -t rsa hostname.domain.tld
# hostname.domain.tld SSH-2.0-OpenSSH_6.6.1
hostname.domain.tld ssh-rsa RSA-KEY

Copy the output from the last italic line and head to cupadmin, Messaging, External Server Setup and External File Servers. Click Add New, give the record a name, enter the host/fqdn (be careful here that the format matches the RSA-key) and paste the output from ssh-keyscan;

Capture

After saving, continue to Messaging, External Server Setup and External Databases. Click Add New, and be careful to enter the correct information here – the Database nameĀ must match with the configured service name on the database server;

Capture

Once this has been saved, head to Messaging and select File Transfer. Select Managed File Transfer, select your servers and save.

Capture

Click the link for Public Key and copy the contents of the text-box within the popup. Do NOT continue with any other steps regarding IM&P right now, but head back to your fileserver. Edit ~/.ssh/authorized_keys for the configured user (using whatever editor, I’ve heard that there areĀ others then vi, but I refuse to believe it šŸ™‚ ), paste the contents from your clipboard, save the file and go back to cupadmin.

Within cupadmin, by now you should’ve received a notification stating that the XCP Router requires a restart. Proceed with that restart (handy link from within the notification) and when XCP Router is up again, go ahead and try to activate/start Cisco XCP File Transfer Manager.

Pay attention to the service status for Cisco XCP File Transfer Manager, it might attempt a few starts and then end up in “not running”. IĀ poked around a bit with the associations, and everytime you update the server assignment, a new public key gets generated. From the CLI, use

file view activelog epas/trace/xcp/log/AFTStartup.log

to find potential issues. If that log ends up with;

AFT - Passwordless SSH has not been set up correctly. Exiting

…then you have the wrong public key in ~/.ssh/authorized_keys.

If the service starts (and stays running) as expected, head back to cupadmin, Messaging, External Server Setup and External Databases (and External File Servers) and select your file transfer database/server, if everything looks good – you should see the following;

Capture

Capture

Once everything is green, go ahead and restart your Jabber clients. Try to send a file, and you should see the following in your conversation;

Capture

What I really, really like here is that file transfers can be performed with clients that are connecting via MRA.

Notes for Oracle as External database in IM&P

For a while I’ve been running an Oracle XE as my external database for chat persistence and message archiving. Trying to remember how to add an additional database when it was time configure Managed File Transfer was a pain for sure. Hopefully these notes will help me the next time!

[oracle@HOSTNAME ~]$ sqlplus / AS SYSDBA
SQL*Plus: Release 11.2.0.2.0 Production on Mon Jul 6 13:37:44 2015

Copyright (c) 1982, 2011, Oracle.Ā  All rights reserved.
Connected to:
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production

SQL> CREATE TABLESPACE DB_CHATFILE DATAFILE '/u01/app/oracle/oradata/XE/db_chatfile.dbf' SIZE 100M
Ā Ā 2 Ā AUTOEXTEND ON NEXT 1M MAXSIZE UNLIMITED LOGGING EXTENT MANAGEMENT
  3  LOCAL SEGMENT SPACE MANAGEMENT AUTO;

Tablespace created.

SQL> CREATE USER CHATFILE IDENTIFIED BY "pAsSw0rd" DEFAULT TABLESPACE db_chatfile TEMPORARY
  2  TABLESPACE "TEMP" QUOTA UNLIMITED ON db_chatfile ACCOUNT UNLOCK;

User created.

SQL> GRANT DBA TO CHATFILE;

Grant succeeded.

SQL> ALTER SYSTEM SET service_names='XE, CHATCOMP, CHATPERS, CHATFILE';

System altered.

SQL> exit
Disconnected from Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
[oracle@HOSTNAME dbs]$ exit

Once configured, verify that the newly configured database show up using lsnrctl;

[root@HOSTNAME bin]# lsnrctl status

LSNRCTL for Linux: Version 11.2.0.2.0 - Production on 06-JUL-2015 13:42:07

Copyright (c) 1991, 2011, Oracle.  All rights reserved.

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC_FOR_XE)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 11.2.0.2.0 - Production
Start Date                06-JUL-2015 13:29:24
Uptime                    0 days 0 hr. 12 min. 43 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Default Service           XE
Listener Parameter File   /u01/app/oracle/product/11.2.0/xe/network/admin/listener.ora
Listener Log File         /u01/app/oracle/product/11.2.0/xe/log/diag/tnslsnr/HOSTNAME/.../log.xml
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC_FOR_XE)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=FQDN)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=FQDN)(PORT=8080))(Presentation=HTTP)(Session=RAW))
Services Summary...
Service "CHATCOMP" has 1 instance(s).
  Instance "XE", status READY, has 1 handler(s) for this service...
Service "CHATFILE" has 1 instance(s).
  Instance "XE", status READY, has 1 handler(s) for this service...
Service "CHATPERS" has 1 instance(s).
  Instance "XE", status READY, has 1 handler(s) for this service...
Service "PLSExtProc" has 1 instance(s).
  Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service...
Service "XE" has 1 instance(s).
  Instance "XE", status READY, has 1 handler(s) for this service...
Service "XEXDB" has 1 instance(s).
  Instance "XE", status READY, has 1 handler(s) for this service...
The command completed successfully
[root@HOSTNAME bin]#

The Cisco documentation does mention that it should be possible with a more restrictive grant, but that is something I’ll leave for another day to verify.

Enterprise Groups in Jabber

I just configured the Enterprise Groups for Cisco Unified Communications Manager.

I attempted to keep my original agreement for Users and added a second agreement for Groups to align with my directory structure;

Capture
(one existing agreement for ou=Users,ou=XX,ou=YY,dc=domain,dc=tld and one added for ou=Groups,ou=XX,ou=YY,dc=domain,dc=tld)

When running the synchronizations, the groups were added to CUCM as expected and it become possible to add them in the Jabber client. The groups were however empty! I made a few attempts with manually running both of my sync agreements without any success – the groups stayed empty.

Reconfigured the synchronization to start at one higher level in our directory (ou=XX,ou=YY,dc=domain,dc=tld), fetching users and groups within the same agreement, and it worked as a charm! (Be careful here though, you might end up with more users that you’re not expecting – depending on your AD-layout and previous filters in place).

The result; (with actual members in the groups) šŸ˜‰

Capture

As an additionalĀ note, remember that there are currently no search feature from within Jabber for the group, you will have to know the exact name of the group, and it is case sensitive. Add the groups from File, New, Directory Group.