Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce the fragment app check when adding the app role association #6185

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.wso2.carbon.identity.application.common.model.ApplicationBasicInfo;
import org.wso2.carbon.identity.application.common.model.AuthorizedScopes;
import org.wso2.carbon.identity.application.common.model.ServiceProvider;
import org.wso2.carbon.identity.application.mgt.ApplicationConstants;
import org.wso2.carbon.identity.application.mgt.ApplicationManagementService;
import org.wso2.carbon.identity.application.mgt.AuthorizedAPIManagementService;
import org.wso2.carbon.identity.application.mgt.AuthorizedAPIManagementServiceImpl;
Expand All @@ -34,6 +35,7 @@
import org.wso2.carbon.identity.application.mgt.internal.cache.ServiceProviderByResourceIdCache;
import org.wso2.carbon.identity.application.mgt.internal.cache.ServiceProviderIDCacheKey;
import org.wso2.carbon.identity.application.mgt.internal.cache.ServiceProviderResourceIdCacheKey;
import org.wso2.carbon.identity.core.util.IdentityUtil;
import org.wso2.carbon.identity.role.v2.mgt.core.exception.IdentityRoleManagementClientException;
import org.wso2.carbon.identity.role.v2.mgt.core.exception.IdentityRoleManagementException;
import org.wso2.carbon.identity.role.v2.mgt.core.exception.IdentityRoleManagementServerException;
Expand Down Expand Up @@ -92,7 +94,7 @@ public void preAddRole(String roleName, List<String> userList, List<String> grou
throws IdentityRoleManagementException {

if (APPLICATION.equalsIgnoreCase(audience)) {
validateApplicationRoleAudience(audienceId, tenantDomain);
validateApplicationTypeAndRoleAudience(audienceId, tenantDomain);
validatePermissionsForApplication(permissions, audienceId, tenantDomain);
}
}
Expand Down Expand Up @@ -519,7 +521,7 @@ public void postGetAssociatedApplicationIdsByRoleId(List<String> associatedAppli
* @param tenantDomain Tenant domain.
* @throws IdentityRoleManagementException Error occurred while validating application role audience.
*/
private void validateApplicationRoleAudience(String applicationId, String tenantDomain)
private void validateApplicationTypeAndRoleAudience(String applicationId, String tenantDomain)
throws IdentityRoleManagementException {

try {
Expand All @@ -536,6 +538,17 @@ private void validateApplicationRoleAudience(String applicationId, String tenant
throw new IdentityRoleManagementClientException(INVALID_AUDIENCE.getCode(),
"Application: " + applicationId + " does not have Application role audience type");
}

// Set thread local property to identify that the application is a fragment application. This property
// will be used in the role management component to identify the application type.
if (app.getSpProperties() != null && Arrays.stream(app.getSpProperties())
.anyMatch(property -> ApplicationConstants.IS_FRAGMENT_APP.equals(property.getName())
&& Boolean.parseBoolean(property.getValue()))) {
if (IdentityUtil.threadLocalProperties.get().get(ApplicationConstants.IS_FRAGMENT_APP) != null) {
IdentityUtil.threadLocalProperties.get().remove(ApplicationConstants.IS_FRAGMENT_APP);
}
IdentityUtil.threadLocalProperties.get().put(ApplicationConstants.IS_FRAGMENT_APP, Boolean.TRUE);
}
} catch (IdentityApplicationManagementException e) {
String errorMessage = "Error while retrieving the application for the given id: " + applicationId;
throw new IdentityRoleManagementServerException(UNEXPECTED_SERVER_ERROR.getCode(), errorMessage, e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,70 +75,78 @@ public class RoleManagementServiceImpl implements RoleManagementService {
private static final Log log = LogFactory.getLog(RoleManagementServiceImpl.class);
private final RoleDAO roleDAO = RoleMgtDAOFactory.getInstance().getRoleDAO();
private final UserIDResolver userIDResolver = new UserIDResolver();
private static final String IS_FRAGMENT_APP = "isFragmentApp";

@Override
public RoleBasicInfo addRole(String roleName, List<String> userList, List<String> groupList,
List<Permission> permissions, String audience, String audienceId, String tenantDomain)
throws IdentityRoleManagementException {

if (StringUtils.startsWithIgnoreCase(roleName, UserCoreConstants.INTERNAL_SYSTEM_ROLE_PREFIX)) {
String errorMessage = String.format("Invalid role name: %s. Role names with the prefix: %s, is not allowed"
+ " to be created from externally in the system.", roleName,
UserCoreConstants.INTERNAL_SYSTEM_ROLE_PREFIX);
throw new IdentityRoleManagementClientException(INVALID_REQUEST.getCode(), errorMessage);
}
if (isDomainSeparatorPresent(roleName)) {
// SCIM2 API only adds roles to the internal domain.
throw new IdentityRoleManagementClientException(INVALID_REQUEST.getCode(), "Invalid character: "
+ UserCoreConstants.DOMAIN_SEPARATOR + " contains in the role name: " + roleName + ".");
}
List<RoleManagementListener> roleManagementListenerList = RoleManagementServiceComponentHolder.getInstance()
.getRoleManagementListenerList();
for (RoleManagementListener roleManagementListener : roleManagementListenerList) {
if (roleManagementListener.isEnable()) {
roleManagementListener.preAddRole(roleName, userList, groupList,
permissions, audience, audienceId, tenantDomain);
try {
if (StringUtils.startsWithIgnoreCase(roleName, UserCoreConstants.INTERNAL_SYSTEM_ROLE_PREFIX)) {
String errorMessage = String.format("Invalid role name: %s. Role names with the prefix: %s, is not " +
"allowed to be created from externally in the system.", roleName,
UserCoreConstants.INTERNAL_SYSTEM_ROLE_PREFIX);
throw new IdentityRoleManagementClientException(INVALID_REQUEST.getCode(), errorMessage);
}
if (isDomainSeparatorPresent(roleName)) {
// SCIM2 API only adds roles to the internal domain.
throw new IdentityRoleManagementClientException(INVALID_REQUEST.getCode(), "Invalid character: "
+ UserCoreConstants.DOMAIN_SEPARATOR + " contains in the role name: " + roleName + ".");
}
List<RoleManagementListener> roleManagementListenerList = RoleManagementServiceComponentHolder.getInstance()
.getRoleManagementListenerList();
for (RoleManagementListener roleManagementListener : roleManagementListenerList) {
if (roleManagementListener.isEnable()) {
roleManagementListener.preAddRole(roleName, userList, groupList,
permissions, audience, audienceId, tenantDomain);
}
}
}

RoleManagementEventPublisherProxy roleManagementEventPublisherProxy = RoleManagementEventPublisherProxy
.getInstance();
roleManagementEventPublisherProxy.publishPreAddRoleWithException(roleName, userList, groupList, permissions,
audience, audienceId, tenantDomain);
RoleManagementEventPublisherProxy roleManagementEventPublisherProxy = RoleManagementEventPublisherProxy
.getInstance();
roleManagementEventPublisherProxy.publishPreAddRoleWithException(roleName, userList, groupList, permissions,
audience, audienceId, tenantDomain);

// Validate audience.
if (StringUtils.isNotEmpty(audience)) {
if (!(ORGANIZATION.equalsIgnoreCase(audience) || APPLICATION.equalsIgnoreCase(audience))) {
throw new IdentityRoleManagementClientException(INVALID_AUDIENCE.getCode(), "Invalid role audience");
}
if (ORGANIZATION.equalsIgnoreCase(audience)) {
validateOrganizationRoleAudience(audienceId, tenantDomain);
// Validate audience.
if (StringUtils.isNotEmpty(audience)) {
if (!(ORGANIZATION.equalsIgnoreCase(audience) || APPLICATION.equalsIgnoreCase(audience))) {
throw new IdentityRoleManagementClientException(INVALID_AUDIENCE.getCode(),
"Invalid role audience");
}
if (ORGANIZATION.equalsIgnoreCase(audience)) {
validateOrganizationRoleAudience(audienceId, tenantDomain);
audience = ORGANIZATION;
}
if (APPLICATION.equalsIgnoreCase(audience)) {
// audience validation done using listener.
audience = APPLICATION;
}
} else {
audience = ORGANIZATION;
audienceId = getOrganizationIdByTenantDomain(tenantDomain);
}
validatePermissions(permissions, audience, audienceId, tenantDomain);
RoleBasicInfo roleBasicInfo = roleDAO.addRole(roleName, userList, groupList, permissions, audience,
audienceId, tenantDomain);
roleManagementEventPublisherProxy.publishPostAddRole(roleBasicInfo.getId(), roleName, userList, groupList,
permissions, audience, audienceId, tenantDomain);
if (log.isDebugEnabled()) {
log.debug(String.format("%s added role of name : %s successfully.", getUser(tenantDomain), roleName));
}
RoleBasicInfo role = roleDAO.getRoleBasicInfoById(roleBasicInfo.getId(), tenantDomain);
for (RoleManagementListener roleManagementListener : roleManagementListenerList) {
if (roleManagementListener.isEnable()) {
roleManagementListener.postAddRole(role, roleName, userList,
groupList, permissions, audience, audienceId, tenantDomain);
}
}
if (APPLICATION.equalsIgnoreCase(audience)) {
// audience validation done using listener.
audience = APPLICATION;
return role;
} finally {
if (IdentityUtil.threadLocalProperties.get().get(IS_FRAGMENT_APP) != null) {
IdentityUtil.threadLocalProperties.get().remove(IS_FRAGMENT_APP);
}
} else {
audience = ORGANIZATION;
audienceId = getOrganizationIdByTenantDomain(tenantDomain);
}
validatePermissions(permissions, audience, audienceId, tenantDomain);
RoleBasicInfo roleBasicInfo = roleDAO.addRole(roleName, userList, groupList, permissions, audience, audienceId,
tenantDomain);
roleManagementEventPublisherProxy.publishPostAddRole(roleBasicInfo.getId(), roleName, userList, groupList,
permissions, audience, audienceId, tenantDomain);
if (log.isDebugEnabled()) {
log.debug(String.format("%s added role of name : %s successfully.", getUser(tenantDomain), roleName));
}
RoleBasicInfo role = roleDAO.getRoleBasicInfoById(roleBasicInfo.getId(), tenantDomain);
for (RoleManagementListener roleManagementListener : roleManagementListenerList) {
if (roleManagementListener.isEnable()) {
roleManagementListener.postAddRole(role, roleName, userList,
groupList, permissions, audience, audienceId, tenantDomain);
}
}
return role;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ public class RoleDAOImpl implements RoleDAO {
private static final String GROUPS = "groups";
private static final String PERMISSIONS = "permissions";
private static final String ASSOCIATED_APPLICATIONS = "associatedApplications";
private static final String IS_FRAGMENT_APP = "isFragmentApp";

@Override
public RoleBasicInfo addRole(String roleName, List<String> userList, List<String> groupList,
Expand Down Expand Up @@ -1609,8 +1610,8 @@ private void addRoleInfo(String roleId, String roleName, List<Permission> permis
try {
addRoleID(roleId, roleName, audienceRefId, tenantDomain, connection);
addPermissions(roleId, permissions, tenantDomain, connection);

if (APPLICATION.equals(audience) && !isOrganization(tenantDomain)) {
if (APPLICATION.equals(audience) && !isFragmentApp()) {
addAppRoleAssociation(roleId, audienceId, connection);
}
IdentityDatabaseUtil.commitTransaction(connection);
Expand All @@ -1626,6 +1627,23 @@ private void addRoleInfo(String roleId, String roleName, List<Permission> permis
}
}

/**
* Check whether the corresponding application is a fragment application. This check is using a thread local
* property which is set from the default role management listener.
*
* @return True if the application is a fragment application.
*/
private boolean isFragmentApp() {

if (IdentityUtil.threadLocalProperties.get().get(IS_FRAGMENT_APP) != null) {
boolean isFragmentApp = Boolean.parseBoolean(IdentityUtil.threadLocalProperties.get().
get(IS_FRAGMENT_APP).toString());
IdentityUtil.threadLocalProperties.get().remove(IS_FRAGMENT_APP);
ShanChathusanda93 marked this conversation as resolved.
Show resolved Hide resolved
return isFragmentApp;
}
return false;
}

@Override
public boolean isSharedRole(String roleId, String tenantDomain) throws IdentityRoleManagementException {

Expand Down
Loading