Skip to main content

iOS 7.1 Enterprise Distribution

Tags

iOS 7.1

On March 10th Apple released iOS 7.1.  A pretty nice update suite to the already impressive iOS 7.  iOS 7.1 contained many new UI/UX enhancements to the keyboard and automatic HDR for iPhone 5s.  One of the more impressive new features was the brand new user experience for iOS now in your car, entitled CarPlay.  In automobiles that are now compatible, there will be an iOS experience for your car.

 Along with all of the new features to 7.1 came a big package of security patches, which are not displayed on the same page as the new features, but rather a very obscure sub-page as to not spook anyone in seeing that there were more security features released in iOS 7.1 than new features.  Check out the full list here: http://support.apple.com/kb/HT6162.

One of the new security fixes that caught my eye right away was the patch that required Apple developers to distribute all Enterprise applications over the air using a secure socket layer, or an SSL certificate.  This means that my whole method of deployment has to be revaluated and changed to now accept SSL traffic.

To accomplish this I booted up a small CentOS cloud instance through RackSpace.  Once booted up I did some general maintenance on the server and loaded Apache and mod_ssl on my server.

#update your packages 
sudo yum update
 
#install Apache and mod_ssl
sudo yum install httpd mod_ssl

Next I needed to create a certificate signing request file, or CSR file, for my server. The CSR file is used to create your SSL certificate because it contains encrypted information about your company and is often requested when you apply for a certificate. To generate my CSR file through the terminal, I logged into my server as root and ran the following command from the root folder below. 

This command prompted me for a lot of information about my company and about my location. It is important to note, that when you come to the portion about your “common name,” enter a fully qualified domain name, for example, domain-name.com or domain-name.subdomain.com. After I was finished with my questions about m CSR file I was presented with two files, server-name.key and server-name.csr. I opened up server-name.csr with nano and copied the contents to a text document for later.

openssl req -new -newkey rsa:2048 -nodes -keyout server-name.key -out server-name.csr

Next thing I needed to do is actually get my hands on an SSL certificate, so I headed over to DigiCert and started the application process. During the application process I was able to expedite my application by having my copied text from the CSR file ready to paste into one of the form fields. After I completed the form and paid for the SSL, DigiCert called me on the phone and verified my existence so they could email me my SSL certificate. I took the certificate files Digicert sent me and using the root user, FTP’d the certificate files to the root folder alongside the server-name.key and the server-name.csr file.

After my certificate files were in place I needed to do some configuration on Apache to accept traffic from port 443. So I opened up my Apache configuration file and setup a new virtual host.

#open Apache’s config file
sudo nano /etc/httpd/conf/httpd.conf
 
#add this to the bottom of your config file
NameVirtualHost *:443
 
<VirtualHost *:443 >
    DocumentRoot /var/www/html/enterprise
    ServerName domain-name.com
    <Directory /var/www/html/enterprise >
        DirectoryIndex download.html
    </Directory >
 
    SSLEngine on
    SSLProtocol all -SSLv2
    SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM
 
    SSLCertificateFile /root/domain_name_com.crt
    SSLCertificateKeyFile /root/server-name.key
    SSLCertificateChainFile /root/DigiCertCA.crt
</VirtualHost >

Restart Apache and ensure the changes took effect.

#restart apache
sudo httpd restart
 
#check apaches status to ensure that it is running
sudo httpd status 

Next I created a user for the exposed Apache folder /var/www/html, and gave this new user read and write permissions to this folder. Using my newly created user, I logged into my server with an FTP client and created the directory “enterprise.” In the directory enterprise, I added the following documents: download.html, manifest.plist, my-app.ipa, and icon@2x.png.

Here is an example of download.html:

<html>
 <head>
  <title>Download your App>
 </head>
 <body>
   <h1> <a href="itms-services://?action=download-manifest&url=https://domain-name.com/manifest.plist">Download App</a> </h1>
 </body>
</html>

Here is an example of manifest.plist

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
   <key>items</key>
   <array>
       <dict>
           <key>assets</key>
           <array>
               <dict>
                   <key>kind</key>
                   <string>software-package</string>
                   <key>url</key>
                   <string>https://domain-name.com/my-app.ipa</string>
               </dict>
               <dict>
                   <key>kind</key>
                   <string>display-image</string>
                   <key>url</key>
                   <string>https://domain-name.com/icon@2x.png</string>
               </dict>
           </array><key>metadata</key>
           <dict>
               <key>bundle-identifier</key>
               <string>com.dev.app</string>
               <key>bundle-version</key>
               <string>1.0</string>
               <key>kind</key>
               <string>software</string>
               <key>title</key>
               <string>App Title</string>
           </dict>
       </dict>
   </array>
</dict>
</plist>

That is it, after I hooked up my domain to Apache I was able to start serving my Enterprise Applications over the air using an SSL. At this point I was able to navigate out to the https://domain-name.com with my iPad and download and install my-app.ipa to my iPad. Let me know if anyone has any questions.

Member for

3 years 9 months
Matt Eaton

Long time mobile team lead with a love for network engineering, security, IoT, oss, writing, wireless, and mobile.  Avid runner and determined health nut living in the greater Chicagoland area.

Comments

Donald

Mon, 09/29/2014 - 08:29 AM

Matt,
We did the same for our in house distribution but what I can't find is how to force the app to check if the latest version is installed and either alert the user or disallow use until they download the latest version. I'm not looking to push the updates via MDM but rather to have the app check against the server version on startup.

Hello Donald,

This situation is tough. This may not be the perfect solution, but what I have done in the past to remedy this issue is when the application comes back into focus from the background, meaning the app is opened again, I make a network call to the server where my data for the application is stored to see if there is an updated version. You will be able to see if there is an updated version because you should be able to keep the file header in memory and the file headers should have a time stamp on them. If the time stamp is different, alert the user a new version is available and that they should go download it.

Hope that helps!

Julie Elangwey

Mon, 03/21/2016 - 12:00 PM

The 7.1 update forced all software installation services to use the HTTPS protocol, also covering non-standard itms-services:// URLs. How to Fix 'Certificate is not valid' Error for Enterprise Apps on iOS 7.1