From: Mathieu Baudier Date: Thu, 23 Mar 2017 08:38:43 +0000 (+0100) Subject: Deactivate IPA when unnecessary. X-Git-Tag: argeo-commons-2.1.66~3 X-Git-Url: https://git.argeo.org/?p=lgpl%2Fargeo-commons.git;a=commitdiff_plain;h=8a582781fa376ebcf66096dd6fb90232648b4682 Deactivate IPA when unnecessary. --- diff --git a/demo/argeo_node_rap.properties b/demo/argeo_node_rap.properties index 572292ea2..71227581b 100644 --- a/demo/argeo_node_rap.properties +++ b/demo/argeo_node_rap.properties @@ -69,4 +69,9 @@ log4j.configuration=file:../../log4j.properties # DON'T CHANGE BELOW org.eclipse.rap.workbenchAutostart=false org.eclipse.equinox.http.jetty.autostart=false -#javax.security.auth.useSubjectCredsOnly=false +org.osgi.framework.bootdelegation=com.sun.jndi.ldap,\ +com.sun.jndi.ldap.sasl,\ +com.sun.security.jgss,\ +com.sun.jndi.dns,\ +com.sun.nio.file,\ +com.sun.nio.sctp diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/Activator.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/Activator.java index e5930303a..2e524b9d5 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/Activator.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/Activator.java @@ -69,7 +69,9 @@ public class Activator implements BundleActivator { if (System.getProperty(KernelConstants.JAAS_CONFIG_PROP) == null) { String jaasConfig = KernelConstants.JAAS_CONFIG; URL url = getClass().getClassLoader().getResource(jaasConfig); - System.setProperty(KernelConstants.JAAS_CONFIG_PROP, url.toExternalForm()); + // System.setProperty(KernelConstants.JAAS_CONFIG_PROP, + // url.toExternalForm()); + KernelUtils.setJaasConfiguration(url); } // explicitly load JAAS configuration Configuration.getConfiguration(); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java index 6faa4c9e2..126c591e6 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java @@ -28,6 +28,7 @@ import org.argeo.node.NodeConstants; import org.argeo.node.NodeDeployment; import org.argeo.node.NodeState; import org.argeo.node.security.CryptoKeyring; +import org.argeo.osgi.useradmin.UserAdminConf; import org.argeo.util.LangUtils; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; @@ -108,6 +109,20 @@ public class CmsDeployment implements NodeDeployment { Object cn = config.getProperties().get(NodeConstants.CN); log.debug("Standalone repo cn: " + cn); } + configs = configurationAdmin + .listConfigurations("(service.factoryPid=" + NodeConstants.NODE_USER_ADMIN_PID + ")"); + + boolean hasDomain = false; + for (Configuration config : configs) { + Object realm = config.getProperties().get(UserAdminConf.realm.name()); + if (realm != null) { + log.debug("Realm: " + realm); + hasDomain = true; + } + } + if (!hasDomain) { + loadNoIpaJaasConfiguration(); + } } catch (Exception e) { throw new CmsException("Cannot initialize config", e); } @@ -116,8 +131,18 @@ public class CmsDeployment implements NodeDeployment { }.open(); } + private void loadNoIpaJaasConfiguration() { + if (System.getProperty(KernelConstants.JAAS_CONFIG_PROP) == null) { + String jaasConfig = KernelConstants.JAAS_CONFIG_NOIPA; + URL url = getClass().getClassLoader().getResource(jaasConfig); + KernelUtils.setJaasConfiguration(url); + if (log.isDebugEnabled()) + log.debug("Set no-IPA JAAS configuration."); + } + } + public void shutdown() { - if(nodeHttp!=null) + if (nodeHttp != null) nodeHttp.destroy(); if (deployConfig != null) deployConfig.save(); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsSecurity.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsSecurity.java deleted file mode 100644 index 4f25e6106..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsSecurity.java +++ /dev/null @@ -1,339 +0,0 @@ -package org.argeo.cms.internal.kernel; - -import java.io.IOException; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.URL; -import java.net.UnknownHostException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.security.PrivilegedExceptionAction; -import java.util.ArrayList; -import java.util.Iterator; - -import javax.security.auth.Subject; -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.NameCallback; -import javax.security.auth.callback.UnsupportedCallbackException; -import javax.security.auth.kerberos.KerberosPrincipal; -import javax.security.auth.login.Configuration; -import javax.security.auth.login.LoginContext; -import javax.security.auth.login.LoginException; - -import org.apache.commons.httpclient.auth.AuthPolicy; -import org.apache.commons.httpclient.auth.CredentialsProvider; -import org.apache.commons.httpclient.cookie.CookiePolicy; -import org.apache.commons.httpclient.params.DefaultHttpParams; -import org.apache.commons.httpclient.params.HttpMethodParams; -import org.apache.commons.httpclient.params.HttpParams; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.cms.CmsException; -import org.argeo.cms.internal.http.NodeHttp; -import org.argeo.cms.internal.http.client.SpnegoAuthScheme; -import org.argeo.cms.internal.http.client.HttpCredentialProvider; -import org.argeo.naming.DnsBrowser; -import org.argeo.node.NodeConstants; -import org.ietf.jgss.GSSCredential; -import org.ietf.jgss.GSSException; -import org.ietf.jgss.GSSManager; -import org.ietf.jgss.GSSName; -import org.ietf.jgss.Oid; - -/** Low-level kernel security */ -@Deprecated -public class CmsSecurity implements KernelConstants { - private final static Log log = LogFactory.getLog(CmsSecurity.class); - // http://java.sun.com/javase/6/docs/technotes/guides/security/jgss/jgss-features.html - private final static Oid KERBEROS_OID; - static { - try { - KERBEROS_OID = new Oid("1.3.6.1.5.5.2"); - } catch (GSSException e) { - throw new IllegalStateException("Cannot create Kerberos OID", e); - } - } - - public final static int DEPLOYED = 30; - public final static int STANDALONE = 20; - public final static int DEV = 10; - public final static int UNKNOWN = 0; - - private String hostname; - - private final int securityLevel; - private Subject nodeSubject; - - // IPA - private String kerberosDomain; - private String service = null; - private GSSCredential acceptorCredentials; - - private Path nodeKeyTab = KernelUtils.getOsgiInstancePath(KernelConstants.NODE_KEY_TAB_PATH); - - CmsSecurity() { - - if (!DeployConfig.isInitialized()) // first init - FirstInit.prepareInstanceArea(); - - securityLevel = evaluateSecurityLevel(); - - if (securityLevel == DEPLOYED) { - // Register client-side SPNEGO auth scheme - AuthPolicy.registerAuthScheme(SpnegoAuthScheme.NAME, SpnegoAuthScheme.class); - HttpParams params = DefaultHttpParams.getDefaultParams(); - ArrayList schemes = new ArrayList<>(); - schemes.add(SpnegoAuthScheme.NAME);// SPNEGO preferred - // schemes.add(AuthPolicy.BASIC);// incompatible with Basic - params.setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, schemes); - params.setParameter(CredentialsProvider.PROVIDER, new HttpCredentialProvider()); - params.setParameter(HttpMethodParams.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY); - // params.setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY); - } - - // Configure JAAS first - if (System.getProperty(JAAS_CONFIG_PROP) == null) { - String jaasConfig = securityLevel < DEPLOYED ? JAAS_CONFIG : JAAS_CONFIG_IPA; - URL url = getClass().getClassLoader().getResource(jaasConfig); - System.setProperty(JAAS_CONFIG_PROP, url.toExternalForm()); - } - // explicitly load JAAS configuration - Configuration.getConfiguration(); - nodeSubject = logInKernel(); - - // firstInit = !new File(getOsgiInstanceDir(), DIR_NODE).exists(); - - // this.keyStoreFile = new File(KernelUtils.getOsgiInstanceDir(), - // "node.p12"); - // createKeyStoreIfNeeded(); - } - - private int evaluateSecurityLevel() { - int res = UNKNOWN; - try (DnsBrowser dnsBrowser = new DnsBrowser()) { - InetAddress localhost = InetAddress.getLocalHost(); - hostname = localhost.getHostName(); - String dnsZone = hostname.substring(hostname.indexOf('.') + 1); - String ipfromDns = dnsBrowser.getRecord(hostname, localhost instanceof Inet6Address ? "AAAA" : "A"); - boolean consistentIp = localhost.getHostAddress().equals(ipfromDns); - kerberosDomain = dnsBrowser.getRecord("_kerberos." + dnsZone, "TXT"); - if (consistentIp && kerberosDomain != null && Files.exists(nodeKeyTab)) { - res = DEPLOYED; - } else { - res = STANDALONE; - kerberosDomain = null; - // FIXME make state more robust - } - } catch (UnknownHostException e) { - hostname = "localhost"; - log.warn("Cannot determine hostname, using " + hostname + ":" + e.getMessage()); - res = STANDALONE; - } catch (Exception e) { - log.warn("Exception when evaluating security level, setting it to DEV", e); - res = DEV; - } - - if (res == UNKNOWN) - throw new CmsException("Undefined security level"); - return res; - } - - private Subject logInKernel() { - final Subject nodeSubject = new Subject(); - - CallbackHandler callbackHandler; - if (Files.exists(nodeKeyTab)) { - service = NodeHttp.DEFAULT_SERVICE; - // service = NodeConstants.NODE_SERVICE; - callbackHandler = new CallbackHandler() { - - @Override - public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { - for (Callback callback : callbacks) - if (callback instanceof NameCallback) - ((NameCallback) callback).setName(getKerberosServicePrincipal()); - - } - }; - try { - LoginContext kernelLc = new LoginContext(NodeConstants.LOGIN_CONTEXT_NODE, nodeSubject, - callbackHandler); - kernelLc.login(); - } catch (LoginException e) { - throw new CmsException("Cannot log in kernel", e); - } - } else { - callbackHandler = null; - // try { - // callbackHandler = (CallbackHandler) - // Class.forName("com.sun.security.auth.callback.TextCallbackHandler") - // .newInstance(); - // } catch (ReflectiveOperationException e) { - // throw new CmsException("Cannot create text callback handler", e); - // } - try { - LoginContext kernelLc = new LoginContext(NodeConstants.LOGIN_CONTEXT_NODE, nodeSubject); - kernelLc.login(); - } catch (LoginException e) { - throw new CmsException("Cannot log in kernel", e); - } - } - - if (securityLevel >= DEPLOYED) { - acceptorCredentials = logInAsAcceptor(nodeSubject); - } - return nodeSubject; - } - - private String getKerberosServicePrincipal() { - if (hostname == null || "locahost".equals(hostname) || kerberosDomain == null || service == null) - throw new IllegalStateException("Cannot determine kerberos principal"); - return service + "/" + hostname + "@" + kerberosDomain; - } - - private GSSCredential logInAsAcceptor(Subject nodeSubject) { - // GSS - Iterator krb5It = nodeSubject.getPrincipals(KerberosPrincipal.class).iterator(); - if (!krb5It.hasNext()) - return null; - KerberosPrincipal krb5Principal = null; - while (krb5It.hasNext()) { - KerberosPrincipal principal = krb5It.next(); - if (service == null && krb5Principal == null)// first as default - krb5Principal = principal; - if (service != null && principal.getName().equals(getKerberosServicePrincipal())) - krb5Principal = principal; - } - - if (krb5Principal == null) - return null; - - GSSManager manager = GSSManager.getInstance(); - try { - GSSName gssName = manager.createName(krb5Principal.getName(), null); - GSSCredential serverCredentials = Subject.doAs(nodeSubject, new PrivilegedExceptionAction() { - - @Override - public GSSCredential run() throws GSSException { - return manager.createCredential(gssName, GSSCredential.INDEFINITE_LIFETIME, KERBEROS_OID, - GSSCredential.ACCEPT_ONLY); - - } - - }); - if (log.isDebugEnabled()) - log.debug("GSS acceptor configured for " + krb5Principal); - return serverCredentials; - } catch (Exception gsse) { - throw new CmsException("Cannot create acceptor credentials for " + krb5Principal, gsse); - } - } - // - // private Subject logInHardenedKernel() { - // final Subject kernelSubject = new Subject(); - // createKeyStoreIfNeeded(); - // - // CallbackHandler cbHandler = new CallbackHandler() { - // - // @Override - // public void handle(Callback[] callbacks) throws IOException, - // UnsupportedCallbackException { - // // alias - //// ((NameCallback) callbacks[1]).setName(AuthConstants.ROLE_KERNEL); - // // store pwd - // ((PasswordCallback) callbacks[2]).setPassword("changeit".toCharArray()); - // // key pwd - // ((PasswordCallback) callbacks[3]).setPassword("changeit".toCharArray()); - // } - // }; - // try { - // LoginContext kernelLc = new - // LoginContext(KernelConstants.LOGIN_CONTEXT_HARDENED_KERNEL, - // kernelSubject, - // cbHandler); - // kernelLc.login(); - // } catch (LoginException e) { - // throw new CmsException("Cannot log in kernel", e); - // } - // return kernelSubject; - // } - - void destroy() { - // Logout kernel - try { - LoginContext kernelLc = new LoginContext(NodeConstants.LOGIN_CONTEXT_NODE, nodeSubject); - kernelLc.logout(); - } catch (LoginException e) { - throw new CmsException("Cannot log out kernel", e); - } - - // Security.removeProvider(SECURITY_PROVIDER); - } - - public synchronized int getSecurityLevel() { - return securityLevel; - } - -// public String getKerberosDomain() { -// return kerberosDomain; -// } - -// public Subject getNodeSubject() { -// return nodeSubject; -// } - -// public GSSCredential getServerCredentials() { -// return acceptorCredentials; -// } - - // public void setSecurityLevel(int newValue) { - // if (newValue != STANDALONE || newValue != DEV) - // throw new CmsException("Invalid value for security level " + newValue); - // if (newValue >= securityLevel) - // throw new CmsException( - // "Impossible to increase security level (from " + securityLevel + " to " + - // newValue + ")"); - // securityLevel = newValue; - // } - - // private void createKeyStoreIfNeeded() { - // // for (Provider provider : Security.getProviders()) - // // System.out.println(provider.getName()); - // - // char[] ksPwd = "changeit".toCharArray(); - // char[] keyPwd = Arrays.copyOf(ksPwd, ksPwd.length); - // if (!keyStoreFile.exists()) { - // try { - // keyStoreFile.getParentFile().mkdirs(); - // KeyStore keyStore = PkiUtils.getKeyStore(keyStoreFile, ksPwd); - // // PkiUtils.generateSelfSignedCertificate(keyStore, new - // // X500Principal(AuthConstants.ROLE_KERNEL), 1024, - // // keyPwd); - // PkiUtils.saveKeyStore(keyStoreFile, ksPwd, keyStore); - // if (log.isDebugEnabled()) - // log.debug("Created keystore " + keyStoreFile); - // } catch (Exception e) { - // if (keyStoreFile.length() == 0) - // keyStoreFile.delete(); - // log.error("Cannot create keystore " + keyStoreFile, e); - // } - // } - // } - - // private final static String SECURITY_PROVIDER = "BC";// Bouncy Castle - // private final static Log log; - // static { - // log = LogFactory.getLog(NodeSecurity.class); - // // Make Bouncy Castle the default provider - // Provider provider = new BouncyCastleProvider(); - // int position = Security.insertProviderAt(provider, 1); - // if (position == -1) - // log.error("Provider " + provider.getName() - // + " already installed and could not be set as default"); - // Provider defaultProvider = Security.getProviders()[0]; - // if (!defaultProvider.getName().equals(SECURITY_PROVIDER)) - // log.error("Provider name is " + defaultProvider.getName() - // + " but it should be " + SECURITY_PROVIDER); - // } -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelConstants.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelConstants.java index f49d5d495..efadde0ce 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelConstants.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelConstants.java @@ -18,7 +18,7 @@ public interface KernelConstants { // Security String JAAS_CONFIG = "/org/argeo/cms/internal/kernel/jaas.cfg"; - String JAAS_CONFIG_IPA = "/org/argeo/cms/internal/kernel/jaas-ipa.cfg"; + String JAAS_CONFIG_NOIPA = "/org/argeo/cms/internal/kernel/jaas-noipa.cfg"; // Java String JAAS_CONFIG_PROP = "java.security.auth.login.config"; diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java index 5d4979791..b3fb33ac3 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java @@ -5,9 +5,11 @@ import java.io.IOException; import java.io.PrintStream; import java.net.URI; import java.net.URISyntaxException; +import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; import java.security.PrivilegedAction; +import java.security.URIParameter; import java.util.Dictionary; import java.util.Hashtable; import java.util.Properties; @@ -33,6 +35,17 @@ class KernelUtils implements KernelConstants { final static String OSGI_INSTANCE_AREA = "osgi.instance.area"; final static String OSGI_CONFIGURATION_AREA = "osgi.configuration.area"; + static void setJaasConfiguration(URL jaasConfigurationUrl) { + try { + URIParameter uriParameter = new URIParameter(jaasConfigurationUrl.toURI()); + javax.security.auth.login.Configuration jaasConfiguration = javax.security.auth.login.Configuration + .getInstance("JavaLoginConfig", uriParameter); + javax.security.auth.login.Configuration.setConfiguration(jaasConfiguration); + } catch (Exception e) { + throw new CmsException("Cannot set configuration " + jaasConfigurationUrl, e); + } + } + static Dictionary asDictionary(Properties props) { Hashtable hashtable = new Hashtable(); for (Object key : props.keySet()) { @@ -109,17 +122,17 @@ class KernelUtils implements KernelConstants { } // Security -// static Subject anonymousLogin() { -// Subject subject = new Subject(); -// LoginContext lc; -// try { -// lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, subject); -// lc.login(); -// return subject; -// } catch (LoginException e) { -// throw new CmsException("Cannot login as anonymous", e); -// } -// } + // static Subject anonymousLogin() { + // Subject subject = new Subject(); + // LoginContext lc; + // try { + // lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, subject); + // lc.login(); + // return subject; + // } catch (LoginException e) { + // throw new CmsException("Cannot login as anonymous", e); + // } + // } static void logFrameworkProperties(Log log) { BundleContext bc = getBundleContext(); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas-ipa.cfg b/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas-ipa.cfg deleted file mode 100644 index 550de1074..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas-ipa.cfg +++ /dev/null @@ -1,37 +0,0 @@ -USER { - org.argeo.cms.auth.HttpSessionLoginModule sufficient; - org.argeo.cms.auth.SpnegoLoginModule optional; - com.sun.security.auth.module.Krb5LoginModule optional; - org.argeo.cms.auth.IpaLoginModule requisite; -}; - -DATA_ADMIN { - org.argeo.cms.auth.DataAdminLoginModule requisite; -}; - -NODE { - com.sun.security.auth.module.Krb5LoginModule optional - keyTab="${osgi.instance.area}node/krb5.keytab" - useKeyTab=true - storeKey=true - debug=true; - org.argeo.cms.auth.DataAdminLoginModule requisite; -}; - -SINGLE_USER { - com.sun.security.auth.module.Krb5LoginModule optional - principal="${user.name}" - storeKey=true - useTicketCache=true - debug=true; - org.argeo.cms.auth.SingleUserLoginModule requisite; -}; - -KEYRING { - org.argeo.cms.auth.KeyringLoginModule required; -}; - -Jackrabbit { - org.argeo.security.jackrabbit.SystemJackrabbitLoginModule requisite; -}; - diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas-noipa.cfg b/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas-noipa.cfg new file mode 100644 index 000000000..88724d984 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas-noipa.cfg @@ -0,0 +1,24 @@ +USER { + org.argeo.cms.auth.HttpSessionLoginModule sufficient; + org.argeo.cms.auth.UserAdminLoginModule sufficient; +}; + +DATA_ADMIN { + org.argeo.cms.auth.DataAdminLoginModule requisite; +}; + +NODE { + org.argeo.cms.auth.DataAdminLoginModule requisite; +}; + +KEYRING { + org.argeo.cms.auth.KeyringLoginModule required; +}; + +SINGLE_USER { + org.argeo.cms.auth.SingleUserLoginModule requisite; +}; + +Jackrabbit { + org.argeo.security.jackrabbit.SystemJackrabbitLoginModule requisite; +}; diff --git a/org.argeo.node.api/src/org/argeo/node/NodeConstants.java b/org.argeo.node.api/src/org/argeo/node/NodeConstants.java index 1bf574590..72083e8e7 100644 --- a/org.argeo.node.api/src/org/argeo/node/NodeConstants.java +++ b/org.argeo.node.api/src/org/argeo/node/NodeConstants.java @@ -8,7 +8,6 @@ public interface NodeConstants { String NODE_DEPLOYMENT_PID = "org.argeo.node.deployment"; String NODE_INSTANCE_PID = "org.argeo.node.instance"; - String NODE_USER_ADMIN_PID = "org.argeo.node.userAdmin"; String NODE_KEYRING_PID = "org.argeo.node.keyring"; String NODE_FS_PROVIDER_PID = "org.argeo.node.fsProvider"; @@ -16,7 +15,7 @@ public interface NodeConstants { * FACTORY PIDs */ String NODE_REPOS_FACTORY_PID = "org.argeo.node.repos"; - String NODE_USER_DIRECTORIES_FACTORY_PID = "org.argeo.node.userDirectories"; + String NODE_USER_ADMIN_PID = "org.argeo.node.userAdmin"; /* * DN ATTRIBUTES (RFC 4514)