Modify INVITE (to CMS Space / CMS Space naming)

I have spent serious time considering how I want to address my spaces within CMS. I’m personally not to happy with the idea to utilize prefix/suffix on the userpart, such as cmr-username, username.vmr – whatever name you want to use, or where you place it. My preferred logic there would be to have the CMS-spaces within a specific subdomain, so – to call a user directly you would dial username@domain.tld and to dial the space of the user you would dial username@meet.domain.tld.

Attempting to apply this logic does however introduce a few issues.

If the username should be used to provision the space – guess what, it will not synchronize that user. That causes a conflict with the adressing of the actual user if you were using the MeetingApp. Reachibility for the MeetingApp is way beyond the scope of this post, we are using devices and/or Jabber and will just use the spaces within CMS.

So, to manage this, I do need to provision the space using a prefix (or suffix), such as cmr-username and rewrite the invite on the way. Where should I do that? It would be very easily done in the VCS, a bit more tricky on the CUCM side – but still doable.

I will not argue that this script is perfect at the moment, but it is a start and can surely be developed further down the road. I’ve also argued heavily with myself if the To-header also should be updated, but it seems to work just fine with only updating the INVITE, so I’m happy with that for now.

The script;

M = {}

local cmrDomain = "meet.domain.tld" 

function M.outbound_INVITE(msg)
  local method, ruri, ver = msg:getRequestLine()
  if string.find(ruri, cmrDomain) then
    startTo_str = string.find(ruri, "sip:")
    endTo_str = string.find(ruri, "@", startTo_str+1)
    toUserPart_str = string.sub(ruri, startTo_str+4, endTo_str-1)
    if not string.sub(toUserPart_str, 0,3):match("cmr-") then
      changedToUserPart_str = "cmr-" .. toUserPart_str
      changedRuri_str = string.gsub(ruri, toUserPart_str, changedToUserPart_str)
      msg:setRequestUri(changedRuri_str)
    end
  end
end

return M

Worth mentioning about the script is the parameter for cmrDomain, without a check to make sure we are only applying this script for the actual domain we’re planning to use here – it would for sure break CUCM integration with regards to AdHoc conferences. (CUCM will create a temporary space, using id@fqdn – we don’t want to interfere there). Also, if you use another naming-convention then cmr-…., pay attention to line 11/12 and modify the code accordingly. There is also a check if cmr- is already present, if so we do not want to add it again.

Also, keep in mind – if you create dedicated spaces, configure them within CMS with the prefix of cmr-, or apply logic to exclude them from the script as well. šŸ™‚

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. šŸ™‚

  

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.

Failed Presence/IM&P upgrade

Attempted CUP/IM&P upgrade from 8.6(4) to 10.5(2)a but ended up with failed refresh upgrade (RU) and system booting back to 8.6.

Investigating install.log shows the following;

03/24/2015 02:13:32 IPM|Internal Error, File:ipm.c:2011, Function: ipmReadNormalizedInputLine(), "/usr/local/cm/script/cm-dbl-install RU PostInstall 10.5.2.20000-1 8.6.4.10000-28 /usr/local/cm/ /common/component/database /common/log/install/capture.txt " failed (1)|<LVL::Critical>
03/23/2015 18:13:34 InstallWizard|Platform Install: view|<LVL::Info>
03/24/2015 02:13:34 IPM| end-of-session "Installing database component": 4387.198 secs.|<LVL::Info>
03/24/2015 02:13:34 IPM|Close progress meter "Component Install"|<LVL::Info>
03/24/2015 02:13:34 component_install|Writing database into /common/log/install/component_failed.xml file.|<LVL::Info>
03/24/2015 02:13:34 component_install|/common/log/install/component_failed.xml created : 0|<LVL::Info>
...
03/24/2015 02:13:34 component_install|File:/opt/cisco/install/bin/component_install:807, Function: exec_progmeter(), /opt/cisco/install/bin/progmeter failed (1)|<LVL::Error>
03/24/2015 02:13:34 appmanager.sh|Internal Error, File:/usr/local/bin/base_scripts/appmanager.sh:273, Function: refresh_upgrade(), failed to refresh_upgrade infrastructure_post components|<LVL::Critical>
03/24/2015 02:13:34 post_install|File:/opt/cisco/install/bin/post_install:961, Function: install_applications(), /usr/local/bin/base_scripts/appmanager.sh -refresh-upgrade failed (1)|<LVL::Error>
03/24/2015 02:13:34 post_install|Exiting with result 1|<LVL::Info>
...
03/24/2015 02:13:38 post_install|_set_upgrade_status_attribute: status set to upgrade.stage.error|<LVL::Debug>
03/24/2015 02:13:38 post_install|File:/opt/cisco/install/bin/post_install:624, Function: handle_refresh_upgrade_failure(), Refresh upgrade failed. Trying to reboot to currently active version.|<LVL::Error>

Investigating syslog/messages on the INACTIVE partition after the RU failure shows multiple avc denials, similar to the following examples;

