The change is introduced in SAP NetWeaver 7.5 SP_COR (SP25) code line.
3154658-Missing Authorization check in SAP NetWeaver Application Server for Applocking service
Following actions have been introduced:
- logical_locking_create
- app_locking_administrative
Following roles have been introduced:
- APP_LOCKING_CREATE
- Action logical_locking_create is assigned to this role and is needed to invoke LogicalLockingFactory.createLogicalLocking(..).
- APP_LOCKING_ADMIN
- Action app_locking_administrative and action logical_locking_create are assigned to this role and is needed to use LogicalLockingFactory.createLogicalLocking(..) and AppLockingRuntimeInterface methods.
Following roles have been extended:
- Administrator - action logical_locking_create and action app_locking_administrative are assigned to this role.
Following property has been added to Applocking service:
- secureMode - with predefined values - Off / On / Preview.
- Off - reverts the old behavior without any checks;
- On - full security is enabled. I.e. guest/anonymous users are not allowed, only users with required roles will be allowed to use the functionality;
- Preview - Similar to “On” but instead of breaking the functionality only exception with severity “Error” will be logged in the defaultTrace files, allowing the customers to adopt to the new changes;
The property is offline modifiable (i.e. requires AS Java restart) and will be added in "Expert" view
Default value for the property:
- At the beginning it will be set to Off until the internal adoption is finished (7.50 SP25). No documentation for the customers will be available. It is not expected for the customers to know about the new behavior;
- After finishing with internal adoption the value will be set to Preview (7.50 SP26) which will allow the customers to adopt to the new functionality. Technical note for customers will support this activity;
- Finally the property will be set to On (7.50 SP 27) at that time few issues should be handled;
No roles are needed in the following cases:
- AppLockingRuntimeInterface methods are called in system thread.
- AppLockingRuntimeInterface methods are called with a user under Administrator role.
- New LogicalLockingFactory is created in system thread.
- New LogicalLockingFactory is created with user under Administrator role.
Unauthorized user will receive an exceptions similar to this one:
EXCEPTION]
java.lang.SecurityException: The user does not have permission: applocking, Action: logical_locking_create
at com.sap.engine.services.applocking.AppLockingAccessPermissionProvider.checkAccessPermission(AppLockingAccessPermissionProvider.java:20)
at com.sap.engine.services.applocking.LogicalLockingFactoryImpl.createLogicalLocking(LogicalLockingFactoryImpl.java:43)
at sun.reflect.GeneratedMethodAccessor498.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
Which are the affected methods:
1.LogicalLockingFactory methods are protected. If you lookup "/LogicalLockingFactory" you should adopt your application.
createLogicalLocking(...)
2. AppLockingRuntimeInterface methods are protected. If you look up "/applocking" you should adopt your application.
registerManagementListener(...)
getTimeStatisticsEntries()
enableTimeStatistics()
disableTimeStatistics()
resetTimeStatistics()
getLifetimeDescriptions()
getLifetimeDescriptionsAsProperties()
getTimeStatisticsEntriesAsProperties()
How to adopt the Applocking authorization change:
Define a new role or reuse the predefined one:
- Define the new role in SDA META-INF/actions.xml or META-INF/authorization-configuration.xml file. If you use Japro, the file path is psrv/server/descriptors/authorization-configuration.xml (BeginPrimaryServiceComponent) or ear/dist/META-INF/actions.xml (BeginJ2EEApplicationComponent).You can do this by adding the following:
<BUSINESSSERVICE NAME="COMPONENT NAME">
<DESCRIPTION LOCALE="en" VALUE="COMPONENT_DESCRIPTION"/>
<ACTION NAME="logical_locking_create">
<DESCRIPTION LOCALE="en" VALUE="Allows calls to create logical locking, i.e. to call LogicalLockingFactoryImpl.createLogicalLocking(...)"/>
<PERMISSION CLASS="com.sap.engine.services.applocking.AppLockingAccessPermission" NAME="applocking" VALUE="logical_locking_create"/>
</ACTION>
<ROLE NAME="SOME_ROLE_NAME">
<ASSIGNEDACTION NAME="logical_locking_create"/>
</ROLE>
</BUSINESSSERVICE>
OR
- Assign one of the following roles to the calling user
- APP_LOCKING_CREATE
- APP_LOCKING_ADMIN
Assign this role to an existing user:
- Use useradmin
- Create/assign it programmatically
private void createAssignUser() throws UMException {
IServiceUserFactory userFactory = UMFactory.getServiceUserFactory();
IRoleFactory rf = UMFactory.getRoleFactory();
// Get the desired role
IRole role = rf.getRoleByUniqueName(DESIRED_ROLE);
String roleUniqueID = adminRole.getUniqueID();
// Try to get the user
IUser user= null;
try {
user= userFactory.getServiceUser(DESIRED_USER_NAME);
// Add user to DESIRED_ROLE role if it is still not in this role
boolean isMember = user.isMemberOfRole(roleUniqueID , true);
if (!isMember) {
rf.addUserToRole(user.getUniqueID(), roleUniqueID );
}
} catch (NoSuchUserException noSuchUserExc) {
// The user doesn't exist, create it
try {
userFactory.createServiceUser(DESIRED_USER_NAME);
user = userFactory.getServiceUser(DESIRED_USER_NAME);
// Add user to DESIRED_ROLE role without a check.
// If the user is created on another server node and it is still not
// granted DESIRED_ROLE role we ensure here we are not going to
// use it before we grant it this role. Thus we do not need to have
// special synchronization in cluster
rf.addUserToRole(user.getUniqueID(), roleUniqueID);
} catch (UserAlreadyExistsException uaex) {
user = userFactory.getServiceUser(DESIRED_USER_NAME);
boolean isMember = user.isMemberOfRole(roleUniqueID, true);
if (!isMember) {
rf.addUserToRole(user.getUniqueID(), roleUniqueID);
}
}
}
}
Use the new user:
- Programmatically
Using Subject.doAs() method. Run code with user which has desired role. Here is an example:
// Or create separate class
PrivilegedExceptionAction codeToBeExecutedWithGivenUser = new PrivilegedExceptionAction() { public Object run() throws Exception { //Code to be executed with given user and return result return null; } };
IUser doAsUser = UMFactory.getUserFactory().getUserByLogonID("RUN_AS_USER"); // create new Subject final Subject runAsSubject = new Subject(); runAsSubject.getPrincipals().add(doAsUser); try { Object result = Subject.doAs(runAsSubject, codeToBeExecutedWithGivenUser); } catch (PrivilegedActionException pae) { // Process, wrap and rethrow exception }
NB: Here it is better not to use Administrator(could be removed from UME) user or user in the role Administrator(could be very slow). It is beeter to be the current authenticated user or a technical user.
- Declarative - run-as in ejb-jar.xml or web.xml
ejb-jar.xml
<ejb-jar>
<assembly-descriptor>
<security-role>
<role-name>SOME_ROLE_NAME</role-name>
</security-role>
</assembly-descriptor>
......
<enterprise-beans>
<message-driven>
....
<security-identity>
<run-as>
<role-name>SOME_ROLE_NAME</role-name>
</run-as>
</security-identity>
</message-driven>
</enterprise-beans>
</ejb-jar>
ejb-j2ee-engine.xml:
<security-permission>
<security-role-map>
<role-name>SOME_ROLE_NAME</role-name>
<server-role-name>APP_LOCKING_CREATE</server-role-name>
</security-role-map>
</security-permission>- Annotations in ejb class instate changes in ejb-jar.xml :
@DeclareRoles({"SOME_ROLE_NAME"})
@RunAs("SOME_ROLE_NAME")
web.xml:
<web-app>
<servlet>
<servlet-name>...</servlet-name>
...
<run-as>
<role-name>MyServletRole</role-name>
</run-as>
</servlet>
<security-role>
<role-name>MyServletRole</role-name>
</security-role>
</web-app>
web-j2ee-engine.xml
<web-j2ee-engine>
<security-role-map>
<role-name>MyServletRole</role-name>
<server-role-name>MyASJavaRole</server-role-name>
</security-role-map>
</web-j2ee-engine>
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.