Author: frm
Date: Fri Sep 18 07:34:53 2015
New Revision: 1703758
URL: http://svn.apache.org/viewvc?rev=1703758&view=rev
Log:
OAK-3201 - Prevent SecurityProviderImpl to register unless its required
dependencies are accessible
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/Preconditions.java
(with props)
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderRegistration.java
(with props)
jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/SecurityProviderRegistrationTest.groovy
Modified:
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugSecurityProvider.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/package-info.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/RandomAuthorizableNodeName.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/token/CompositeTokenConfiguration.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/token/package-info.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/CompositePrincipalConfiguration.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/package-info.java
jackrabbit/oak/trunk/oak-pojosr/pom.xml
Modified:
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugSecurityProvider.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugSecurityProvider.java?rev=1703758&r1=1703757&r2=1703758&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugSecurityProvider.java
(original)
+++
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugSecurityProvider.java
Fri Sep 18 07:34:53 2015
@@ -33,12 +33,8 @@ final class CugSecurityProvider extends
composite.setDefaultConfig(authorizationConfiguration);
composite.addConfiguration(new CugConfiguration(this));
composite.addConfiguration(authorizationConfiguration);
- ((CugSecurityProvider)
this).bindAuthorizationConfiguration(composite);
+ setAuthorizationConfiguration(composite);
}
}
- @Override
- protected void bindAuthorizationConfiguration(@Nonnull
AuthorizationConfiguration reference) {
- super.bindAuthorizationConfiguration(reference);
- }
}
\ No newline at end of file
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/Preconditions.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/Preconditions.java?rev=1703758&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/Preconditions.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/Preconditions.java
Fri Sep 18 07:34:53 2015
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security;
+
+import java.util.Set;
+
+import static com.google.common.collect.Sets.newHashSet;
+
+/**
+ * Represents a preconditions set that may be satisfied by adding the right
+ * candidates.
+ * <p/>
+ * Initially, a set of preconditions is empty. An empty set of preconditions is
+ * always satisfied. If candidates are added, but the precondition set is
empty,
+ * the preconditions are considered satisfied.
+ * <p/>
+ * When some preconditions are added, the preconditions set may enter into the
+ * unsatisfied state. In this case, the preconditions set may be come satisfied
+ * again only with the addition of the right candidates.
+ * <p/>
+ * This class doesn't admit duplicates for preconditions or candidates. Adding
+ * the same precondition (or candidate) twice doesn't have any effect on the
+ * state of the preconditions set.
+ */
+class Preconditions {
+
+ private final Set<String> preconditions = newHashSet();
+
+ private final Set<String> candidates = newHashSet();
+
+ private boolean dirty = false;
+
+ private boolean satisfied = true;
+
+ /**
+ * Add a precondition to this preconditions set. If the precondition
already
+ * belongs to this set, this operation has no effect.
+ *
+ * @param precondition The precondition to be added.
+ */
+ public void addPrecondition(String precondition) {
+ if (preconditions.add(precondition)) {
+ dirty = true;
+ }
+ }
+
+ /**
+ * Remove all the preconditions to this set. This makes the set of
+ * preconditions empty and, as such, satisfied.
+ */
+ public void clearPreconditions() {
+ preconditions.clear();
+ dirty = false;
+ satisfied = true;
+ }
+
+ /**
+ * Add a candidate to this preconditions set. If the candidate already
+ * belongs to this set, this operation has no effect.
+ *
+ * @param candidate The candidate to be added.
+ */
+ public void addCandidate(String candidate) {
+ if (candidates.add(candidate)) {
+ dirty = true;
+ }
+ }
+
+ /**
+ * Remove a candidate from this preconditions set. If the candidate doesn't
+ * belong to this set, this operation has no effect.
+ *
+ * @param candidate The candidate to be removed.
+ */
+ public void removeCandidate(String candidate) {
+ if (candidates.remove(candidate)) {
+ dirty = true;
+ }
+ }
+
+ /**
+ * Check if the preconditions set are satisfied.
+ *
+ * @return {@code true} if the preconditions set is satisfied, {@code
false}
+ * otherwise.
+ */
+ public boolean areSatisfied() {
+ if (dirty) {
+ satisfied = candidates.containsAll(preconditions);
+ dirty = false;
+ }
+
+ return satisfied;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("Preconditions(preconditions = %s, candidates =
%s)", preconditions, candidates);
+ }
+
+}
Propchange:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/Preconditions.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderImpl.java?rev=1703758&r1=1703757&r2=1703758&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderImpl.java
Fri Sep 18 07:34:53 2015
@@ -16,116 +16,94 @@
*/
package org.apache.jackrabbit.oak.security;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import com.google.common.collect.ImmutableMap;
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.ReferencePolicy;
-import org.apache.felix.scr.annotations.Service;
-import org.apache.jackrabbit.oak.osgi.OsgiWhiteboard;
import
org.apache.jackrabbit.oak.security.authentication.AuthenticationConfigurationImpl;
import
org.apache.jackrabbit.oak.security.authentication.token.TokenConfigurationImpl;
import
org.apache.jackrabbit.oak.security.authorization.AuthorizationConfigurationImpl;
import org.apache.jackrabbit.oak.security.principal.PrincipalConfigurationImpl;
import org.apache.jackrabbit.oak.security.privilege.PrivilegeConfigurationImpl;
import org.apache.jackrabbit.oak.security.user.UserConfigurationImpl;
-import org.apache.jackrabbit.oak.spi.security.ConfigurationBase;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.SecurityConfiguration;
import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
import
org.apache.jackrabbit.oak.spi.security.authentication.AuthenticationConfiguration;
-import
org.apache.jackrabbit.oak.spi.security.authentication.token.CompositeTokenConfiguration;
import
org.apache.jackrabbit.oak.spi.security.authentication.token.TokenConfiguration;
import
org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
-import
org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants;
-import
org.apache.jackrabbit.oak.spi.security.principal.CompositePrincipalConfiguration;
import org.apache.jackrabbit.oak.spi.security.principal.PrincipalConfiguration;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConfiguration;
import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
-import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
-import
org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardAuthorizableActionProvider;
-import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardAuthorizableNodeName;
import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardAware;
-import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardRestrictionProvider;
-import
org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUserAuthenticationFactory;
-import org.osgi.framework.BundleContext;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Sets.newHashSet;
-@Component
-@Service(value = {SecurityProvider.class})
public class SecurityProviderImpl implements SecurityProvider, WhiteboardAware
{
- @Reference
- private volatile AuthorizationConfiguration authorizationConfiguration;
+ private AuthenticationConfiguration authenticationConfiguration;
- @Reference
- private volatile AuthenticationConfiguration authenticationConfiguration;
+ private AuthorizationConfiguration authorizationConfiguration;
- @Reference
- private volatile PrivilegeConfiguration privilegeConfiguration;
+ private UserConfiguration userConfiguration;
- @Reference
- private volatile UserConfiguration userConfiguration;
-
- @Reference(referenceInterface = PrincipalConfiguration.class,
- name = "principalConfiguration",
- bind = "bindPrincipalConfiguration",
- unbind = "unbindPrincipalConfiguration",
- policy = ReferencePolicy.DYNAMIC,
- cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE)
- private final CompositePrincipalConfiguration principalConfiguration = new
CompositePrincipalConfiguration(this);
-
- @Reference(referenceInterface = TokenConfiguration.class,
- name = "tokenConfiguration",
- bind = "bindTokenConfiguration",
- unbind = "unbindTokenConfiguration",
- policy = ReferencePolicy.DYNAMIC,
- cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE)
- private final CompositeTokenConfiguration tokenConfiguration = new
CompositeTokenConfiguration(this);
-
- private final WhiteboardAuthorizableNodeName authorizableNodeName = new
WhiteboardAuthorizableNodeName();
- private final WhiteboardAuthorizableActionProvider
authorizableActionProvider = new WhiteboardAuthorizableActionProvider();
- private final WhiteboardRestrictionProvider restrictionProvider = new
WhiteboardRestrictionProvider();
- private final WhiteboardUserAuthenticationFactory
userAuthenticationFactory = new
WhiteboardUserAuthenticationFactory(UserConfigurationImpl.getDefaultAuthenticationFactory());
+ private PrincipalConfiguration principalConfiguration;
+
+ private PrivilegeConfiguration privilegeConfiguration;
+
+ private TokenConfiguration tokenConfiguration;
private ConfigurationParameters configuration;
private Whiteboard whiteboard;
/**
- * Default constructor used in OSGi environments.
+ * Default constructor using an empty configuration and default
+ * implementations for the security configurations.
*/
public SecurityProviderImpl() {
this(ConfigurationParameters.EMPTY);
}
/**
- * Create a new {@code SecurityProvider} instance with the given
configuration
- * parameters.
+ * Create a new {@code SecurityProvider} instance with the given
+ * configuration parameters.
*
* @param configuration security configuration
*/
public SecurityProviderImpl(@Nonnull ConfigurationParameters
configuration) {
- checkNotNull(configuration);
- this.configuration = configuration;
+ this.configuration = checkNotNull(configuration);
+ this.authenticationConfiguration = new
AuthenticationConfigurationImpl(this);
+ this.authorizationConfiguration = new
AuthorizationConfigurationImpl(this);
+ this.userConfiguration = new UserConfigurationImpl(this);
+ this.principalConfiguration = new PrincipalConfigurationImpl(this);
+ this.privilegeConfiguration = new PrivilegeConfigurationImpl();
+ this.tokenConfiguration = new TokenConfigurationImpl(this);
+ }
+
+ protected void setAuthenticationConfiguration(AuthenticationConfiguration
authenticationConfiguration) {
+ this.authenticationConfiguration =
checkNotNull(authenticationConfiguration);
+ }
+
+ protected void setAuthorizationConfiguration(AuthorizationConfiguration
authorizationConfiguration) {
+ this.authorizationConfiguration = authorizationConfiguration;
+ }
+
+ protected void setUserConfiguration(UserConfiguration userConfiguration) {
+ this.userConfiguration = userConfiguration;
+ }
- authenticationConfiguration = new
AuthenticationConfigurationImpl(this);
- authorizationConfiguration = new AuthorizationConfigurationImpl(this);
- userConfiguration = new UserConfigurationImpl(this);
- privilegeConfiguration = new PrivilegeConfigurationImpl();
+ protected void setPrincipalConfiguration(PrincipalConfiguration
principalConfiguration) {
+ this.principalConfiguration = principalConfiguration;
+ }
+
+ protected void setPrivilegeConfiguration(PrivilegeConfiguration
privilegeConfiguration) {
+ this.privilegeConfiguration = privilegeConfiguration;
+ }
- principalConfiguration.setDefaultConfig(new
PrincipalConfigurationImpl(this));
- tokenConfiguration.setDefaultConfig(new TokenConfigurationImpl(this));
+ protected void setTokenConfiguration(TokenConfiguration
tokenConfiguration) {
+ this.tokenConfiguration = tokenConfiguration;
}
@Override
@@ -144,7 +122,9 @@ public class SecurityProviderImpl implem
if (name == null) {
return configuration;
}
+
ConfigurationParameters params = configuration.getConfigValue(name,
ConfigurationParameters.EMPTY);
+
for (SecurityConfiguration sc : getConfigurations()) {
if (sc != null && sc.getName().equals(name)) {
return ConfigurationParameters.of(params, sc.getParameters());
@@ -156,14 +136,14 @@ public class SecurityProviderImpl implem
@Nonnull
@Override
public Iterable<? extends SecurityConfiguration> getConfigurations() {
- Set<SecurityConfiguration> scs = new HashSet<SecurityConfiguration>();
- scs.add(authenticationConfiguration);
- scs.add(authorizationConfiguration);
- scs.add(userConfiguration);
- scs.add(principalConfiguration);
- scs.add(privilegeConfiguration);
- scs.add(tokenConfiguration);
- return scs;
+ return newHashSet(
+ authenticationConfiguration,
+ authorizationConfiguration,
+ userConfiguration,
+ principalConfiguration,
+ privilegeConfiguration,
+ tokenConfiguration
+ );
}
@SuppressWarnings("unchecked")
@@ -187,89 +167,4 @@ public class SecurityProviderImpl implem
}
}
- //----------------------------------------------------------------< SCR
>---
- @Activate
- protected void activate(BundleContext context) {
- whiteboard = new OsgiWhiteboard(context);
- authorizableActionProvider.start(whiteboard);
- authorizableNodeName.start(whiteboard);
- restrictionProvider.start(whiteboard);
- userAuthenticationFactory.start(whiteboard);
-
- initializeConfigurations();
- }
-
- @Deactivate
- protected void deactivate() {
- authorizableActionProvider.stop();
- authorizableNodeName.stop();
- restrictionProvider.stop();
- userAuthenticationFactory.stop();
- }
-
- @SuppressWarnings("UnusedDeclaration")
- protected void bindPrincipalConfiguration(@Nonnull PrincipalConfiguration
reference) {
- principalConfiguration.addConfiguration(initConfiguration(reference));
- }
-
- @SuppressWarnings("UnusedDeclaration")
- protected void unbindPrincipalConfiguration(@Nonnull
PrincipalConfiguration reference) {
- principalConfiguration.removeConfiguration(reference);
- }
-
- @SuppressWarnings("UnusedDeclaration")
- protected void bindTokenConfiguration(@Nonnull TokenConfiguration
reference) {
- tokenConfiguration.addConfiguration(initConfiguration(reference));
- }
-
- @SuppressWarnings("UnusedDeclaration")
- protected void unbindTokenConfiguration(@Nonnull TokenConfiguration
reference) {
- tokenConfiguration.removeConfiguration(reference);
- }
-
- @SuppressWarnings("UnusedDeclaration")
- protected void bindAuthorizationConfiguration(@Nonnull
AuthorizationConfiguration reference) {
- authorizationConfiguration = initConfiguration(reference);
- // TODO (OAK-1268):
authorizationConfiguration.addConfiguration(initConfiguration(reference));
- }
-
- @SuppressWarnings("UnusedDeclaration")
- protected void unbindAuthorizationConfiguration(@Nonnull
AuthorizationConfiguration reference) {
- authorizationConfiguration = new AuthorizationConfigurationImpl(this);
- // TODO (OAK-1268):
authorizationConfiguration.removeConfiguration(reference);
- }
-
- //------------------------------------------------------------< private
>---
- private void initializeConfigurations() {
- initConfiguration(authorizationConfiguration,
ConfigurationParameters.of(
- AccessControlConstants.PARAM_RESTRICTION_PROVIDER,
restrictionProvider)
- );
-
- Map<String, Object> userMap = ImmutableMap.<String,Object>of(
- UserConstants.PARAM_AUTHORIZABLE_ACTION_PROVIDER,
authorizableActionProvider,
- UserConstants.PARAM_AUTHORIZABLE_NODE_NAME,
authorizableNodeName,
- UserConstants.PARAM_USER_AUTHENTICATION_FACTORY,
userAuthenticationFactory);
- initConfiguration(userConfiguration,
ConfigurationParameters.of(userMap));
-
- initConfiguration(authenticationConfiguration);
- initConfiguration(privilegeConfiguration);
- }
-
- private <T extends SecurityConfiguration> T initConfiguration(@Nonnull T
config) {
- if (config instanceof ConfigurationBase) {
- ConfigurationBase cfg = (ConfigurationBase) config;
- cfg.setSecurityProvider(this);
-
cfg.setParameters(ConfigurationParameters.of(ConfigurationParameters.EMPTY,
cfg.getParameters()));
- }
- return config;
- }
-
- private <T extends SecurityConfiguration> T initConfiguration(@Nonnull T
config, @Nonnull ConfigurationParameters params) {
- if (config instanceof ConfigurationBase) {
- ConfigurationBase cfg = (ConfigurationBase) config;
- cfg.setSecurityProvider(this);
- cfg.setParameters(ConfigurationParameters.of(params,
cfg.getParameters()));
- }
- return config;
- }
}
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderRegistration.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderRegistration.java?rev=1703758&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderRegistration.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderRegistration.java
Fri Sep 18 07:34:53 2015
@@ -0,0 +1,622 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Modified;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.PropertyUnbounded;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.ReferencePolicy;
+import org.apache.felix.scr.annotations.References;
+import org.apache.jackrabbit.oak.commons.PropertiesUtil;
+import org.apache.jackrabbit.oak.osgi.OsgiWhiteboard;
+import org.apache.jackrabbit.oak.security.user.UserConfigurationImpl;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationBase;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+import org.apache.jackrabbit.oak.spi.security.SecurityConfiguration;
+import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
+import
org.apache.jackrabbit.oak.spi.security.authentication.AuthenticationConfiguration;
+import
org.apache.jackrabbit.oak.spi.security.authentication.token.CompositeTokenConfiguration;
+import
org.apache.jackrabbit.oak.spi.security.authentication.token.TokenConfiguration;
+import
org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
+import
org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants;
+import
org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
+import
org.apache.jackrabbit.oak.spi.security.principal.CompositePrincipalConfiguration;
+import org.apache.jackrabbit.oak.spi.security.principal.PrincipalConfiguration;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConfiguration;
+import org.apache.jackrabbit.oak.spi.security.user.AuthorizableNodeName;
+import org.apache.jackrabbit.oak.spi.security.user.UserAuthenticationFactory;
+import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import
org.apache.jackrabbit.oak.spi.security.user.action.AuthorizableActionProvider;
+import
org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardAuthorizableActionProvider;
+import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardAuthorizableNodeName;
+import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardRestrictionProvider;
+import
org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUserAuthenticationFactory;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.collect.Lists.newCopyOnWriteArrayList;
+
+@Component(
+ immediate = true,
+ metatype = true,
+ label = "Apache Jackrabbit Oak SecurityProvider",
+ description = "The default SecurityProvider embedded in Apache
Jackrabbit Oak"
+)
+@Properties({
+ @Property(
+ name = "requiredServicePids",
+ label = "Required service PIDs",
+ description = "The SecurityProvider will not register itself "
+
+ "unless the services identified by these PIDs are " +
+ "registered first. Only the PIDs of implementations of
" +
+ "the following interfaces are checked: " +
+ "PrincipalConfiguration, TokenConfiguration, " +
+ "AuthorizableNodeName, AuthorizableActionProvider, " +
+ "RestrictionProvider and UserAuthenticationFactory.",
+ value = {
+
"org.apache.jackrabbit.oak.security.principal.PrincipalConfigurationImpl",
+
"org.apache.jackrabbit.oak.security.authentication.token.TokenConfigurationImpl",
+
"org.apache.jackrabbit.oak.security.user.RandomAuthorizableNodeName",
+
"org.apache.jackrabbit.oak.spi.security.user.action.DefaultAuthorizableActionProvider",
+
"org.apache.jackrabbit.oak.security.authorization.restriction.RestrictionProviderImpl",
+
"org.apache.jackrabbit.oak.security.user.UserAuthenticationFactoryImpl"
+ },
+ unbounded = PropertyUnbounded.ARRAY
+ )
+})
+@References({
+ @Reference(
+ name = "principalConfiguration",
+ referenceInterface = PrincipalConfiguration.class,
+ cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
+ policy = ReferencePolicy.DYNAMIC
+ ),
+ @Reference(
+ name = "tokenConfiguration",
+ referenceInterface = TokenConfiguration.class,
+ cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
+ policy = ReferencePolicy.DYNAMIC
+ ),
+ @Reference(
+ name = "authorizableNodeName",
+ referenceInterface = AuthorizableNodeName.class,
+ cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
+ policy = ReferencePolicy.DYNAMIC
+ ),
+ @Reference(
+ name = "authorizableActionProvider",
+ referenceInterface = AuthorizableActionProvider.class,
+ cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
+ policy = ReferencePolicy.DYNAMIC
+ ),
+ @Reference(
+ name = "restrictionProvider",
+ referenceInterface = RestrictionProvider.class,
+ cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
+ policy = ReferencePolicy.DYNAMIC
+ ),
+ @Reference(
+ name = "userAuthenticationFactory",
+ referenceInterface = UserAuthenticationFactory.class,
+ cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
+ policy = ReferencePolicy.DYNAMIC
+ )
+})
+public class SecurityProviderRegistration {
+
+ private static final Logger log =
LoggerFactory.getLogger(SecurityProviderRegistration.class);
+
+ @Reference
+ private AuthorizationConfiguration authorizationConfiguration;
+
+ @Reference
+ private AuthenticationConfiguration authenticationConfiguration;
+
+ @Reference
+ private PrivilegeConfiguration privilegeConfiguration;
+
+ @Reference
+ private UserConfiguration userConfiguration;
+
+ private BundleContext context;
+
+ private ServiceRegistration registration;
+
+ private boolean registering;
+
+ private final Preconditions preconditions = new Preconditions();
+
+ private final List<PrincipalConfiguration> principalConfigurations =
newCopyOnWriteArrayList();
+
+ private final List<TokenConfiguration> tokenConfigurations =
newCopyOnWriteArrayList();
+
+ private final List<AuthorizableNodeName> authorizableNodeNames =
newCopyOnWriteArrayList();
+
+ private final List<AuthorizableActionProvider> authorizableActionProviders
= newCopyOnWriteArrayList();
+
+ private final List<RestrictionProvider> restrictionProviders =
newCopyOnWriteArrayList();
+
+ private final List<UserAuthenticationFactory> userAuthenticationFactories
= newCopyOnWriteArrayList();
+
+ @Activate
+ public void activate(BundleContext context, Map<String, Object>
configuration) {
+ String[] requiredServicePids = getRequiredServicePids(configuration);
+
+ synchronized (this) {
+ for (String pid : requiredServicePids) {
+ preconditions.addPrecondition(pid);
+ }
+
+ this.context = context;
+ }
+
+ maybeRegister();
+ }
+
+ @Modified
+ public void modified(Map<String, Object> configuration) {
+ String[] requiredServicePids = getRequiredServicePids(configuration);
+
+ synchronized (this) {
+ preconditions.clearPreconditions();
+
+ for (String pid : requiredServicePids) {
+ preconditions.addPrecondition(pid);
+ }
+ }
+
+ maybeUnregister();
+ maybeRegister();
+ }
+
+ @Deactivate
+ public void deactivate() {
+ ServiceRegistration registration;
+
+ synchronized (this) {
+ registration = this.registration;
+
+ this.registration = null;
+ this.registering = false;
+ this.context = null;
+
+ this.preconditions.clearPreconditions();
+ }
+
+ if (registration != null) {
+ registration.unregister();
+ }
+ }
+
+ public void bindAuthorizationConfiguration(AuthorizationConfiguration
authorizationConfiguration) {
+ this.authorizationConfiguration = authorizationConfiguration;
+ }
+
+ public void unbindAuthorizationConfiguration(AuthorizationConfiguration
authorizationConfiguration) {
+ this.authorizationConfiguration = null;
+ }
+
+ public void bindAuthenticationConfiguration(AuthenticationConfiguration
authenticationConfiguration) {
+ this.authenticationConfiguration = authenticationConfiguration;
+ }
+
+ public void unbindAuthenticationConfiguration(AuthenticationConfiguration
authenticationConfiguration) {
+ this.authenticationConfiguration = null;
+ }
+
+ public void bindPrivilegeConfiguration(PrivilegeConfiguration
privilegeConfiguration) {
+ this.privilegeConfiguration = privilegeConfiguration;
+ }
+
+ public void unbindPrivilegeConfiguration(PrivilegeConfiguration
privilegeConfiguration) {
+ this.privilegeConfiguration = null;
+ }
+
+ public void bindUserConfiguration(UserConfiguration userConfiguration) {
+ this.userConfiguration = userConfiguration;
+ }
+
+ public void unbindUserConfiguration(UserConfiguration userConfiguration) {
+ this.userConfiguration = null;
+ }
+
+ public void bindPrincipalConfiguration(PrincipalConfiguration
principalConfiguration, Map<String, Object> properties) {
+ synchronized (this) {
+ principalConfigurations.add(principalConfiguration);
+ addCandidate(properties);
+ }
+
+ maybeRegister();
+ }
+
+ public void unbindPrincipalConfiguration(PrincipalConfiguration
principalConfiguration, Map<String, Object> properties) {
+ synchronized (this) {
+ principalConfigurations.remove(principalConfiguration);
+ removeCandidate(properties);
+ }
+
+ maybeUnregister();
+ }
+
+ public void bindTokenConfiguration(TokenConfiguration tokenConfiguration,
Map<String, Object> properties) {
+ synchronized (this) {
+ tokenConfigurations.add(tokenConfiguration);
+ addCandidate(properties);
+ }
+
+ maybeRegister();
+ }
+
+ public void unbindTokenConfiguration(TokenConfiguration
tokenConfiguration, Map<String, Object> properties) {
+ synchronized (this) {
+ tokenConfigurations.remove(tokenConfiguration);
+ removeCandidate(properties);
+ }
+
+ maybeUnregister();
+ }
+
+ public void bindAuthorizableNodeName(AuthorizableNodeName
authorizableNodeName, Map<String, Object> properties) {
+ synchronized (this) {
+ authorizableNodeNames.add(authorizableNodeName);
+ addCandidate(properties);
+ }
+
+ maybeRegister();
+ }
+
+ public void unbindAuthorizableNodeName(AuthorizableNodeName
authorizableNodeName, Map<String, Object> properties) {
+ synchronized (this) {
+ authorizableNodeNames.remove(authorizableNodeName);
+ removeCandidate(properties);
+ }
+
+ maybeUnregister();
+ }
+
+ public void bindAuthorizableActionProvider(AuthorizableActionProvider
authorizableActionProvider, Map<String, Object> properties) {
+ synchronized (this) {
+ authorizableActionProviders.add(authorizableActionProvider);
+ addCandidate(properties);
+ }
+
+ maybeRegister();
+ }
+
+ public void unbindAuthorizableActionProvider(AuthorizableActionProvider
authorizableActionProvider, Map<String, Object> properties) {
+ synchronized (this) {
+ authorizableActionProviders.remove(authorizableActionProvider);
+ removeCandidate(properties);
+ }
+
+ maybeUnregister();
+ }
+
+ public void bindRestrictionProvider(RestrictionProvider
restrictionProvider, Map<String, Object> properties) {
+ synchronized (this) {
+ restrictionProviders.add(restrictionProvider);
+ addCandidate(properties);
+ }
+
+ maybeRegister();
+ }
+
+ public void unbindRestrictionProvider(RestrictionProvider
restrictionProvider, Map<String, Object> properties) {
+ synchronized (this) {
+ restrictionProviders.remove(restrictionProvider);
+ removeCandidate(properties);
+ }
+
+ maybeUnregister();
+ }
+
+ public void bindUserAuthenticationFactory(UserAuthenticationFactory
userAuthenticationFactory, Map<String, Object> properties) {
+ synchronized (this) {
+ userAuthenticationFactories.add(userAuthenticationFactory);
+ addCandidate(properties);
+ }
+
+ maybeRegister();
+ }
+
+ public void unbindUserAuthenticationFactory(UserAuthenticationFactory
userAuthenticationFactory, Map<String, Object> properties) {
+ synchronized (this) {
+ userAuthenticationFactories.remove(userAuthenticationFactory);
+ removeCandidate(properties);
+ }
+
+ maybeUnregister();
+ }
+
+ private void maybeRegister() {
+ BundleContext context;
+
+ log.info("Trying to register a SecurityProvider...");
+
+ synchronized (this) {
+
+ // The component is not activated, yet. We have no means of
registering
+ // the SecurityProvider. This method will be called again after
+ // activation completes.
+
+ if (this.context == null) {
+ log.info("Aborting: no BundleContext is available");
+ return;
+ }
+
+ // The preconditions are not satisifed. This may happen when this
+ // component is activated but not enough mandatory services are
bound
+ // to it.
+
+ if (!preconditions.areSatisfied()) {
+ log.info("Aborting: preconditions are not satisfied: {}",
preconditions);
+ return;
+ }
+
+ // The SecurityProvider is already registered. This may happen
when a
+ // new dependency is added to this component, but the requirements
are
+ // already satisfied.
+
+ if (registration != null) {
+ log.info("Aborting: a SecurityProvider is already registered");
+ return;
+ }
+
+ // If the component is in the process of registering an instance of
+ // SecurityProvider, return. This check is necessary because we
don't
+ // want to call createSecurityProvider() more than once. That
method,
+ // in fact, changes the state of the bound dependencies (it sets a
+ // back-reference from the security configurations to the new
+ // SecurityProvider). We want those dependencies to change state
only
+ // when we are sure that we will register the SecurityProvider we
+ // are creating.
+
+ if (registering) {
+ log.info("Aborting: a SecurityProvider is already being
registered");
+ return;
+ }
+
+ // Mark the start of a registration process.
+
+ registering = true;
+
+ // Save the BundleContext for local usage.
+
+ context = this.context;
+ }
+
+ // Register the SecurityProvider.
+
+ ServiceRegistration registration = context.registerService(
+ SecurityProvider.class.getName(),
+ createSecurityProvider(context),
+ null
+ );
+
+ synchronized (this) {
+ this.registration = registration;
+ this.registering = false;
+ }
+
+ log.info("SecurityProvider instance registered");
+ }
+
+ private void maybeUnregister() {
+ ServiceRegistration registration;
+
+ log.info("Trying to unregister the SecurityProvider...");
+
+ synchronized (this) {
+
+ // If there is nothing to register, we obviously have nothing to
do.
+
+ if (this.registration == null) {
+ log.info("Aborting: no SecurityProvider is registered");
+ return;
+ }
+
+ // The preconditions are not satisfied. This may happen when a
+ // dependency is unbound from the current component.
+
+ if (preconditions.areSatisfied()) {
+ log.info("Aborting: preconditions are satisfied");
+ return;
+ }
+
+ // Save the ServiceRegistration for local use.
+
+ registration = this.registration;
+ this.registration = null;
+ }
+
+ registration.unregister();
+
+ log.info("SecurityProvider instance unregistered");
+ }
+
+ private SecurityProvider createSecurityProvider(BundleContext context) {
+ SecurityProviderImpl securityProvider = new SecurityProviderImpl();
+
+ // Static, mandatory references
+
+
securityProvider.setAuthenticationConfiguration(initializeConfiguration(securityProvider,
authenticationConfiguration));
+
securityProvider.setAuthorizationConfiguration(initializeConfiguration(securityProvider,
authorizationConfiguration));
+
securityProvider.setUserConfiguration(initializeConfiguration(securityProvider,
userConfiguration));
+
securityProvider.setPrivilegeConfiguration(initializeConfiguration(securityProvider,
privilegeConfiguration));
+
+ // Multiple, dynamic references
+
+
securityProvider.setPrincipalConfiguration(createCompositePrincipalConfiguration(securityProvider));
+
securityProvider.setTokenConfiguration(createCompositeTokenConfiguration(securityProvider));
+
+ // Whiteboard
+
+ securityProvider.setWhiteboard(new OsgiWhiteboard(context));
+
+ return securityProvider;
+ }
+
+ private PrincipalConfiguration
createCompositePrincipalConfiguration(SecurityProvider securityProvider) {
+ return new CompositePrincipalConfiguration(securityProvider) {
+
+ @Override
+ protected List<PrincipalConfiguration> getConfigurations() {
+ ArrayList<PrincipalConfiguration> configurations =
newArrayList(newArrayList(principalConfigurations));
+
+ for (PrincipalConfiguration configuration : configurations) {
+ initializeConfiguration(getSecurityProvider(),
configuration);
+ }
+
+ return configurations;
+ }
+
+ };
+ }
+
+ private TokenConfiguration
createCompositeTokenConfiguration(SecurityProvider securityProvider) {
+ return new CompositeTokenConfiguration(securityProvider) {
+
+ @Override
+ protected List<TokenConfiguration> getConfigurations() {
+ List<TokenConfiguration> configurations =
newArrayList(tokenConfigurations);
+
+ for (TokenConfiguration configuration : configurations) {
+ initializeConfiguration(getSecurityProvider(),
configuration);
+ }
+
+ return configurations;
+ }
+
+ };
+ }
+
+ private AuthorizationConfiguration
initializeConfiguration(SecurityProvider securityProvider,
AuthorizationConfiguration authorizationConfiguration) {
+ return initializeConfiguration(securityProvider,
authorizationConfiguration, ConfigurationParameters.of(
+ AccessControlConstants.PARAM_RESTRICTION_PROVIDER,
createCompositeRestrictionProvider()
+ ));
+ }
+
+ private UserConfiguration initializeConfiguration(SecurityProvider
securityProvider, UserConfiguration userConfiguration) {
+ return initializeConfiguration(securityProvider, userConfiguration,
ConfigurationParameters.of(
+
ConfigurationParameters.of(UserConstants.PARAM_AUTHORIZABLE_ACTION_PROVIDER,
createCompositeAuthorizableActionProvider()),
+
ConfigurationParameters.of(UserConstants.PARAM_AUTHORIZABLE_NODE_NAME,
createCompositeAuthorizableNodeName()),
+
ConfigurationParameters.of(UserConstants.PARAM_USER_AUTHENTICATION_FACTORY,
createCompositeUserAuthenticationFactory())
+ ));
+ }
+
+ private <T extends SecurityConfiguration> T
initializeConfiguration(SecurityProvider securityProvider, T configuration) {
+ return initializeConfiguration(securityProvider, configuration,
ConfigurationParameters.EMPTY);
+ }
+
+ private <T extends SecurityConfiguration> T
initializeConfiguration(SecurityProvider securityProvider, T configuration,
ConfigurationParameters parameters) {
+ if (configuration instanceof ConfigurationBase) {
+ ConfigurationBase base = (ConfigurationBase) configuration;
+ base.setSecurityProvider(securityProvider);
+ base.setParameters(ConfigurationParameters.of(parameters,
base.getParameters()));
+ }
+
+ return configuration;
+ }
+
+ private RestrictionProvider createCompositeRestrictionProvider() {
+ return new WhiteboardRestrictionProvider() {
+
+ @Override
+ protected List<RestrictionProvider> getServices() {
+ return newArrayList(restrictionProviders);
+ }
+
+ };
+ }
+
+ private AuthorizableActionProvider
createCompositeAuthorizableActionProvider() {
+ return new WhiteboardAuthorizableActionProvider() {
+
+ @Override
+ protected List<AuthorizableActionProvider> getServices() {
+ return newArrayList(authorizableActionProviders);
+ }
+
+ };
+ }
+
+ private AuthorizableNodeName createCompositeAuthorizableNodeName() {
+ return new WhiteboardAuthorizableNodeName() {
+
+ @Override
+ protected List<AuthorizableNodeName> getServices() {
+ return newArrayList(authorizableNodeNames);
+ }
+
+ };
+ }
+
+ private UserAuthenticationFactory
createCompositeUserAuthenticationFactory() {
+ return new
WhiteboardUserAuthenticationFactory(UserConfigurationImpl.getDefaultAuthenticationFactory())
{
+
+ @Override
+ protected List<UserAuthenticationFactory> getServices() {
+ return newArrayList(userAuthenticationFactories);
+ }
+
+ };
+ }
+
+ private void addCandidate(Map<String, Object> properties) {
+ String pid = getServicePid(properties);
+
+ if (pid == null) {
+ return;
+ }
+
+ preconditions.addCandidate(pid);
+ }
+
+ private void removeCandidate(Map<String, Object> properties) {
+ String pid = getServicePid(properties);
+
+ if (pid == null) {
+ return;
+ }
+
+ preconditions.removeCandidate(pid);
+ }
+
+ private String getServicePid(Map<String, Object> properties) {
+ return PropertiesUtil.toString(properties.get(Constants.SERVICE_PID),
null);
+ }
+
+ private String[] getRequiredServicePids(Map<String, Object> configuration)
{
+ return
PropertiesUtil.toStringArray(configuration.get("requiredServicePids"), new
String[]{});
+ }
+
+}
Propchange:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderRegistration.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/package-info.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/package-info.java?rev=1703758&r1=1703757&r2=1703758&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/package-info.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/package-info.java
Fri Sep 18 07:34:53 2015
@@ -20,7 +20,7 @@
*
* See <a href="README.md">README.md</a> for more details.
*/
-@Version("1.0.1")
+@Version("2.0.0")
@Export(optional = "provide:=true")
package org.apache.jackrabbit.oak.security;
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/RandomAuthorizableNodeName.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/RandomAuthorizableNodeName.java?rev=1703758&r1=1703757&r2=1703758&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/RandomAuthorizableNodeName.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/RandomAuthorizableNodeName.java
Fri Sep 18 07:34:53 2015
@@ -33,7 +33,7 @@ import org.apache.jackrabbit.oak.spi.sec
* Implementation of the {@code AuthorizableNodeName} that generates a random
* node name that doesn't reveal the ID of the authorizable.
*/
-@Component(metatype = true, label = "Apache Jackrabbit Oak Random Authorizable
Node Name", description = "Generates a random name for the authorizable node.",
policy = ConfigurationPolicy.REQUIRE)
+@Component(metatype = true, label = "Apache Jackrabbit Oak Random Authorizable
Node Name", description = "Generates a random name for the authorizable node.")
@Service(AuthorizableNodeName.class)
public class RandomAuthorizableNodeName implements AuthorizableNodeName {
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/token/CompositeTokenConfiguration.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/token/CompositeTokenConfiguration.java?rev=1703758&r1=1703757&r2=1703758&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/token/CompositeTokenConfiguration.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/token/CompositeTokenConfiguration.java
Fri Sep 18 07:34:53 2015
@@ -28,7 +28,7 @@ import org.apache.jackrabbit.oak.spi.sec
/**
* {@link TokenConfiguration} that combines different token provider
implementations.
*/
-public final class CompositeTokenConfiguration extends
CompositeConfiguration<TokenConfiguration> implements TokenConfiguration {
+public class CompositeTokenConfiguration extends
CompositeConfiguration<TokenConfiguration> implements TokenConfiguration {
public CompositeTokenConfiguration(@Nonnull SecurityProvider
securityProvider) {
super(TokenConfiguration.NAME, securityProvider);
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/token/package-info.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/token/package-info.java?rev=1703758&r1=1703757&r2=1703758&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/token/package-info.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/token/package-info.java
Fri Sep 18 07:34:53 2015
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@Version("1.1.0")
+@Version("1.2.0")
@Export(optional = "provide:=true")
package org.apache.jackrabbit.oak.spi.security.authentication.token;
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/CompositePrincipalConfiguration.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/CompositePrincipalConfiguration.java?rev=1703758&r1=1703757&r2=1703758&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/CompositePrincipalConfiguration.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/CompositePrincipalConfiguration.java
Fri Sep 18 07:34:53 2015
@@ -30,7 +30,7 @@ import org.apache.jackrabbit.oak.spi.sec
* {@link PrincipalConfiguration} that combines different principal provider
* implementations that share a common principal manager implementation.
*/
-public final class CompositePrincipalConfiguration extends
CompositeConfiguration<PrincipalConfiguration> implements
PrincipalConfiguration {
+public class CompositePrincipalConfiguration extends
CompositeConfiguration<PrincipalConfiguration> implements
PrincipalConfiguration {
public CompositePrincipalConfiguration(@Nonnull SecurityProvider
securityProvider) {
super(PrincipalConfiguration.NAME, securityProvider);
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/package-info.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/package-info.java?rev=1703758&r1=1703757&r2=1703758&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/package-info.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/package-info.java
Fri Sep 18 07:34:53 2015
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@Version("1.0")
+@Version("1.1.0")
@Export(optional = "provide:=true")
package org.apache.jackrabbit.oak.spi.security.principal;
Modified: jackrabbit/oak/trunk/oak-pojosr/pom.xml
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-pojosr/pom.xml?rev=1703758&r1=1703757&r2=1703758&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-pojosr/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-pojosr/pom.xml Fri Sep 18 07:34:53 2015
@@ -305,5 +305,11 @@
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <version>1.10.19</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
Added:
jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/SecurityProviderRegistrationTest.groovy
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/SecurityProviderRegistrationTest.groovy?rev=1703758&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/SecurityProviderRegistrationTest.groovy
(added)
+++
jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/SecurityProviderRegistrationTest.groovy
Fri Sep 18 07:34:53 2015
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.run.osgi
+
+import org.apache.felix.connect.launch.PojoServiceRegistry
+import org.apache.jackrabbit.oak.spi.security.SecurityProvider
+import
org.apache.jackrabbit.oak.spi.security.authentication.token.TokenConfiguration
+import
org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider
+import org.apache.jackrabbit.oak.spi.security.principal.PrincipalConfiguration
+import org.apache.jackrabbit.oak.spi.security.user.AuthorizableNodeName
+import org.apache.jackrabbit.oak.spi.security.user.UserAuthenticationFactory
+import
org.apache.jackrabbit.oak.spi.security.user.action.AuthorizableActionProvider
+import org.junit.Before
+import org.junit.Test
+import org.osgi.framework.ServiceReference
+import org.osgi.service.cm.ConfigurationAdmin
+
+import java.util.concurrent.TimeUnit
+
+import static org.mockito.Mockito.mock
+
+class SecurityProviderRegistrationTest extends AbstractRepositoryFactoryTest {
+
+ private PojoServiceRegistry registry;
+
+ @Before
+ public void initializeRegistry() {
+ registry = repositoryFactory.initializeServiceRegistry(config)
+ }
+
+ /**
+ * Test that, without any additional configuration, a SecurityProvider
+ * service is registered by default.
+ */
+ @Test
+ public void testDefaultSetup() {
+ assert securityProviderServiceReferences != null
+ }
+
+ /**
+ * A SecurityProvider shouldn't start without a required
+ * PrincipalConfiguration service.
+ */
+ @Test
+ public void testRequiredPrincipalConfigurationNotAvailable() {
+ testRequiredService(PrincipalConfiguration,
mock(PrincipalConfiguration))
+ }
+
+ /**
+ * A SecurityProvider shouldn't start without a required TokenConfiguration
+ * service.
+ */
+ @Test
+ public void testRequiredTokenConfigurationNotAvailable() {
+ testRequiredService(TokenConfiguration, mock(TokenConfiguration))
+ }
+
+ /**
+ * A SecurityProvider shouldn't start without a required
+ * AuthorizableNodeName service.
+ */
+ @Test
+ public void testRequiredAuthorizableNodeNameNotAvailable() {
+ testRequiredService(AuthorizableNodeName, mock(AuthorizableNodeName))
+ }
+
+ /**
+ * A SecurityProvider shouldn't start without a required
+ * AuthorizableActionProvider service.
+ */
+ @Test
+ public void testRequiredAuthorizableActionProviderNotAvailable() {
+ testRequiredService(AuthorizableActionProvider,
mock(AuthorizableActionProvider))
+ }
+
+ /**
+ * A SecurityProvider shouldn't start without a required
RestrictionProvider
+ * service.
+ */
+ @Test
+ public void testRequiredRestrictionProviderNotAvailable() {
+ testRequiredService(RestrictionProvider, mock(RestrictionProvider))
+ }
+
+ /**
+ * A SecurityProvider shouldn't start without a required
+ * UserAuthenticationFactory service.
+ */
+ @Test
+ public void testRequiredUserAuthenticationFactoryNotAvailable() {
+ testRequiredService(UserAuthenticationFactory,
mock(UserAuthenticationFactory))
+ }
+
+ /**
+ * A SecurityProvider should be registered only if every every prerequisite
+ * is satisfied.
+ */
+ @Test
+ public void testMultipleRequiredServices() {
+
+ // Set up the SecurityProvider to require three services
+
+ setRequiredServicePids("test.RequiredPrincipalConfiguration",
"test.RequiredTokenConfiguration", "test.AuthorizableNodeName")
+ TimeUnit.MILLISECONDS.sleep(500)
+ assert securityProviderServiceReferences == null
+
+ // Start the services and verify that only at the end the
+ // SecurityProvider registers itself
+
+ registry.registerService(PrincipalConfiguration.class.name,
mock(PrincipalConfiguration), dict("service.pid":
"test.RequiredPrincipalConfiguration"))
+ assert securityProviderServiceReferences == null
+
+ registry.registerService(TokenConfiguration.class.name,
mock(TokenConfiguration), dict("service.pid":
"test.RequiredTokenConfiguration"))
+ assert securityProviderServiceReferences == null
+
+ registry.registerService(TokenConfiguration.class.name,
mock(TokenConfiguration), dict("service.pid": "test.AuthorizableNodeName"))
+ assert securityProviderServiceReferences != null
+ }
+
+ private <T> void testRequiredService(Class<T> serviceClass, T service) {
+
+ // Adding a new precondition on a missing service PID forces the
+ // SecurityProvider to unregister.
+
+ setRequiredServicePids("test.Required" + serviceClass.simpleName)
+ TimeUnit.MILLISECONDS.sleep(500)
+ assert securityProviderServiceReferences == null
+
+ // If a service is registered, and if the PID of the service matches
the
+ // precondition, the SecurityProvider is registered again.
+
+ def registration = registry.registerService(serviceClass.name,
service, dict("service.pid": "test.Required" + serviceClass.simpleName))
+ assert securityProviderServiceReferences != null
+
+ // If the service is unregistered, but the precondition is still in
+ // place, the SecurityProvider unregisters again.
+
+ registration.unregister()
+ assert securityProviderServiceReferences == null
+
+ // Removing the precondition allows the SecurityProvider to register.
+
+ setRequiredServicePids()
+ TimeUnit.MILLISECONDS.sleep(500)
+ assert securityProviderServiceReferences != null
+ }
+
+ private ServiceReference<?>[] getSecurityProviderServiceReferences() {
+ return registry.getServiceReferences(SecurityProvider.class.name, null)
+ }
+
+ private void setRequiredServicePids(String... pids) {
+ setConfiguration([
+
"org.apache.jackrabbit.oak.security.SecurityProviderRegistration": [
+ "requiredServicePids": pids
+ ]
+ ])
+ }
+
+ private void setConfiguration(Map<String, Map<String, Object>>
configuration) {
+ getConfigurationInstaller().installConfigs(configuration)
+ }
+
+ private ConfigInstaller getConfigurationInstaller() {
+ return new ConfigInstaller(getConfigurationAdmin(),
registry.bundleContext)
+ }
+
+ private ConfigurationAdmin getConfigurationAdmin() {
+ return
registry.getService(registry.getServiceReference(ConfigurationAdmin.class.name))
as ConfigurationAdmin
+ }
+
+ private static <K, V> Dictionary<K, V> dict(Map<K, V> map) {
+ return new Hashtable<K, V>(map);
+ }
+
+}