Skip to content

Commit

Permalink
Restructure and update Jakarta authorization code
Browse files Browse the repository at this point in the history
- Update to have interfaces in EJB and Web bundles so that can reference
actual classes instead of using Object
- Move JaccService function to the corresponding EJB and Web projects to
keep the methods with their appropriate container function
- Update to add PrincipalMapper to PolicyContextHandlerImpl in
preparation of adding PrincipalMapper implementation
- Update to use instance methods instead of static methods in
PolicyConfigurationManager
- Inline most of the Validator and Propagator function into the EJB and
Web classes except for EJB propagator which is used by both EJB function
and base Jacc function
  • Loading branch information
jhanders34 committed Dec 4, 2024
1 parent 4a4c285 commit e93defc
Show file tree
Hide file tree
Showing 71 changed files with 2,368 additions and 3,289 deletions.
11 changes: 7 additions & 4 deletions dev/com.ibm.ws.ejbcontainer.security/bnd.bnd
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#*******************************************************************************
# Copyright (c) 2017, 2023 IBM Corporation and others.
# Copyright (c) 2017, 2024 IBM Corporation and others.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License 2.0
# which accompanies this distribution, and is available at
Expand All @@ -24,6 +24,9 @@ bVersion=1.0
WS-TraceGroup: \
SecurityCollaborator

Export-Package: \
com.ibm.ws.ejbcontainer.security.jacc

Private-Package: \
com.ibm.ws.ejbcontainer.security.internal.*

Expand All @@ -45,9 +48,9 @@ Service-Component: \
securityReadyService=com.ibm.ws.security.ready.SecurityReadyService; \
unauthenticatedSubjectService=com.ibm.ws.security.authentication.UnauthenticatedSubjectService; \
credentialsService=com.ibm.ws.security.credentials.CredentialsService; \
jaccService=com.ibm.ws.security.authorization.jacc.JaccService;\
dynamic:='jaccService'; \
optional:='jaccService'; \
eJBJaccService=com.ibm.ws.ejbcontainer.security.jacc.EJBJaccService;\
dynamic:='eJBJaccService'; \
optional:='eJBJaccService'; \
properties:="service.vendor=IBM"

