Skip to content

Commit

Permalink
Merge pull request #46 from arjantijms/m3_update
Browse files Browse the repository at this point in the history
Updates for Authorization API M3 and M4
  • Loading branch information
arjantijms committed Apr 2, 2024
2 parents ffa1ef0 + 42793a8 commit b21ccd6
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 52 deletions.
6 changes: 3 additions & 3 deletions impl/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,14 @@
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.1.0-M2</version>
<version>6.1.0</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>jakarta.authorization</groupId>
<artifactId>jakarta.authorization-api</artifactId>
<version>3.0.0-M2</version>
<version>3.0.0-M4</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
Expand Down Expand Up @@ -178,7 +178,7 @@

<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.12.1</version>
<version>3.13.0</version>
<configuration>
<release>17</release>
</configuration>
Expand Down
132 changes: 94 additions & 38 deletions impl/src/main/java/org/glassfish/exousia/AuthorizationService.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@

package org.glassfish.exousia;

import static jakarta.security.jacc.PolicyContext.HTTP_SERVLET_REQUEST;
import static jakarta.security.jacc.PolicyContext.PRINCIPAL_MAPPER;
import static jakarta.security.jacc.PolicyContext.SUBJECT;
import static java.lang.System.Logger.Level.DEBUG;
import static java.lang.System.Logger.Level.ERROR;
import static java.util.Collections.emptySet;
import static org.glassfish.exousia.constraints.transformer.ConstraintsToPermissionsTransformer.createResourceAndDataPermissions;
import static org.glassfish.exousia.permissions.RolesToPermissionsTransformer.createWebRoleRefPermission;

import jakarta.security.jacc.EJBMethodPermission;
import jakarta.security.jacc.EJBRoleRefPermission;
import jakarta.security.jacc.Policy;
Expand All @@ -31,7 +40,6 @@
import jakarta.security.jacc.WebUserDataPermission;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;

import java.lang.System.Logger;
import java.lang.reflect.Method;
import java.security.Permission;
Expand All @@ -44,25 +52,14 @@
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;

import javax.security.auth.Subject;

import org.glassfish.exousia.constraints.SecurityConstraint;
import org.glassfish.exousia.mapping.DefaultPrincipalMapper;
import org.glassfish.exousia.mapping.SecurityRoleRef;
import org.glassfish.exousia.modules.def.DefaultPolicy;
import org.glassfish.exousia.modules.def.DefaultPolicyConfigurationFactory;
import org.glassfish.exousia.permissions.JakartaPermissions;

import static jakarta.security.jacc.PolicyContext.HTTP_SERVLET_REQUEST;
import static jakarta.security.jacc.PolicyContext.PRINCIPAL_MAPPER;
import static jakarta.security.jacc.PolicyContext.SUBJECT;
import static java.lang.System.Logger.Level.DEBUG;
import static java.lang.System.Logger.Level.ERROR;
import static java.util.Collections.emptySet;
import static org.glassfish.exousia.constraints.transformer.ConstraintsToPermissionsTransformer.createResourceAndDataPermissions;
import static org.glassfish.exousia.permissions.RolesToPermissionsTransformer.createWebRoleRefPermission;

/**
*
* @author Arjan Tijms
Expand All @@ -82,8 +79,8 @@ public class AuthorizationService {
*/
private final Policy policy;
private final PolicyFactory policyFactory;
private final PolicyConfigurationFactory factory;
private final PolicyConfiguration policyConfiguration;
private final PolicyConfigurationFactory policyConfigurationFactory;
private final Map<String, jakarta.security.jacc.PrincipalMapper> principalMapper = new ConcurrentHashMap<>();

private String constrainedUriRequestAttribute;
Expand Down Expand Up @@ -117,7 +114,7 @@ public AuthorizationService(
Supplier<Subject> subjectSupplier, Supplier<PrincipalMapper> principalMapperSupplier) {

this(
installFactory(factoryClass), installPolicy(policyClass), contextId,
installPolicyConfigurationFactory(factoryClass), installPolicy(policyClass), contextId,
subjectSupplier, principalMapperSupplier);
}

Expand All @@ -126,15 +123,15 @@ public AuthorizationService(
Supplier<Subject> subjectSupplier, Supplier<PrincipalMapper> principalMapperSupplier) {

this(
getConfigurationFactory(), null, contextId,
PolicyConfigurationFactory.get(), null, contextId,
subjectSupplier, principalMapperSupplier);
}

