X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.cms%2Fsrc%2Forg%2Fargeo%2Fcms%2Finternal%2Fkernel%2FActivator.java;h=f50594210bf37521151b52f1ead3b1f6ca65c6a0;hb=549ff25baf9371d910065303e22daf49321b517a;hp=1efc9dc66474953221194974c0044558e163514b;hpb=5b5c2b97eee9edd037e198acadf8b416a973863f;p=lgpl%2Fargeo-commons.git 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 1efc9dc66..f50594210 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 @@ -1,74 +1,116 @@ package org.argeo.cms.internal.kernel; -import java.awt.image.Kernel; import java.io.IOException; import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; +import java.security.AllPermission; import java.util.Dictionary; import java.util.List; import java.util.Locale; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import javax.security.auth.login.Configuration; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.cms.CmsException; -import org.argeo.node.ArgeoLogger; -import org.argeo.node.NodeConstants; -import org.argeo.node.NodeDeployment; -import org.argeo.node.NodeInstance; -import org.argeo.node.NodeState; -import org.argeo.util.LangUtils; +import org.argeo.api.cms.CmsState; +import org.argeo.api.cms.CmsLog; +import org.argeo.api.cms.CmsConstants; +import org.argeo.api.cms.CmsContext; +import org.argeo.api.cms.CmsDeployment; +import org.argeo.cms.ArgeoLogger; +import org.argeo.cms.auth.ident.IdentClient; import org.ietf.jgss.GSSCredential; +import org.osgi.framework.Bundle; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; -import org.osgi.framework.ServiceReference; +import org.osgi.framework.FrameworkUtil; +import org.osgi.service.condpermadmin.BundleLocationCondition; +import org.osgi.service.condpermadmin.ConditionInfo; +import org.osgi.service.condpermadmin.ConditionalPermissionAdmin; +import org.osgi.service.condpermadmin.ConditionalPermissionInfo; +import org.osgi.service.condpermadmin.ConditionalPermissionUpdate; import org.osgi.service.log.LogReaderService; +import org.osgi.service.permissionadmin.PermissionInfo; import org.osgi.service.useradmin.UserAdmin; +import org.osgi.util.tracker.ServiceTracker; /** - * Activates the {@link Kernel} from the provided {@link BundleContext}. Gives - * access to kernel information for the rest of the bundle (and only it) + * Activates the kernel. Gives access to kernel information for the rest of the + * bundle (and only it) */ public class Activator implements BundleActivator { - private final static Log log = LogFactory.getLog(Activator.class); + private final static CmsLog log = CmsLog.getLog(Activator.class); private static Activator instance; - private BundleContext bc; - // private CmsSecurity nodeSecurity; + // TODO make it configurable + private boolean hardened = false; + + private static BundleContext bundleContext; + private LogReaderService logReaderService; - // private ConfigurationAdmin configurationAdmin; private NodeLogger logger; - private CmsState nodeState; - private CmsDeployment nodeDeployment; - private CmsInstance nodeInstance; + private CmsStateImpl nodeState; + private CmsDeploymentImpl nodeDeployment; + private CmsContextImpl nodeInstance; - @Override - public void start(BundleContext bundleContext) throws Exception { + private ServiceTracker userAdminSt; + private ExecutorService internalExecutorService; + + static { + Bundle bundle = FrameworkUtil.getBundle(Activator.class); + if (bundle != null) { + bundleContext = bundle.getBundleContext(); + } + } + + void init() { Runtime.getRuntime().addShutdownHook(new CmsShutdown()); instance = this; - this.bc = bundleContext; - this.logReaderService = getService(LogReaderService.class); - // this.configurationAdmin = getService(ConfigurationAdmin.class); +// this.bc = bundleContext; + if (bundleContext != null) + this.logReaderService = getService(LogReaderService.class); + this.internalExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); try { - // nodeSecurity = new CmsSecurity(); initSecurity(); - initArgeoLogger(); +// initArgeoLogger(); initNode(); - } catch (Exception e) { + + if (log.isTraceEnabled()) + log.trace("Kernel bundle started"); + } catch (Throwable e) { log.error("## FATAL: CMS activator failed", e); } } + void destroy() { + try { + if (nodeInstance != null) + nodeInstance.shutdown(); + if (nodeDeployment != null) + nodeDeployment.shutdown(); + if (nodeState != null) + nodeState.shutdown(); + + if (userAdminSt != null) + userAdminSt.close(); + + internalExecutorService.shutdown(); + instance = null; + bundleContext = null; + this.logReaderService = null; + // this.configurationAdmin = null; + } catch (Exception e) { + log.error("CMS activator shutdown failed", e); + } + } + private void initSecurity() { if (System.getProperty(KernelConstants.JAAS_CONFIG_PROP) == null) { String jaasConfig = KernelConstants.JAAS_CONFIG; - URL url = getClass().getClassLoader().getResource(jaasConfig); + URL url = getClass().getResource(jaasConfig); // System.setProperty(KernelConstants.JAAS_CONFIG_PROP, // url.toExternalForm()); KernelUtils.setJaasConfiguration(url); @@ -76,95 +118,153 @@ public class Activator implements BundleActivator { // explicitly load JAAS configuration Configuration.getConfiguration(); - // ConditionalPermissionAdmin permissionAdmin = bc - // .getService(bc.getServiceReference(ConditionalPermissionAdmin.class)); - // ConditionalPermissionUpdate update = - // permissionAdmin.newConditionalPermissionUpdate(); - // // Self - // update.getConditionalPermissionInfos() - // .add(permissionAdmin.newConditionalPermissionInfo(null, - // new ConditionInfo[] { - // new ConditionInfo(BundleLocationCondition.class.getName(), new - // String[] { "*" }) }, - // new PermissionInfo[] { new - // PermissionInfo(AllPermission.class.getName(), null, null) }, - // ConditionalPermissionInfo.ALLOW)); - // + // code-level permissions + String osgiSecurity = KernelUtils.getFrameworkProp(Constants.FRAMEWORK_SECURITY); + if (osgiSecurity != null && Constants.FRAMEWORK_SECURITY_OSGI.equals(osgiSecurity)) { + // TODO rather use a tracker? + ConditionalPermissionAdmin permissionAdmin = bundleContext + .getService(bundleContext.getServiceReference(ConditionalPermissionAdmin.class)); + if (!hardened) { + // All permissions to all bundles + ConditionalPermissionUpdate update = permissionAdmin.newConditionalPermissionUpdate(); + update.getConditionalPermissionInfos().add(permissionAdmin.newConditionalPermissionInfo(null, + new ConditionInfo[] { + new ConditionInfo(BundleLocationCondition.class.getName(), new String[] { "*" }) }, + new PermissionInfo[] { new PermissionInfo(AllPermission.class.getName(), null, null) }, + ConditionalPermissionInfo.ALLOW)); + // TODO data admin permission +// PermissionInfo dataAdminPerm = new PermissionInfo(AuthPermission.class.getName(), +// "createLoginContext." + NodeConstants.LOGIN_CONTEXT_DATA_ADMIN, null); +// update.getConditionalPermissionInfos().add(permissionAdmin.newConditionalPermissionInfo(null, +// new ConditionInfo[] { +// new ConditionInfo(BundleLocationCondition.class.getName(), new String[] { "*" }) }, +// new PermissionInfo[] { dataAdminPerm }, ConditionalPermissionInfo.DENY)); +// update.getConditionalPermissionInfos().add(permissionAdmin.newConditionalPermissionInfo(null, +// new ConditionInfo[] { +// new ConditionInfo(BundleSignerCondition.class.getName(), new String[] { "CN=\"Eclipse.org Foundation, Inc.\", OU=IT, O=\"Eclipse.org Foundation, Inc.\", L=Nepean, ST=Ontario, C=CA" }) }, +// new PermissionInfo[] { dataAdminPerm }, ConditionalPermissionInfo.ALLOW)); + update.commit(); + } else { + SecurityProfile securityProfile = new SecurityProfile() { + }; + securityProfile.applySystemPermissions(permissionAdmin); + } + } + } private void initArgeoLogger() { - // Jetty - // disable integration of Jetty logging with SLF4J - // in order to avoid chicken and egg problems - // org.eclipse.jetty.util.log.Log.setLog(new StdErrLog()); - // org.eclipse.jetty.util.log.Logger jettyLog = - // org.eclipse.jetty.util.log.Log.getLog(); - // if (jettyLog != null) { - // jettyLog.warn("TEST JETTY LOG", new Object[0]); - // } - logger = new NodeLogger(logReaderService); - bc.registerService(ArgeoLogger.class, logger, null); + if (bundleContext != null) + bundleContext.registerService(ArgeoLogger.class, logger, null); } private void initNode() throws IOException { // Node state - Path stateUuidPath = bc.getDataFile("stateUuid").toPath(); - String stateUuid; - if (Files.exists(stateUuidPath)) { - stateUuid = Files.readAllLines(stateUuidPath).get(0); - } else { - stateUuid = bc.getProperty(Constants.FRAMEWORK_UUID); - Files.write(stateUuidPath, stateUuid.getBytes()); - } - nodeState = new CmsState(stateUuid); - Dictionary regProps = LangUtils.dico(Constants.SERVICE_PID, NodeConstants.NODE_STATE_PID); - regProps.put(NodeConstants.CN, stateUuid); - bc.registerService(NodeState.class, nodeState, regProps); + nodeState = new CmsStateImpl(); + registerService(CmsState.class, nodeState, null); // Node deployment - nodeDeployment = new CmsDeployment(); - bc.registerService(NodeDeployment.class, nodeDeployment, null); + nodeDeployment = new CmsDeploymentImpl(); +// registerService(NodeDeployment.class, nodeDeployment, null); // Node instance - nodeInstance = new CmsInstance(); - bc.registerService(NodeInstance.class, nodeInstance, null); + nodeInstance = new CmsContextImpl(); + registerService(CmsContext.class, nodeInstance, null); } - @Override - public void stop(BundleContext bundleContext) throws Exception { - try { - if (nodeInstance != null) - nodeInstance.shutdown(); - if (nodeDeployment != null) - nodeDeployment.shutdown(); - if (nodeState != null) - nodeState.shutdown(); + public static void registerService(Class clss, T service, Dictionary properties) { + if (bundleContext != null) { + bundleContext.registerService(clss, service, properties); + } - instance = null; - this.bc = null; - this.logReaderService = null; - // this.configurationAdmin = null; - } catch (Exception e) { - log.error("CMS activator shutdown failed", e); + } + + public static T getService(Class clss) { + if (bundleContext != null) { + return bundleContext.getService(bundleContext.getServiceReference(clss)); + } else { + return null; } } - private T getService(Class clazz) { - ServiceReference sr = bc.getServiceReference(clazz); - if (sr == null) - throw new CmsException("No service available for " + clazz); - return bc.getService(sr); + /* + * OSGi + */ + + @Override + public void start(BundleContext bc) throws Exception { + if (!bc.getBundle().equals(bundleContext.getBundle())) + throw new IllegalStateException( + "Bundle " + bc.getBundle() + " is not consistent with " + bundleContext.getBundle()); + init(); + userAdminSt = new ServiceTracker<>(bundleContext, UserAdmin.class, null); + userAdminSt.open(); + } + + @Override + public void stop(BundleContext bc) throws Exception { + if (!bc.getBundle().equals(bundleContext.getBundle())) + throw new IllegalStateException( + "Bundle " + bc.getBundle() + " is not consistent with " + bundleContext.getBundle()); + destroy(); } - public static NodeState getNodeState() { +// private T getService(Class clazz) { +// ServiceReference sr = bundleContext.getServiceReference(clazz); +// if (sr == null) +// throw new IllegalStateException("No service available for " + clazz); +// return bundleContext.getService(sr); +// } + + public static CmsState getNodeState() { return instance.nodeState; } public static GSSCredential getAcceptorCredentials() { - ServiceReference sr = instance.bc.getServiceReference(UserAdmin.class); - NodeUserAdmin userAdmin = (NodeUserAdmin) instance.bc.getService(sr); - return userAdmin.getAcceptorCredentials(); + return getNodeUserAdmin().getAcceptorCredentials(); + } + + @Deprecated + public static boolean isSingleUser() { + return getNodeUserAdmin().isSingleUser(); + } + + public static UserAdmin getUserAdmin() { + return (UserAdmin) getNodeUserAdmin(); + } + + public static String getHttpProxySslHeader() { + return KernelUtils.getFrameworkProp(CmsConstants.HTTP_PROXY_SSL_DN); + } + + public static IdentClient getIdentClient(String remoteAddr) { + if (!IdentClient.isDefaultAuthdPassphraseFileAvailable()) + return null; + // TODO make passphrase more configurable + return new IdentClient(remoteAddr); + } + + private static NodeUserAdmin getNodeUserAdmin() { + NodeUserAdmin res; + try { + res = instance.userAdminSt.waitForService(60000); + } catch (InterruptedException e) { + throw new IllegalStateException("Cannot retrieve Node user admin", e); + } + if (res == null) + throw new IllegalStateException("No Node user admin found"); + + return res; + // ServiceReference sr = + // instance.bc.getServiceReference(UserAdmin.class); + // NodeUserAdmin userAdmin = (NodeUserAdmin) instance.bc.getService(sr); + // return userAdmin; + + } + + static ExecutorService getInternalExecutorService() { + return instance.internalExecutorService; } // static CmsSecurity getCmsSecurity() { @@ -180,4 +280,13 @@ public class Activator implements BundleActivator { return res; } + static BundleContext getBundleContext() { + return bundleContext; + } + + public static void main(String[] args) { + instance = new Activator(); + instance.init(); + } + }