instrument.classesExcludes: com/ibm/ws/ejbcontainer/security/internal/resources/*.class
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/*******************************************************************************
* Copyright (c) 2011, 2023 IBM Corporation and others.
* Copyright (c) 2011, 2024 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-2.0/
*
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
Expand Down Expand Up @@ -51,7 +51,7 @@
import com.ibm.ws.ejbcontainer.EJBRequestData;
import com.ibm.ws.ejbcontainer.EJBSecurityCollaborator;
import com.ibm.ws.ejbcontainer.security.internal.jacc.EJBJaccAuthorizationHelper;
import com.ibm.ws.ejbcontainer.security.internal.jacc.JaccUtil;
import com.ibm.ws.ejbcontainer.security.jacc.EJBJaccService;
import com.ibm.ws.ffdc.annotation.FFDCIgnore;
import com.ibm.ws.runtime.metadata.ComponentMetaData;
import com.ibm.ws.runtime.metadata.MetaData;
Expand All @@ -62,7 +62,6 @@
import com.ibm.ws.security.authentication.principals.WSIdentity;
import com.ibm.ws.security.authentication.principals.WSPrincipal;
import com.ibm.ws.security.authorization.AuthorizationService;
import com.ibm.ws.security.authorization.jacc.JaccService;
import com.ibm.ws.security.collaborator.CollaboratorUtils;
import com.ibm.ws.security.context.SubjectManager;
import com.ibm.ws.security.credentials.CredentialsService;
Expand All @@ -79,13 +78,13 @@ public class EJBSecurityCollaboratorImpl implements EJBSecurityCollaborator<Secu
protected static final String KEY_SECURITY_SERVICE = "securityService";
protected static final String KEY_CREDENTIAL_SERVICE = "credentialsService";
protected static final String KEY_UNAUTHENTICATED_SUBJECT_SERVICE = "unauthenticatedSubjectService";
protected static final String KEY_JACC_SERVICE = "jaccService";
protected static final String KEY_EJB_JACC_SERVICE = "eJBJaccService";
protected static final String KEY_SECURITY_READY_SERVICE = "securityReadyService";
private SecurityReadyService securityReadyService;
protected final AtomicServiceReference<SecurityService> securityServiceRef = new AtomicServiceReference<SecurityService>(KEY_SECURITY_SERVICE);
private final AtomicServiceReference<CredentialsService> credServiceRef = new AtomicServiceReference<CredentialsService>(KEY_CREDENTIAL_SERVICE);
private final AtomicServiceReference<UnauthenticatedSubjectService> unauthenticatedSubjectServiceRef = new AtomicServiceReference<UnauthenticatedSubjectService>(KEY_UNAUTHENTICATED_SUBJECT_SERVICE);
private final AtomicServiceReference<JaccService> jaccService = new AtomicServiceReference<JaccService>(KEY_JACC_SERVICE);
private final AtomicServiceReference<EJBJaccService> ejbJaccService = new AtomicServiceReference<EJBJaccService>(KEY_EJB_JACC_SERVICE);

protected SubjectManager subjectManager;
protected CollaboratorUtils collabUtils;
Expand All @@ -96,9 +95,9 @@ public class EJBSecurityCollaboratorImpl implements EJBSecurityCollaborator<Secu
private EJBAuthorizationHelper eah = this;

private boolean waitedForSecurity = false;

private static final String securityWaitTimeProperty = "io.openliberty.ejb.security.startWaitTime";

// wait time in seconds, default 0
private static final int securityWaitTime = AccessController.doPrivileged(new PrivilegedAction<Integer>() {
@Override
Expand Down Expand Up @@ -156,21 +155,21 @@ protected void unsetUnauthenticatedSubjectService(ServiceReference<Unauthenticat
unauthenticatedSubjectServiceRef.unsetReference(ref);
}

protected void setJaccService(ServiceReference<JaccService> reference) {
jaccService.setReference(reference);
eah = new EJBJaccAuthorizationHelper(jaccService);
protected void setEJBJaccService(ServiceReference<EJBJaccService> reference) {
ejbJaccService.setReference(reference);
eah = new EJBJaccAuthorizationHelper(ejbJaccService);
}

protected void unsetJaccService(ServiceReference<JaccService> reference) {
jaccService.unsetReference(reference);
protected void unsetEJBJaccService(ServiceReference<EJBJaccService> reference) {
ejbJaccService.unsetReference(reference);
eah = this;
}

protected void activate(ComponentContext cc, Map<String, Object> props) {
securityServiceRef.activate(cc);
credServiceRef.activate(cc);
unauthenticatedSubjectServiceRef.activate(cc);
jaccService.activate(cc);
ejbJaccService.activate(cc);
ejbSecConfig = new EJBSecurityConfigImpl(props);
}

Expand All @@ -186,7 +185,7 @@ protected void deactivate(ComponentContext cc) {
securityServiceRef.deactivate(cc);
credServiceRef.deactivate(cc);
unauthenticatedSubjectServiceRef.deactivate(cc);
jaccService.deactivate(cc);
ejbJaccService.deactivate(cc);
}

/**
Expand Down Expand Up @@ -237,7 +236,7 @@ public SecurityCookieImpl preInvoke(EJBRequestData request) throws EJBAccessDeni
@Override
public void postInvoke(EJBRequestData request, SecurityCookieImpl preInvokeResult) throws EJBAccessDeniedException {
if (preInvokeResult != null) {
JaccService js = jaccService.getService();
EJBJaccService js = ejbJaccService.getService();
if (js != null) {
js.resetPolicyContextHandlerInfo();
}
Expand Down Expand Up @@ -726,7 +725,7 @@ private boolean setUnauthenticatedSubjectIfNeeded(Subject invokedSubject, Subjec

@Override
public boolean areRequestMethodArgumentsRequired() {
JaccService js = jaccService.getService();
EJBJaccService js = ejbJaccService.getService();
boolean result = false;
if (js != null) {
result = js.areRequestMethodArgumentsRequired();
Expand All @@ -741,13 +740,12 @@ public boolean areRequestMethodArgumentsRequired() {
*/
@Override
public void componentMetaDataCreated(MetaDataEvent<ComponentMetaData> event) {
JaccService js = jaccService.getService();
EJBJaccService js = ejbJaccService.getService();
if (js != null) {
MetaData metaData = event.getMetaData();
if (metaData instanceof BeanMetaData) {
BeanMetaData bmd = (BeanMetaData) metaData;
js.propagateEJBRoles(bmd.j2eeName.getApplication(), bmd.j2eeName.getModule(), bmd.enterpriseBeanName, bmd.ivRoleLinkMap,
JaccUtil.convertMethodInfoList(JaccUtil.mergeMethodInfos(bmd)));
js.propagateEJBRoles(bmd);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/*******************************************************************************
* Copyright (c) 2015,2022 IBM Corporation and others.
* Copyright (c) 2015,2024 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-2.0/
*
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
Expand Down Expand Up @@ -33,9 +33,9 @@
import com.ibm.ws.ejbcontainer.security.internal.EJBAccessDeniedException;
import com.ibm.ws.ejbcontainer.security.internal.EJBAuthorizationHelper;
import com.ibm.ws.ejbcontainer.security.internal.TraceConstants;
import com.ibm.ws.ejbcontainer.security.jacc.EJBJaccService;
import com.ibm.ws.security.audit.Audit;
import com.ibm.ws.security.authentication.principals.WSPrincipal;
import com.ibm.ws.security.authorization.jacc.JaccService;
import com.ibm.wsspi.kernel.service.utils.AtomicServiceReference;

/**
Expand All @@ -44,9 +44,9 @@
public class EJBJaccAuthorizationHelper implements EJBAuthorizationHelper {
private static final TraceComponent tc = Tr.register(EJBJaccAuthorizationHelper.class);

private AtomicServiceReference<JaccService> jaccServiceRef = null;
private AtomicServiceReference<EJBJaccService> jaccServiceRef = null;

public EJBJaccAuthorizationHelper(AtomicServiceReference<JaccService> jaccServiceRef) {
public EJBJaccAuthorizationHelper(AtomicServiceReference<EJBJaccService> jaccServiceRef) {
this.jaccServiceRef = jaccServiceRef;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*******************************************************************************
* Copyright (c) 2024 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package com.ibm.ws.ejbcontainer.security.jacc;

import java.util.List;

import javax.ejb.EnterpriseBean;
import javax.security.auth.Subject;

import com.ibm.ejs.container.BeanMetaData;

public interface EJBJaccService {

/**
* Propagates EJB role mapping information to JACC.
*
* @param bmd Bean meta data
*/
public void propagateEJBRoles(BeanMetaData bmd);

/**
* Validates whether given Subject is granted to access the specified resource.
*
* @param applicationName Application name
* @param moduleName Module name
* @param beanName Bean name
* @param methodName Method name
* @param methodInterface Method interface
* @param methodName Method signature
* @param methodParameters The list of method parameters. this is optional and null is accepted.
* @param bean EnterpriseBean object this is an optional and null is allowed.
* @param subject Subject object to be authorized.
* @return true if the specified subject is granted to access the specified resource.
*/
public boolean isAuthorized(String applicationName,
String moduleName,
String beanName,
String methodName,
String methodInterface,
String methodSignature,
List<Object> methodParameters,
EnterpriseBean bean,
Subject subject);

/**
* Validates whether given Subject is a member of the specified role
*
* @param applicationName Application name
* @param moduleName Module name
* @param beanName Bean name
* @param methodName Method name
* @param methodInterface Method interface
* @param methodParameters The list of method parameters. this is optional and null is accepted.
* @param role Role name
* @param bean EnterpriseBean object this is an optional and null is allowed.
* @param subject Subject object to be authorized.
* @return true if the specified subject has a member of the specified role.
*/
public boolean isSubjectInRole(String applicationName,
String moduleName,
String beanName,
String methodName,
List<Object> methodParameters,
String role,
EnterpriseBean bean,
Subject subject);

/**
* Returns whether RequestMethodArguments are required for authorization decision for EJB.
*
* @return true if RequestMethodArguments are required. false otherwise.
*/
public boolean areRequestMethodArgumentsRequired();

/**
* Reset the policyContext Handler as per JACC specification
*/
public void resetPolicyContextHandlerInfo();
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
/*******************************************************************************
* Copyright (c) 2015 IBM Corporation and others.
* Copyright (c) 2024 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
/**
* @version 1.0
*/
@org.osgi.annotation.versioning.Version("1.0")
package com.ibm.ws.security.authorization.jacc.web;
@TraceOptions(traceGroup = TraceConstants.TRACE_GROUP, messageBundle = TraceConstants.MESSAGE_BUNDLE)
package com.ibm.ws.ejbcontainer.security.jacc;

import com.ibm.websphere.ras.annotation.TraceOptions;
import com.ibm.ws.ejbcontainer.security.internal.TraceConstants;
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/*******************************************************************************
* Copyright (c) 2015, 2022 IBM Corporation and others.
* Copyright (c) 2015, 2024 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-2.0/
*
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
Expand Down Expand Up @@ -42,8 +42,8 @@
import com.ibm.ws.ejbcontainer.EJBRequestData;
import com.ibm.ws.ejbcontainer.InternalConstants;
import com.ibm.ws.ejbcontainer.security.internal.EJBAccessDeniedException;
import com.ibm.ws.ejbcontainer.security.jacc.EJBJaccService;
import com.ibm.ws.security.authentication.principals.WSPrincipal;
import com.ibm.ws.security.authorization.jacc.JaccService;
import com.ibm.wsspi.kernel.service.utils.AtomicServiceReference;

import test.common.SharedOutputManager;
Expand All @@ -58,20 +58,20 @@ public class EJBJaccAuthorizationHelperTest {
@Rule
public TestRule managerRule = outputMgr;

static final String KEY_JACC_SERVICE = "jaccService";
static final String KEY_EJB_JACC_SERVICE = "eJBJaccService";

private final Mockery context = new JUnit4Mockery();
private final EJBRequestData erd = context.mock(EJBRequestData.class);
private final EJBMethodMetaData emmd = context.mock(EJBMethodMetaData.class);
private final EJBComponentMetaData ecmd = context.mock(EJBComponentMetaData.class);
private final J2EEName jen = context.mock(J2EEName.class);
@SuppressWarnings("unchecked")
private final ServiceReference<JaccService> jsr = context.mock(ServiceReference.class, "jaccServiceRef");
private final JaccService js = context.mock(JaccService.class);
private final ServiceReference<EJBJaccService> jsr = context.mock(ServiceReference.class, "jaccServiceRef");
private final EJBJaccService js = context.mock(EJBJaccService.class);
private final ComponentContext cc = context.mock(ComponentContext.class);
private final EnterpriseBean eb = context.mock(EnterpriseBean.class);
private final WSPrincipal wp = new WSPrincipal("securityName", "accessId", "BASIC");
private final AtomicServiceReference<JaccService> ajsr = new AtomicServiceReference<JaccService>(KEY_JACC_SERVICE);
private final AtomicServiceReference<EJBJaccService> ajsr = new AtomicServiceReference<EJBJaccService>(KEY_EJB_JACC_SERVICE);

/**
* Tests authorizeEJB method normal role.
Expand Down Expand Up @@ -118,7 +118,7 @@ public void authorizeEJBNormalNoMethodArgDenied() {
will(returnValue(0L));
allowing(jsr).getProperty(Constants.SERVICE_RANKING);
will(returnValue(0));
one(cc).locateService("jaccService", jsr);
one(cc).locateService("eJBJaccService", jsr);
will(returnValue(js));
one(js).isAuthorized(APP_NAME, MODULE_NAME, BEAN_NAME, METHOD_NAME, METHOD_INTERFACE_NAME, METHOD_SIGNATURE, null, null, SUBJECT);
will(returnValue(false));
Expand Down Expand Up @@ -185,7 +185,7 @@ public void authorizeEJBNormalMethodArgEenterpriseBeanGranted() {
will(returnValue(0L));
allowing(jsr).getProperty(Constants.SERVICE_RANKING);
will(returnValue(0));
one(cc).locateService("jaccService", jsr);
one(cc).locateService("eJBJaccService", jsr);
will(returnValue(js));
one(js).isAuthorized(APP_NAME, MODULE_NAME, BEAN_NAME, METHOD_NAME, METHOD_INTERFACE_NAME, METHOD_SIGNATURE, Arrays.asList(ARG_LIST), eb, SUBJECT);
will(returnValue(true));
Expand Down Expand Up @@ -243,7 +243,7 @@ public void isCallerInRoleFalse() {
will(returnValue(0L));
allowing(jsr).getProperty(Constants.SERVICE_RANKING);
will(returnValue(0));
one(cc).locateService("jaccService", jsr);
one(cc).locateService("eJBJaccService", jsr);
will(returnValue(js));
one(js).isSubjectInRole(APP_NAME, MODULE_NAME, BEAN_NAME, METHOD_NAME, Arrays.asList(ARG_LIST), ROLE, eb, SUBJECT);
will(returnValue(false));
Expand Down Expand Up @@ -294,7 +294,7 @@ public void isCallerInRoleTrue() {
will(returnValue(0L));
allowing(jsr).getProperty(Constants.SERVICE_RANKING);
will(returnValue(0));
one(cc).locateService("jaccService", jsr);
one(cc).locateService("eJBJaccService", jsr);
will(returnValue(js));
one(js).isSubjectInRole(APP_NAME, MODULE_NAME, BEAN_NAME, METHOD_NAME, null, ROLE, null, SUBJECT);
will(returnValue(true));
Expand Down
Loading

0 comments on commit e93defc

Please sign in to comment.