001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *      http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.apache.oozie.util;
020
021import java.util.HashMap;
022import java.util.Map;
023import javax.security.auth.login.AppConfigurationEntry;
024import javax.security.auth.login.Configuration;
025
026
027/**
028 * Creates a programmatic version of a jaas.conf file.  This can be used instead of writing a jaas.conf file and setting
029 * the system property, "java.security.auth.login.config", to point to that file.  It is meant to be used for connecting to
030 * ZooKeeper.
031 * <p>
032 * example usage:
033 * JaasConfiguration.addEntry("Client", principal, keytabFile);
034 * javax.security.auth.login.Configuration.setConfiguration(JaasConfiguration.getInstance());
035 */
036public class JaasConfiguration extends Configuration {
037    private static Map<String, AppConfigurationEntry> entries = new HashMap<String, AppConfigurationEntry>();
038    private static JaasConfiguration me = null;
039    private static final String krb5LoginModuleName;
040
041    static  {
042        if (System.getProperty("java.vendor").contains("IBM")) {
043            krb5LoginModuleName = "com.ibm.security.auth.module.Krb5LoginModule";
044        }
045        else {
046            krb5LoginModuleName = "com.sun.security.auth.module.Krb5LoginModule";
047        }
048    }
049
050    private JaasConfiguration() {
051        // don't need to do anything here but we want to make it private
052    }
053
054    /**
055     * Return the singleton.  You'd typically use it only to do this:
056     * <p>
057     * javax.security.auth.login.Configuration.setConfiguration(JaasConfiguration.getInstance());
058     *
059     * @return
060     */
061    public static Configuration getInstance() {
062        if (me == null) {
063            me = new JaasConfiguration();
064        }
065        return me;
066    }
067
068    /**
069     * Add an entry to the jaas configuration with the passed in name, principal, and keytab.  The other necessary options will be
070     * set for you.
071     *
072     * @param name The name of the entry (e.g. "Client")
073     * @param principal The principal of the user
074     * @param keytab The location of the keytab
075     */
076    public static void addEntry(String name, String principal, String keytab) {
077        Map<String, String> options = new HashMap<String, String>();
078        options.put("principal", principal);
079        if (System.getProperty("java.vendor").contains("IBM")) {
080            // IBM JAVA's UseKeytab covers both keyTab and useKeyTab options
081            options.put("useKeytab",keytab.startsWith("file://") ? keytab : "file://" + keytab);
082
083            // Both "initiator" and "acceptor"
084            options.put("credsType", "both");
085        } else {
086            options.put("keyTab", keytab);
087            options.put("useKeyTab", "true");
088            options.put("storeKey", "true");
089            options.put("useTicketCache", "false");
090        }
091        AppConfigurationEntry entry = new AppConfigurationEntry(krb5LoginModuleName,
092                AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
093        entries.put(name, entry);
094    }
095
096    /**
097     * Removes the specified entry.
098     *
099     * @param name  The name of the entry to remove
100     */
101    public static void removeEntry(String name) {
102        entries.remove(name);
103    }
104
105    /**
106     * Clears all entries.
107     */
108    public static void clearEntries() {
109        entries.clear();
110    }
111
112    /**
113     * Returns the entries map.
114     *
115     * @return the entries map
116     */
117    public static Map<String, AppConfigurationEntry> getEntries() {
118        return entries;
119    }
120
121    @Override
122    public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
123        return new AppConfigurationEntry[]{entries.get(name)};
124    }
125}