Posted on 03-25-2014 06:18 AM
I have a web application that uses Java 7 and wanted to get it 'pre-approved' - which used to be easy with Apple's Java 6 as the certificates were originally distributed with MCX back in the day (which would now be done into the system keystore via Casper certificate distribution).
But I don't think there's a way to do this for Java 7 is there? I was feeling very pleased when I found the 'system' certificate store at
/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/security/trusted.certs
and have got myself as far as importing a cert with keytool
keytool -importcert -noprompt -file mynewcert -keystore trusted.certs
But that requires an inline interactive password setting. Is there a better way of going around doing this. It's a lot of work when I could just e-mail everyone saying "when it comes up the first time tick the OK, and don't ask again" and that will put it in their user home (~/Application Support/Oracle/Java/Deployment/security/trusted.certs)
Solved! Go to Solution.
Posted on 03-25-2014 07:05 AM
This is the command that we have been trying; it accepts the command, but Java doesn't actually show our imported certs in the keystore GUI:
/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/bin/keytool -importcert -keystore /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/security/cacerts -storepass changeit -alias YOURALIAS -noprompt -file /path/to/your/cert.cer
I haven't tried importing into 'trusted.certs' but maybe that also uses the default '-storepass changeit' I don't know if that helps at all in your case, but it's worth a shot. The documentation on enterprise management of the OS X Java 7 client is pretty weak. We've had to riff off of the Windows documentation for most of our implementation.
Posted on 03-25-2014 07:05 AM
This is the command that we have been trying; it accepts the command, but Java doesn't actually show our imported certs in the keystore GUI:
/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/bin/keytool -importcert -keystore /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/security/cacerts -storepass changeit -alias YOURALIAS -noprompt -file /path/to/your/cert.cer
I haven't tried importing into 'trusted.certs' but maybe that also uses the default '-storepass changeit' I don't know if that helps at all in your case, but it's worth a shot. The documentation on enterprise management of the OS X Java 7 client is pretty weak. We've had to riff off of the Windows documentation for most of our implementation.
Posted on 03-25-2014 07:59 AM
STOREPASS - thank you, that did it. staring me in the face in the -help command there. I think that did it.
(Oddly it looks like the java 7 install we have is confined to the Library/Internet Plug-Ins/JavaAppletPlugin.plugin and there's nothing in /Library/Java/JavaVirtualMachines)
Posted on 03-25-2014 09:07 AM
That answered my immediate issue - but annoyingly though I now have a deployment-ready way to get the certificate into the java 7 'system keystore' it still prompts the user and after approving it manually you end up with the same certitifcate in both user and system pane :-(
Posted on 03-25-2014 10:57 AM
I wrote this quick and dirty Python script for handling this problem. It assumes that the certificate you want to add to the user's trusted.certs keystore exists in /private/tmp.
#!/usr/bin/env python
'''
This script allows you to import a certificate into
the Oracle Java trusted.certs keystore.
Created by James Barclay on 2014-03-10.
'''
from __future__ import print_function
import os
import plistlib
import subprocess
import sys
# Constants
ALIAS = 'your_alias'
INTERNET_PLUGINS = '/Library/Internet Plug-Ins'
JAVA_CERT = '/private/tmp/your_cert.cer'
JAVA_WEB_PLUGIN = os.path.join(INTERNET_PLUGINS, 'JavaAppletPlugin.plugin')
def get_console_user():
'''Returns the currently logged-in user as
a string, even if running as EUID root.'''
if os.geteuid() == 0:
console_user = subprocess.check_output(['/usr/bin/stat',
'-f%Su',
'/dev/console']).strip()
else:
import getpass
console_user = getpass.getuser()
return console_user
def determine_java_vendor(info_plist):
'''Determine Java vendor. Takes the path to
a Java Info.plist file and returns a string
of the Java vendor's name.'''
java_vendor = None
try:
pl = plistlib.readPlist(info_plist)
java_vendor = pl['CFBundleIdentifier'].split('.')[1]
except KeyError:
print('CFBundleIdentifer does not exist in %s.' % info_plist)
except IOError:
print('%s does not exist!' % info_plist)
return java_vendor
def get_keytool_path(java_vendor):
'''Returns the path to the keytool command-
line utility.'''
keytool_path = None
if java_vendor == 'oracle':
keytool_path = os.path.join(JAVA_WEB_PLUGIN, 'Contents/Home/bin/keytool')
elif java_vendor == 'apple':
keytool_path = '/usr/bin/keytool'
return keytool_path
def cert_in_keystore(keytool, keystore, store_pass, alias):
'''Returns True if the specified certificate
alias exists in the specified keystore.'''
try:
if os.path.exists(keystore):
rc = subprocess.check_call([keytool,
'-list',
'-keystore',
keystore,
'-storepass',
store_pass,
'-alias',
alias])
if rc == 0:
return True
except subprocess.CalledProcessError, e:
print('An error occurred when attempting to locate alias '%s' in %s. Probably ok. Error: %s' % (alias, keystore, e))
def add_cert_to_java_trusted_certs(keytool, store_pass, cert, keystore):
'''Adds the specified certificate to the specified
Java cacerts keystore.'''
try:
subprocess.check_output([keytool,
'-import',
'-v',
'-noprompt',
'-storepass',
store_pass,
'-alias',
ALIAS,
'-keystore',
keystore,
'-trustcacerts',
'-file',
cert])
except subprocess.CalledProcessError, e:
print('An error occurred when attempting to add %s to %s. Error: %s.' % (cert, keystore, e))
def main():
real_java_path = os.path.realpath(JAVA_WEB_PLUGIN)
java_info_plist = os.path.join(real_java_path, 'Contents/Info.plist')
java_vendor = determine_java_vendor(java_info_plist)
trusted_certs = '/Users/%s/Library/Application Support/Oracle/Java/Deployment/security/trusted.certs' % get_console_user()
keytool = os.path.join(JAVA_WEB_PLUGIN, 'Contents/Home/bin/keytool')
if not os.path.isfile(keytool):
keytool = '/usr/bin/keytool'
store_pass = ''
if not os.path.isfile(trusted_certs):
store_pass = 'changeit'
if os.path.exists(JAVA_CERT):
if java_vendor == 'oracle':
if cert_in_keystore(keytool, trusted_certs, store_pass, ALIAS):
print('%s already exists in %s. Exiting now.' % (ALIAS, trusted_certs))
sys.exit(1)
else:
print('Using %s to add %s to %s.' % (keytool, JAVA_CERT, trusted_certs))
add_cert_to_java_trusted_certs(keytool, store_pass, JAVA_CERT, trusted_certs)
elif java_vendor == 'apple':
print('Unable to add certificate to trusted.certs. Modify com.apple.java.security.plist instead.')
sys.exit(1)
else:
print('Unable to continue. Unknown Java vendor: %s.' % java_vendor)
sys.exit(1)
else:
print('%s does not exist! Exiting now.' % JAVA_CERT)
sys.exit(1)
if __name__ == '__main__':
main()
Posted on 03-25-2014 12:55 PM
Huh, I haven't tried setting it via the internet plug-ins path. I'll try that and see if it solves my problem. That's frustrating that it got you a little closer but still ends up with users getting prompted. JAVA!!!!
Posted on 03-26-2014 01:58 AM
@alan.trewartha: the JRE is contained in the Internet plug-in. Jason references the JDK.
We import into /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/security/cacerts btw.
Posted on 03-26-2014 03:32 AM
Thanks for clearing that up for me, and i'll try the cacerts file instead
Posted on 03-26-2014 04:16 AM
I got it into the cacerts file - it appears listed as both "Signer CA" and "Secure Site CA". But amazingly I still get prompted to go through manually adding it in the 'user realm' and end up with it there under "Trusted certificates" too.
For anyone playing along at home, the "cacert" file has a default password of "changeit" (or "changeme" on some earlier versions) (which jason already mentioned! d'oh)
Posted on 03-26-2014 06:40 AM
Ok, so I adjust my command to the following and it is working everywhere I need it:
sudo /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/keytool -importcert -keystore /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/security/cacerts -storepass changeit -alias YOURALIAS -noprompt -file /path/to/your/cert.cer
We are also utilizing the DeploymentRuleSet.jar which allows us to whitelist websites, which might be something you need to stop getting that prompt.
Here are the instructions we followed for how to create the whitelist):
http://kylebubp.com/2013/11/use-java-whitelisting-to-further-secure-your-organization/
The only thing that we did differently from this document was placing the DeploymentRuleSet.jar in /Library/Application Support/Oracle/Java/Deployment/ instead of /etc/.java/deployment/
Posted on 03-28-2014 09:07 AM
I thought I'd give that new style whitelist JAR a shot, but I got a bit unstuck at the jar signing. looks like it would give us good control of this sort of thing - as would importing it properly into the system certs properly if I understood what I was doing and could spot what I was doing wrong in the first place!