Mar 23 18:12:01 HOSTNAME kern 6 kernel:SELinux:Ā  Context admin_u:object_r:cli_tmp_t:s0 is not valid (left unmapped).
Mar 23 18:12:01 HOSTNAME kern 5 kernel:type=1400 audit(1427159521.658:796866): avc:Ā  deniedĀ  { getattr } forĀ  pid=1842 comm="installdb" path="/common/log/install/downloaded_versions" dev=sda6 ino=1769674 scontext=system_u:system_r:initrc_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=file
Mar 23 18:12:03 HOSTNAME kern 5 kernel:type=1400 audit(1427159523.390:796867): avc:Ā  deniedĀ  { setattr } forĀ  pid=2085 comm="chown" name="drfuser" dev=sda1 ino=612031 scontext=system_u:system_r:initrc_t:s0 tcontext=unconfined_u:object_r:user_home_dir_t:s0 tclass=dir
Mar 23 18:13:16 HOSTNAME kern 5 kernel:type=1400 audit(1427159596.820:796876): avc:Ā  deniedĀ  { ioctl } forĀ  pid=6070 comm="sftp_connect.sh" path="/home/sftpuser/sftp_connect.sh" dev=sda1 ino=612018 scontext=system_u:system_r:initrc_t:s0 tcontext=system_u:object_r:user_home_dir_t:s0 tclass=file
Mar 23 18:13:26 HOSTNAME kern 5 kernel:type=1400 audit(1427159606.576:796877): avc:Ā  deniedĀ  { remove_name } forĀ  pid=1842 comm="installdb" name="sqlhosts_9BoX7x" dev=sda1 ino=612082 scontext=system_u:system_r:initrc_t:s0 tcontext=system_u:object_r:home_root_t:s0 tclass=dir
Mar 23 18:13:26 HOSTNAME kern 5 kernel:type=1400 audit(1427159606.576:796878): avc:Ā  deniedĀ  { unlink } forĀ  pid=1842 comm="installdb" name="sqlhosts_9BoX7x" dev=sda1 ino=612082 scontext=system_u:system_r:initrc_t:s0 tcontext=system_u:object_r:home_root_t:s0 tclass=file
Mar 23 18:13:26 HOSTNAME kern 5 kernel:type=1400 audit(1427159606.841:796879): avc:Ā  deniedĀ  { getattr } forĀ  pid=6158 comm="cupl2_new.py" path="/common/component/database/cupl2.export" dev=sda6 ino=1000180 scontext=system_u:system_r:initrc_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=dir
Mar 23 18:13:26 HOSTNAME kern 5 kernel:type=1400 audit(1427159606.851:796880): avc:Ā  deniedĀ  { getattr } forĀ  pid=6158 comm="cupl2_new.py" path="/common/component/database/cupl2.export/dependency.txt" dev=sda6 ino=1000181 scontext=system_u:system_r:initrc_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=file
Mar 23 18:13:30 HOSTNAME kern 5 kernel:type=1400 audit(1427159610.036:796881): avc:Ā  deniedĀ  { read } forĀ  pid=6310 comm="installdb" name="dependency.txt" dev=sda6 ino=1000181 scontext=system_u:system_r:initrc_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=file
Mar 23 18:13:30 HOSTNAME kern 5 kernel:type=1400 audit(1427159610.036:796882): avc:Ā  deniedĀ  { open } forĀ  pid=6310 comm="installdb" name="dependency.txt" dev=sda6 ino=1000181 scontext=system_u:system_r:initrc_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=file
Mar 23 18:13:30 HOSTNAME kern 5 kernel:type=1400 audit(1427159610.246:796883): avc:Ā  deniedĀ  { write } forĀ  pid=6333 comm="rm" name="cupl2.export" dev=sda6 ino=1000180 scontext=system_u:system_r:initrc_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=dir
Mar 23 18:13:32 HOSTNAME kern 5 kernel:type=1400 audit(1427159612.023:796889): avc:Ā  deniedĀ  { read } forĀ  pid=6563 comm="cp" name="id_dsa.pub" dev=sda1 ino=612062 scontext=system_u:system_r:initrc_t:s0 tcontext=system_u:object_r:user_home_dir_t:s0 tclass=file
Mar 23 18:13:32 HOSTNAME kern 5 kernel:type=1400 audit(1427159612.023:796890): avc:Ā  deniedĀ  { open } forĀ  pid=6563 comm="cp" name="id_dsa.pub" dev=sda1 ino=612062 scontext=system_u:system_r:initrc_t:s0 tcontext=system_u:object_r:user_home_dir_t:s0 tclass=file
Mar 23 18:13:32 HOSTNAME kern 5 kernel:type=1400 audit(1427159612.023:796891): avc:Ā  deniedĀ  { write } forĀ  pid=6563 comm="cp" name="id_dsa.pub" dev=sda1 ino=612071 scontext=system_u:system_r:initrc_t:s0 tcontext=system_u:object_r:user_home_dir_t:s0 tclass=file
Mar 23 18:13:34 HOSTNAME kern 5 kernel:type=1400 audit(1427159614.949:796893): avc:Ā  deniedĀ  { create } forĀ  pid=8184 comm="sed" name="sedYOAA0s" scontext=system_u:system_r:initrc_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=file
Mar 23 18:13:34 HOSTNAME kern 5 kernel:type=1400 audit(1427159614.949:796894): avc:Ā  deniedĀ  { write } forĀ  pid=8184 comm="sed" name="sedYOAA0s" dev=sda6 ino=1769710 scontext=system_u:system_r:initrc_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=file
Mar 23 18:13:34 HOSTNAME kern 5 kernel:type=1400 audit(1427159614.950:796895): avc:Ā  deniedĀ  { rename } forĀ  pid=8184 comm="sed" name="sedYOAA0s" dev=sda6 ino=1769710 scontext=system_u:system_r:initrc_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=file

Workaround;
This does not seem to be documented, but with the bad feeling from avc denials – applying workaround from similar bugs – CSCul25056 and CSCue18397 did the trick. Boot to a linux-disc and modify grub.conf to include enforcing=0.