public AuthorizationService(
PolicyConfigurationFactory factory, Policy policy, String contextId,
Supplier<Subject> subjectSupplier, Supplier<PrincipalMapper> principalMapperSupplier) {
try {
this.factory = factory;
this.policyConfigurationFactory = factory;
this.policyConfiguration = factory.getPolicyConfiguration(contextId, false);
this.policy = policy;
this.contextId = contextId;
Expand Down Expand Up @@ -242,10 +239,10 @@ public void addPermissionsToPolicy(JakartaPermissions jakartaPermissions) {

public void removeStatementsFromPolicy(Set<String> declaredRoles) {
try {
boolean inService = factory.inService(contextId);
boolean inService = policyConfigurationFactory.inService(contextId);

// Open policy configuration
PolicyConfiguration policyConfiguration = factory.getPolicyConfiguration(contextId, false);
PolicyConfiguration policyConfiguration = policyConfigurationFactory.getPolicyConfiguration(contextId, false);

policyConfiguration.removeUncheckedPolicy();
policyConfiguration.removeExcludedPolicy();
Expand Down Expand Up @@ -286,7 +283,7 @@ public void removeStatementsFromPolicy(Set<String> declaredRoles) {
*/
public boolean linkPolicy(String linkedContextId, boolean lastInService) {
try {
boolean inService = factory.inService(contextId);
boolean inService = policyConfigurationFactory.inService(contextId);

if (linkedContextId == null) {
return inService;
Expand All @@ -298,8 +295,8 @@ public boolean linkPolicy(String linkedContextId, boolean lastInService) {

// Only do the link if the named policyConfiguration is not inService.
if (!inService) {
PolicyConfiguration policyConfiguration = factory.getPolicyConfiguration(contextId, false);
PolicyConfiguration linkedPolicyConfiguration = factory.getPolicyConfiguration(linkedContextId, false);
PolicyConfiguration policyConfiguration = policyConfigurationFactory.getPolicyConfiguration(contextId, false);
PolicyConfiguration linkedPolicyConfiguration = policyConfigurationFactory.getPolicyConfiguration(linkedContextId, false);
policyConfiguration.linkConfiguration(linkedPolicyConfiguration);
}

Expand Down Expand Up @@ -340,7 +337,7 @@ public static boolean linkPolicy(String contextId, String linkedContextId, boole

public void commitPolicy() {
try {
if (!factory.inService(contextId)) {
if (!policyConfigurationFactory.inService(contextId)) {

// Note that it is presumed that the policyConfiguration exists, and that
// it is populated with the desired policy statements.
Expand Down Expand Up @@ -380,7 +377,7 @@ public static void commitPolicy(String contextId) {
public void refresh() {
// Refresh policy if the context was in service
try {
if (factory.inService(contextId)) {
if (policyConfigurationFactory.inService(contextId)) {
getPolicy().refresh();
}
} catch (PolicyContextException e) {
Expand Down Expand Up @@ -501,18 +498,17 @@ public Object invokeBeanMethod(Object bean, Method beanClassMethod, Object[] met
return runInScope(() -> beanClassMethod.invoke(bean, methodParameters));
}


/**
* Inform the policy module to take the named policy context out of service. The policy context is transitioned to the
* deleted state.
*
*/
public void deletePolicy() {
try {
boolean wasInService = factory.inService(contextId);
boolean wasInService = policyConfigurationFactory.inService(contextId);

// Find the PolicyConfig and delete it.
factory.getPolicyConfiguration(contextId, false).delete();
policyConfigurationFactory.getPolicyConfiguration(contextId, false).delete();

// Only do refresh policy if the deleted context was in service
if (wasInService) {
Expand Down Expand Up @@ -543,7 +539,6 @@ public static void deletePolicy(String contextId) {
}
}


boolean checkPermission(Permission permissionToBeChecked) {
LOG.log(DEBUG, "checkPermission(permissionToBeChecked={0})", permissionToBeChecked);
return getPolicy().implies(permissionToBeChecked);
Expand Down Expand Up @@ -590,26 +585,86 @@ public Object runInScope(ThrowableSupplier<Object> supplier) throws Throwable {
}
}

private static PolicyConfigurationFactory installFactory(Class<?> factoryClass) {
public static PolicyConfigurationFactory installPolicyConfigurationFactory(Class<?> factoryClass) {
if (factoryClass == null) {
return null;
}

PolicyConfigurationFactory existingFactory = PolicyConfigurationFactory.get();
if (existingFactory.getClass().equals(factoryClass)) {
return existingFactory; // first one
}

PolicyConfigurationFactory newFactory = null;
try {
newFactory = (PolicyConfigurationFactory)
factoryClass.getDeclaredConstructor(PolicyConfigurationFactory.class)
.newInstance(existingFactory);
} catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) {
// not available
}

if (newFactory == null) {
try {
newFactory = (PolicyConfigurationFactory)
factoryClass.getDeclaredConstructor()
.newInstance();
} catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) {
throw new IllegalStateException(e);
}
}

PolicyConfigurationFactory.setPolicyConfigurationFactory(newFactory);
System.setProperty(PolicyConfigurationFactory.FACTORY_NAME, factoryClass.getName());

return getConfigurationFactory();
return PolicyConfigurationFactory.get();
}

private static Policy installPolicy(Class<? extends Policy> policyClass) {
try {
PolicyFactory.getPolicyFactory().setPolicy(policyClass.getConstructor().newInstance());
public static PolicyFactory installPolicyFactory(Class<?> factoryClass) {
if (factoryClass == null) {
return null;
}

return PolicyFactory.getPolicyFactory().getPolicy();
PolicyFactory existingFactory = PolicyFactory.getPolicyFactory();
if (existingFactory.getClass().equals(factoryClass)) {
return existingFactory; // first one
}

PolicyFactory newFactory = null;
try {
newFactory = (PolicyFactory)
factoryClass.getDeclaredConstructor(PolicyFactory.class)
.newInstance(existingFactory);
} catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) {
throw new IllegalStateException(e);
// not available
}

if (newFactory == null) {
try {
newFactory = (PolicyFactory)
factoryClass.getDeclaredConstructor()
.newInstance();
} catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) {
throw new IllegalStateException(e);
}
}

PolicyFactory.setPolicyFactory(newFactory);
System.setProperty(PolicyFactory.FACTORY_NAME, factoryClass.getName());

return PolicyFactory.getPolicyFactory();
}

private static PolicyConfigurationFactory getConfigurationFactory() {
public static Policy installPolicy(Class<? extends Policy> policyClass) {
if (policyClass == null) {
return null;
}

try {
return PolicyConfigurationFactory.getPolicyConfigurationFactory();
} catch (ClassNotFoundException | PolicyContextException e) {
PolicyFactory.getPolicyFactory().setPolicy(policyClass.getConstructor().newInstance());

return PolicyFactory.getPolicyFactory().getPolicy();
} catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) {
throw new IllegalStateException(e);
}
}
Expand Down Expand Up @@ -650,7 +705,8 @@ private PrincipalMapper getDefaultRoleMapper(String contextId) {
}

private static Collection<String> getAllDeclaredRoles() {
return getConfigurationFactory()
return PolicyConfigurationFactory
.get()
.getPolicyConfiguration()
.getPerRolePermissions()
.keySet();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Contributors to the Eclipse Foundation.
* Copyright (c) 2023, 2024 Contributors to the Eclipse Foundation.
* Copyright (c) 2019, 2021 OmniFaces. All rights reserved.
*
* This program and the accompanying materials are made available under the
Expand Down Expand Up @@ -33,6 +33,10 @@ public class DefaultPolicyConfigurationFactory extends PolicyConfigurationFactor

private static final ConcurrentMap<String, DefaultPolicyConfigurationStateMachine> configurators = new ConcurrentHashMap<>();

public DefaultPolicyConfigurationFactory() {
super(null);
}

@Override
public PolicyConfiguration getPolicyConfiguration(String contextID, boolean remove) throws PolicyContextException {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Contributors to the Eclipse Foundation.
* Copyright (c) 2023, 2024 Contributors to the Eclipse Foundation.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand All @@ -24,6 +24,10 @@ public class DefaultPolicyFactory extends PolicyFactory {

private static Map<String, Policy> idToPolicyMap = new ConcurrentHashMap<>();

public DefaultPolicyFactory() {
super(null);
}

// get/set global (system wide) policy?

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Contributors to Eclipse Foundation.
* Copyright (c) 2021, 2024 Contributors to Eclipse Foundation.
* Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
Expand All @@ -24,12 +24,12 @@

/**
* Abstract factory and finder class for obtaining the instance of the class that implements the
* PolicyConfigurationFactory of a provider.
*
* PolicyConfigurationFactory of a provider.
*
* <p>
* The factory will be used to instantiate PolicyConfiguration objects that will be used by the deployment tools of the
* container to create and manage policy contexts within the Policy Provider.
*
*
* <P>
* Implementation classes must have a public no argument constructor that may be used to create an operational instance
* of the factory implementation class.
Expand All @@ -41,23 +41,27 @@
*/
public class SimplePolicyConfigurationFactory extends PolicyConfigurationFactory {

public SimplePolicyConfigurationFactory() {
super(null);
}

/**
* This method is used to obtain an instance of the provider specific class that implements the PolicyConfiguration
* interface that corresponds to the identified policy context within the provider. The methods of the
* PolicyConfiguration interface are used to define the policy statements of the identified policy context.
*
*
* <P>
* If at the time of the call, the identified policy context does not exist in the provider, then the policy context
* will be created in the provider and the Object that implements the context's PolicyConfiguration Interface will be
* returned. If the state of the identified context is "deleted" or "inService" it will be transitioned to the "open"
* state as a result of the call. The states in the lifecycle of a policy context are defined by the PolicyConfiguration
* interface.
*
*
* <P>
* For a given value of policy context identifier, this method must always return the same instance of
* PolicyConfiguration and there must be at most one actual instance of a PolicyConfiguration with a given policy
* context identifier (during a process context).
*
*
* <P>
* To preserve the invariant that there be at most one PolicyConfiguration object for a given policy context, it may be
* necessary for this method to be thread safe.
Expand Down

0 comments on commit b21ccd6

Please sign in to comment.