Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Any Way to Read JAAS Configuration File from Memory

We use JAAS in a heavily loaded web server. The configuration file is loaded from a file,

  System.setProperty("java.security.auth.login.config", "/config/jaas.config");

During profiling, we noticed that the configuration is loaded from file for every login attempt. This is an I/O operation we try to avoid. Is there anyway to store the JAAS configuration in memory?

like image 330
ZZ Coder Avatar asked Sep 18 '09 00:09

ZZ Coder


2 Answers

Following code snippet connects to a PostgreSQL database (using pgjdbc and HikariCP) with an in-memory JAAS configuration, that is, no Configuration files are required:

package com.vlkan.kerberos.auth;

import com.google.common.collect.ImmutableMap;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import java.util.Properties;

import static com.google.common.base.Preconditions.checkArgument;

public enum Main {

    private static final String JAAS_CONFIG_NAME = "pgjdbc";

    public static void main(String[] args) throws LoginException, SQLException {

        String jdbcUrl = "jdbc:postgresql://host/dbname";
        String jdbcDriver = "org.postgresql.Driver";
        String username = "user";
        String password = "pass";

        Configuration jaasConfig = createJaasConfig();
        Configuration.setConfiguration(jaasConfig);

        HikariConfig hikariConfig = createHikariConfig(jdbcUrl, jdbcDriver, username, password);
        HikariDataSource dataSource = new HikariDataSource(hikariConfig);
        try (Connection connection = dataSource.getConnection()) {
            try (PreparedStatement statement = connection.prepareStatement("SELECT 1")) {
                try (ResultSet resultSet = statement.executeQuery()) {
                    boolean next = resultSet.next();
                    checkArgument(next, "no results");
                    int result = resultSet.getInt(1);
                    checkArgument(result == 1, "expecting: 1, found: %s", result);
                    System.out.println("ok");
                }
            }
        }

    }

    private static HikariConfig createHikariConfig(String jdbcUrl, String jdbcDriver, String username, String password) {
        HikariConfig config = new HikariConfig();
        config.setDriverClassName(jdbcDriver);
        config.setJdbcUrl(jdbcUrl);
        config.setUsername(username);
        config.setPassword(password);
        fixKerberosProperties(config, username, password);
        return config;
    }

    private static void fixKerberosProperties(HikariConfig config, String username, String password) {
        Properties properties = new Properties();
        properties.setProperty("user", username);
        properties.setProperty("password", password);
        properties.setProperty("JAASConfigName", JAAS_CONFIG_NAME);
        config.setDataSourceProperties(properties);
    }

    private static Configuration createJaasConfig() {

        // Create entry options.
        Map<String, Object> options = ImmutableMap.of(
                "useFirstPass", "false",    // Do *not* use javax.security.auth.login.{name,password} from shared state.
                "debug", "true"             // Output debug (including plain text username and password!) messages.
        );

        // Create entries.
        AppConfigurationEntry[] entries = {
                new AppConfigurationEntry(
                        "com.sun.security.auth.module.Krb5LoginModule",
                        AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
                        options)
        };

        // Create configuration.
        return new Configuration() {
            @Override
            public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
                checkArgument(JAAS_CONFIG_NAME.equals(name));
                return entries;
            }
        };

    }

}
like image 122
Volkan Yazıcı Avatar answered Oct 05 '22 01:10

Volkan Yazıcı


You could implement your own Configuration. The javadoc says:

The default Configuration implementation can be changed by setting the value of the "login.configuration.provider" security property (in the Java security properties file) to the fully qualified name of the desired Configuration implementation class.

The default implementation com.sun.security.auth.login.ConfigFile (source) appears to load the file each time the class is instantiated. You could cache the contents. No comment on the security aspects either way.

like image 34
Billy Bob Bain Avatar answered Oct 05 '22 00:10

Billy Bob Bain