8ca8dd20ebc2bce7a35d77a4a426c04ab032c1a2
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/IPBlocklistTableWrapper.java
| ... | ... | @@ -23,11 +23,9 @@ import com.sap.sse.gwt.client.ErrorReporter; |
| 23 | 23 | import com.sap.sse.gwt.client.celltable.EntityIdentityComparator; |
| 24 | 24 | import com.sap.sse.gwt.client.celltable.RefreshableSelectionModel; |
| 25 | 25 | import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel; |
| 26 | -import com.sap.sse.security.shared.AdminRole; |
|
| 27 | -import com.sap.sse.security.shared.ServerAdminRole; |
|
| 28 | -import com.sap.sse.security.shared.dto.RoleWithSecurityDTO; |
|
| 29 | -import com.sap.sse.security.shared.dto.UserDTO; |
|
| 30 | -import com.sap.sse.security.shared.impl.SecuredSecurityTypes.ServerActions; |
|
| 26 | +import com.sap.sse.security.shared.HasPermissions.DefaultActions; |
|
| 27 | +import com.sap.sse.security.shared.WildcardPermission; |
|
| 28 | +import com.sap.sse.security.shared.impl.SecuredSecurityTypes; |
|
| 31 | 29 | import com.sap.sse.security.ui.client.UserService; |
| 32 | 30 | import com.sap.sse.security.ui.client.component.SelectedElementsCountingButton; |
| 33 | 31 | |
| ... | ... | @@ -35,7 +33,6 @@ abstract class IPBlocklistTableWrapper |
| 35 | 33 | extends TableWrapper<IpToTimedLockDTO, RefreshableSelectionModel<IpToTimedLockDTO>> { |
| 36 | 34 | private final UserService userService; |
| 37 | 35 | private final LabeledAbstractFilterablePanel<IpToTimedLockDTO> filterField; |
| 38 | - private final ServerActions unlockAction; |
|
| 39 | 36 | private final String errorMessageOnDataFailureString; |
| 40 | 37 | |
| 41 | 38 | protected abstract void fetchData(AsyncCallback<HashMap<String, TimedLock>> callback); |
| ... | ... | @@ -43,8 +40,8 @@ abstract class IPBlocklistTableWrapper |
| 43 | 40 | protected abstract void unlockIP(String ip, AsyncCallback<Void> asyncCallback); |
| 44 | 41 | |
| 45 | 42 | public IPBlocklistTableWrapper(final SailingServiceWriteAsync sailingServiceWrite, final UserService userService, |
| 46 | - final ServerActions unlockAction, final String errorMessageOnDataFailureString, |
|
| 47 | - final StringMessages stringMessages, final ErrorReporter errorReporter) { |
|
| 43 | + final String errorMessageOnDataFailureString, final StringMessages stringMessages, |
|
| 44 | + final ErrorReporter errorReporter) { |
|
| 48 | 45 | super(sailingServiceWrite, stringMessages, errorReporter, true, true, |
| 49 | 46 | new EntityIdentityComparator<IpToTimedLockDTO>() { |
| 50 | 47 | @Override |
| ... | ... | @@ -57,7 +54,6 @@ abstract class IPBlocklistTableWrapper |
| 57 | 54 | return t.ip.hashCode(); |
| 58 | 55 | } |
| 59 | 56 | }); |
| 60 | - this.unlockAction = unlockAction; |
|
| 61 | 57 | this.userService = userService; |
| 62 | 58 | this.errorMessageOnDataFailureString = errorMessageOnDataFailureString; |
| 63 | 59 | this.filterField = composeFilterField(); |
| ... | ... | @@ -81,26 +77,6 @@ abstract class IPBlocklistTableWrapper |
| 81 | 77 | mainPanel.setSpacing(5); |
| 82 | 78 | } |
| 83 | 79 | |
| 84 | - // admin, server admin and those with the permission can all unlock |
|
| 85 | - private boolean canUnlock() { |
|
| 86 | - final UserDTO user = userService.getCurrentUser(); |
|
| 87 | - final Iterable<RoleWithSecurityDTO> roles = user.getRoles(); |
|
| 88 | - boolean isAdmin = false; |
|
| 89 | - boolean isServerAdmin = false; |
|
| 90 | - final boolean hasUnlockPermission = userService.hasServerPermission(unlockAction); |
|
| 91 | - for (RoleWithSecurityDTO role : roles) { |
|
| 92 | - isAdmin = role.getName().equals(AdminRole.getInstance().getName()); |
|
| 93 | - if (isAdmin) { |
|
| 94 | - break; |
|
| 95 | - } |
|
| 96 | - isServerAdmin = role.getName().equals(ServerAdminRole.getInstance().getName()); |
|
| 97 | - if (isServerAdmin) { |
|
| 98 | - break; |
|
| 99 | - } |
|
| 100 | - } |
|
| 101 | - return isAdmin || isServerAdmin || hasUnlockPermission; |
|
| 102 | - } |
|
| 103 | - |
|
| 104 | 80 | private Widget composeButtonPanel() { |
| 105 | 81 | final HorizontalPanel buttonPanel = new HorizontalPanel(); |
| 106 | 82 | buttonPanel.setSpacing(5); |
| ... | ... | @@ -112,32 +88,42 @@ abstract class IPBlocklistTableWrapper |
| 112 | 88 | }); |
| 113 | 89 | refreshButton.ensureDebugId("refreshButton"); |
| 114 | 90 | buttonPanel.add(refreshButton); |
| 115 | - if (canUnlock()) { |
|
| 116 | - final Button unlockButton = new SelectedElementsCountingButton<IpToTimedLockDTO>( |
|
| 117 | - getStringMessages().unlock(), getSelectionModel(), new ClickHandler() { |
|
| 118 | - @Override |
|
| 119 | - public void onClick(ClickEvent event) { |
|
| 120 | - for (IpToTimedLockDTO e : getSelectionModel().getSelectedSet()) { |
|
| 121 | - unlockIP(e.ip, new AsyncCallback<Void>() { |
|
| 122 | - @Override |
|
| 123 | - public void onFailure(Throwable caught) { |
|
| 124 | - errorReporter.reportError(errorMessageOnDataFailureString); |
|
| 125 | - } |
|
| 126 | - |
|
| 127 | - @Override |
|
| 128 | - public void onSuccess(Void result) { |
|
| 129 | - filterField.remove(e); |
|
| 130 | - } |
|
| 131 | - }); |
|
| 132 | - } |
|
| 133 | - } |
|
| 134 | - }); |
|
| 91 | + if (hasUnlockPermission()) { |
|
| 92 | + final Button unlockButton = composeUnlockButton(); |
|
| 135 | 93 | unlockButton.ensureDebugId("unlockButton"); |
| 136 | 94 | buttonPanel.add(unlockButton); |
| 137 | 95 | } |
| 138 | 96 | return buttonPanel; |
| 139 | 97 | } |
| 140 | 98 | |
| 99 | + private boolean hasUnlockPermission() { |
|
| 100 | + final WildcardPermission unlockIpPermission = SecuredSecurityTypes.LOCKED_IP |
|
| 101 | + .getPermission(DefaultActions.DELETE); |
|
| 102 | + return userService.hasPermission(unlockIpPermission, userService.getServerInfo().getOwnership()); |
|
| 103 | + } |
|
| 104 | + |
|
| 105 | + private SelectedElementsCountingButton<IpToTimedLockDTO> composeUnlockButton() { |
|
| 106 | + return new SelectedElementsCountingButton<IpToTimedLockDTO>(getStringMessages().unlock(), getSelectionModel(), |
|
| 107 | + new ClickHandler() { |
|
| 108 | + @Override |
|
| 109 | + public void onClick(ClickEvent event) { |
|
| 110 | + for (IpToTimedLockDTO e : getSelectionModel().getSelectedSet()) { |
|
| 111 | + unlockIP(e.ip, new AsyncCallback<Void>() { |
|
| 112 | + @Override |
|
| 113 | + public void onFailure(Throwable caught) { |
|
| 114 | + errorReporter.reportError(errorMessageOnDataFailureString); |
|
| 115 | + } |
|
| 116 | + |
|
| 117 | + @Override |
|
| 118 | + public void onSuccess(Void result) { |
|
| 119 | + filterField.remove(e); |
|
| 120 | + } |
|
| 121 | + }); |
|
| 122 | + } |
|
| 123 | + } |
|
| 124 | + }); |
|
| 125 | + } |
|
| 126 | + |
|
| 141 | 127 | private void loadDataAndPopulateTable() { |
| 142 | 128 | final AsyncCallback<HashMap<String, TimedLock>> dataInitializationCallback = new AsyncCallback<HashMap<String, TimedLock>>() { |
| 143 | 129 | @Override |
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LocalServerManagementPanel.java
| ... | ... | @@ -152,7 +152,6 @@ public class LocalServerManagementPanel extends SimplePanel { |
| 152 | 152 | 3); |
| 153 | 153 | panel.ensureDebugId("bearerTokenAbusePanel"); |
| 154 | 154 | final IPBlocklistTableWrapper table = new IPBlocklistTableWrapper(sailingService, userService, |
| 155 | - ServerActions.UNLOCK_IPS_BLOCKED_FOR_BEARER_TOKEN_ABUSE, |
|
| 156 | 155 | stringMessages.unableToLoadIpsBlockedForBearerTokenAbuse(), stringMessages, errorReporter) { |
| 157 | 156 | @Override |
| 158 | 157 | protected void fetchData(AsyncCallback<HashMap<String, TimedLock>> callback) { |
| ... | ... | @@ -173,7 +172,6 @@ public class LocalServerManagementPanel extends SimplePanel { |
| 173 | 172 | 3); |
| 174 | 173 | panel.ensureDebugId("userCreationAbusePanel"); |
| 175 | 174 | final IPBlocklistTableWrapper table = new IPBlocklistTableWrapper(sailingService, userService, |
| 176 | - ServerActions.UNLOCK_IPS_BLOCKED_FOR_USER_CREATION_ABUSE, |
|
| 177 | 175 | stringMessages.unableToLoadIpsBlockedForUserCreationAbuse(), stringMessages, errorReporter) { |
| 178 | 176 | @Override |
| 179 | 177 | protected void fetchData(AsyncCallback<HashMap<String, TimedLock>> callback) { |
java/com.sap.sse.security.common/src/com/sap/sse/security/shared/IPAddress.java
| ... | ... | @@ -0,0 +1,28 @@ |
| 1 | +package com.sap.sse.security.shared; |
|
| 2 | + |
|
| 3 | +import com.sap.sse.security.shared.impl.SecuredSecurityTypes; |
|
| 4 | + |
|
| 5 | +public class IPAddress implements WithQualifiedObjectIdentifier { |
|
| 6 | + private static final long serialVersionUID = 8016397230668484898L; |
|
| 7 | + private final String ipAddress; |
|
| 8 | + |
|
| 9 | + public IPAddress(final String ipAddress) { |
|
| 10 | + this.ipAddress = ipAddress; |
|
| 11 | + } |
|
| 12 | + |
|
| 13 | + @Override |
|
| 14 | + public String getName() { |
|
| 15 | + return ipAddress; |
|
| 16 | + } |
|
| 17 | + |
|
| 18 | + @Override |
|
| 19 | + public QualifiedObjectIdentifier getIdentifier() { |
|
| 20 | + return getPermissionType().getQualifiedObjectIdentifier(new TypeRelativeObjectIdentifier(ipAddress)); |
|
| 21 | + } |
|
| 22 | + |
|
| 23 | + @Override |
|
| 24 | + public HasPermissions getPermissionType() { |
|
| 25 | + return SecuredSecurityTypes.LOCKED_IP; |
|
| 26 | + } |
|
| 27 | + |
|
| 28 | +} |
java/com.sap.sse.security.common/src/com/sap/sse/security/shared/impl/SecuredSecurityTypes.java
| ... | ... | @@ -50,6 +50,12 @@ public class SecuredSecurityTypes extends HasPermissionsImpl { |
| 50 | 50 | .plus(UserActions.FORCE_OVERWRITE_PASSWORD, PublicReadableActions.READ_PUBLIC, |
| 51 | 51 | UserActions.ADD_SUBSCRIPTION, UserActions.BE_PREMIUM, UserActions.MANAGE_LOCK)); |
| 52 | 52 | |
| 53 | + |
|
| 54 | + /** |
|
| 55 | + * type-relative identifier is the {@link User#getName() ip}. |
|
| 56 | + */ |
|
| 57 | + public static final HasPermissions LOCKED_IP = new SecuredSecurityTypes("LOCKED_IP", DefaultActions.values()); |
|
| 58 | + |
|
| 53 | 59 | /** |
| 54 | 60 | * type-relative identifier is the {@link RoleDefinition#getId() role ID's} string representation |
| 55 | 61 | */ |
| ... | ... | @@ -75,12 +81,6 @@ public class SecuredSecurityTypes extends HasPermissionsImpl { |
| 75 | 81 | CONFIGURE_LOCAL_SERVER, |
| 76 | 82 | CONFIGURE_REMOTE_INSTANCES, |
| 77 | 83 | CREATE_OBJECT, |
| 78 | - |
|
| 79 | - GET_IPS_BLOCKED_FOR_USER_CREATION_ABUSE, |
|
| 80 | - GET_IPS_BLOCKED_FOR_BEARER_TOKEN_ABUSE, |
|
| 81 | - |
|
| 82 | - UNLOCK_IPS_BLOCKED_FOR_USER_CREATION_ABUSE, |
|
| 83 | - UNLOCK_IPS_BLOCKED_FOR_BEARER_TOKEN_ABUSE, |
|
| 84 | 84 | |
| 85 | 85 | /** |
| 86 | 86 | * This permission is used to check READ-permission on different things. For that the object type to determine |
| ... | ... | @@ -118,9 +118,7 @@ public class SecuredSecurityTypes extends HasPermissionsImpl { |
| 118 | 118 | CONFIGURE_CORS_FILTER |
| 119 | 119 | ; |
| 120 | 120 | |
| 121 | - private static final Action[] ALL_ACTIONS = new Action[] { GET_IPS_BLOCKED_FOR_USER_CREATION_ABUSE, |
|
| 122 | - GET_IPS_BLOCKED_FOR_BEARER_TOKEN_ABUSE, UNLOCK_IPS_BLOCKED_FOR_USER_CREATION_ABUSE, |
|
| 123 | - UNLOCK_IPS_BLOCKED_FOR_BEARER_TOKEN_ABUSE, CONFIGURE_FILE_STORAGE, CONFIGURE_LOCAL_SERVER, |
|
| 121 | + private static final Action[] ALL_ACTIONS = new Action[] { CONFIGURE_FILE_STORAGE, CONFIGURE_LOCAL_SERVER, |
|
| 124 | 122 | CONFIGURE_REMOTE_INSTANCES, CREATE_OBJECT, CAN_IMPORT_MASTERDATA, CAN_EXPORT_MASTERDATA, DATA_MINING, |
| 125 | 123 | REPLICATE, START_REPLICATION, READ_REPLICATOR, THREADS, CONFIGURE_AI_AGENT, CONFIGURE_CORS_FILTER, |
| 126 | 124 | DefaultActions.CHANGE_OWNERSHIP, DefaultActions.CHANGE_ACL, DefaultActions.CREATE, |
java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/server/UserManagementServiceImpl.java
| ... | ... | @@ -35,6 +35,7 @@ import com.sap.sse.security.interfaces.Credential; |
| 35 | 35 | import com.sap.sse.security.shared.AccessControlListAnnotation; |
| 36 | 36 | import com.sap.sse.security.shared.HasPermissions; |
| 37 | 37 | import com.sap.sse.security.shared.HasPermissions.DefaultActions; |
| 38 | +import com.sap.sse.security.shared.IPAddress; |
|
| 38 | 39 | import com.sap.sse.security.shared.QualifiedObjectIdentifier; |
| 39 | 40 | import com.sap.sse.security.shared.TypeRelativeObjectIdentifier; |
| 40 | 41 | import com.sap.sse.security.shared.UnauthorizedException; |
| ... | ... | @@ -418,16 +419,34 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U |
| 418 | 419 | @Override |
| 419 | 420 | public HashMap<String, TimedLock> getClientIPBasedTimedLocksForUserCreation() throws UnauthorizedException { |
| 420 | 421 | final SecurityService securityService = getSecurityService(); |
| 421 | - // throws UnauthorizedException if fails |
|
| 422 | - securityService.checkCurrentUserServerPermission(ServerActions.GET_IPS_BLOCKED_FOR_USER_CREATION_ABUSE); |
|
| 423 | - return securityService.getClientIPBasedTimedLocksForUserCreation(); |
|
| 422 | + final HashMap<String, TimedLock> ipToLockMap = securityService.getClientIPBasedTimedLocksForUserCreation(); |
|
| 423 | + // remove from Map, those where permission == FALSE |
|
| 424 | + ipToLockMap.entrySet().forEach(ipToLockPair -> { |
|
| 425 | + final String ip = ipToLockPair.getKey(); |
|
| 426 | + final WildcardPermission userReadPermissionOnIp = SecuredSecurityTypes.LOCKED_IP |
|
| 427 | + .getPermissionForObject(DefaultActions.READ, new IPAddress(ip)); |
|
| 428 | + final boolean isPermitted = SecurityUtils.getSubject().isPermitted(userReadPermissionOnIp.toString()); |
|
| 429 | + if (!isPermitted) { |
|
| 430 | + ipToLockMap.remove(ip); |
|
| 431 | + } |
|
| 432 | + }); |
|
| 433 | + return ipToLockMap; |
|
| 424 | 434 | } |
| 425 | 435 | |
| 426 | 436 | @Override |
| 427 | 437 | public HashMap<String, TimedLock> getClientIPBasedTimedLocksForBearerTokenAbuse() throws UnauthorizedException { |
| 428 | 438 | final SecurityService securityService = getSecurityService(); |
| 429 | - // throws UnauthorizedException if fails |
|
| 430 | - securityService.checkCurrentUserServerPermission(ServerActions.GET_IPS_BLOCKED_FOR_USER_CREATION_ABUSE); |
|
| 431 | - return securityService.getClientIPBasedTimedLocksForBearerTokenAbuse(); |
|
| 439 | + final HashMap<String, TimedLock> ipToLockMap = securityService.getClientIPBasedTimedLocksForBearerTokenAbuse(); |
|
| 440 | + // remove from Map, those where permission == FALSE |
|
| 441 | + ipToLockMap.entrySet().forEach(ipToLockPair -> { |
|
| 442 | + final String ip = ipToLockPair.getKey(); |
|
| 443 | + final WildcardPermission userReadPermissionOnIp = SecuredSecurityTypes.LOCKED_IP |
|
| 444 | + .getPermissionForObject(DefaultActions.READ, new IPAddress(ip)); |
|
| 445 | + final boolean isPermitted = SecurityUtils.getSubject().isPermitted(userReadPermissionOnIp.toString()); |
|
| 446 | + if (!isPermitted) { |
|
| 447 | + ipToLockMap.remove(ip); |
|
| 448 | + } |
|
| 449 | + }); |
|
| 450 | + return ipToLockMap; |
|
| 432 | 451 | } |
| 433 | 452 | } |
java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/server/UserManagementWriteServiceImpl.java
| ... | ... | @@ -23,6 +23,7 @@ import com.sap.sse.common.media.TakedownNoticeRequestContext; |
| 23 | 23 | import com.sap.sse.security.Action; |
| 24 | 24 | import com.sap.sse.security.SecurityService; |
| 25 | 25 | import com.sap.sse.security.shared.HasPermissions.DefaultActions; |
| 26 | +import com.sap.sse.security.shared.IPAddress; |
|
| 26 | 27 | import com.sap.sse.security.shared.PermissionChecker; |
| 27 | 28 | import com.sap.sse.security.shared.QualifiedObjectIdentifier; |
| 28 | 29 | import com.sap.sse.security.shared.RoleDefinition; |
| ... | ... | @@ -745,16 +746,20 @@ public class UserManagementWriteServiceImpl extends UserManagementServiceImpl im |
| 745 | 746 | @Override |
| 746 | 747 | public void releaseUserCreationLockOnIp(String ip) throws UnauthorizedException { |
| 747 | 748 | final SecurityService securityService = getSecurityService(); |
| 748 | - // throws if permission not granted |
|
| 749 | - securityService.checkCurrentUserServerPermission(ServerActions.UNLOCK_IPS_BLOCKED_FOR_USER_CREATION_ABUSE); |
|
| 749 | + final WildcardPermission userReadPermissionOnIp = SecuredSecurityTypes.LOCKED_IP |
|
| 750 | + .getPermissionForObject(DefaultActions.DELETE, new IPAddress(ip)); |
|
| 751 | + // throws exception if not permitted |
|
| 752 | + SecurityUtils.getSubject().checkPermission(userReadPermissionOnIp.toString()); |
|
| 750 | 753 | securityService.releaseUserCreationLockOnIp(ip); |
| 751 | 754 | } |
| 752 | 755 | |
| 753 | 756 | @Override |
| 754 | 757 | public void releaseBearerTokenLockOnIp(String ip) throws UnauthorizedException { |
| 755 | 758 | final SecurityService securityService = getSecurityService(); |
| 756 | - // throws UnauthorizedException if fails |
|
| 757 | - securityService.checkCurrentUserServerPermission(ServerActions.UNLOCK_IPS_BLOCKED_FOR_BEARER_TOKEN_ABUSE); |
|
| 759 | + final WildcardPermission userReadPermissionOnIp = SecuredSecurityTypes.LOCKED_IP |
|
| 760 | + .getPermissionForObject(DefaultActions.DELETE, new IPAddress(ip)); |
|
| 761 | + // throws exception if not permitted |
|
| 762 | + SecurityUtils.getSubject().checkPermission(userReadPermissionOnIp.toString()); |
|
| 758 | 763 | securityService.releaseBearerTokenLockOnIp(ip); |
| 759 | 764 | } |
| 760 | 765 | } |