bug5684: added SecuredServer.hasPermissions and corresponding test

This commit is contained in:
Axel Uhl
2022-03-01 11:05:10 +01:00
parent d629444bda
commit e87c9629fe
5 changed files with 75 additions and 12 deletions
@@ -56,6 +56,7 @@ import com.sap.sse.ServerInfo;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.landscape.InboundReplicationConfiguration;
import com.sap.sse.landscape.Release;
import com.sap.sse.landscape.ReplicationCredentials;
@@ -674,9 +675,12 @@ public class LandscapeServiceImpl implements LandscapeService {
final UUID userGroupId = securityServiceServer.getUserGroupIdByName(serverGroupName);
// TODO bug5684: use this userGroupId instead of the following old code to check existence, then ownership!
if (userGroupId != null) {
// TODO bug5684: check ownership; SecuredServer now needs something like getOwnership(...)
final Pair<UUID, String> serverGroupOwnership = securityServiceServer.getGroupAndUserOwner(
SecuredSecurityTypes.USER_GROUP, new TypeRelativeObjectIdentifier(userGroupId.toString()));
final Pair<UUID, String> serverOwnership = securityServiceServer.getGroupAndUserOwner(SecuredSecurityTypes.SERVER,
new TypeRelativeObjectIdentifier(serverName));
// TODO bug5684: check ownerships and permissions; user should have CREATE and UPDATE permission at least, probably also DELETE?
}
final UserGroup existingServerGroup = getSecurityService().getUserGroupByName(serverGroupName);
final UserGroup serverGroup;
if (existingServerGroup == null) {
@@ -5,10 +5,12 @@ import static com.sap.sailing.selenium.api.core.ApiContext.createAdminApiContext
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.UUID;
import org.apache.http.client.ClientProtocolException;
@@ -23,7 +25,9 @@ import com.sap.sailing.selenium.api.event.SecurityApi.Hello;
import com.sap.sailing.selenium.api.event.SecurityApi.User;
import com.sap.sailing.selenium.test.AbstractSeleniumTest;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.security.shared.HasPermissions.DefaultActions;
import com.sap.sse.security.shared.TypeRelativeObjectIdentifier;
import com.sap.sse.security.shared.WildcardPermission;
import com.sap.sse.security.shared.impl.SecuredSecurityTypes;
import com.sap.sse.security.util.RemoteServerUtil;
import com.sap.sse.security.util.SecuredServer;
@@ -87,4 +91,26 @@ public class SecurityApiTest extends AbstractSeleniumTest {
final Pair<UUID, String> userAndGroupOwner = securedServer.getGroupAndUserOwner(SecuredSecurityTypes.USER_GROUP, new TypeRelativeObjectIdentifier(adminTenantGroupId.toString()));
assertEquals(adminTenantGroupId, userAndGroupOwner.getA());
}
@Test
public void testGetPermissions() throws ClientProtocolException, IOException, ParseException {
final ApiContext adminCtx = createAdminApiContext(getContextRoot(), SECURITY_CONTEXT);
final SecuredServer securedServer = createSecuredServer(adminCtx);
final UUID adminTenantGroupId = securedServer.getUserGroupIdByName("admin-tenant");
final WildcardPermission groupReadPermission = SecuredSecurityTypes.USER_GROUP.getPermissionForTypeRelativeIdentifier(DefaultActions.READ, new TypeRelativeObjectIdentifier(adminTenantGroupId.toString()));
final WildcardPermission groupCreatePermission = SecuredSecurityTypes.USER_GROUP.getPermissionForTypeRelativeIdentifier(DefaultActions.CREATE, new TypeRelativeObjectIdentifier(adminTenantGroupId.toString()));
final Iterable<Pair<WildcardPermission, Boolean>> permissions = securedServer.hasPermissions(Arrays.asList(groupReadPermission, groupCreatePermission));
boolean read = false;
boolean create = false;
for (final Pair<WildcardPermission, Boolean> permissionAndGranted : permissions) {
if (permissionAndGranted.getA().equals(groupReadPermission) && permissionAndGranted.getB()) {
read = true;
}
if (permissionAndGranted.getA().equals(groupCreatePermission) && permissionAndGranted.getB()) {
create = true;
}
}
assertTrue(read);
assertTrue(create);
}
}
@@ -60,6 +60,8 @@ public class SecurityResource extends AbstractSecurityResource {
public static final String USERNAME = "username";
public static final String PASSWORD = "password";
public static final String ACCESS_TOKEN = "access_token";
public static final String PERMISSION = "permission";
public static final String GRANTED = "granted";
public static final String ACCESS_TOKEN_METHOD = "/"+ACCESS_TOKEN;
/**
@@ -77,7 +79,7 @@ public class SecurityResource extends AbstractSecurityResource {
@GET
@Path(USERS_WITH_PERMISSION_METHOD)
@Produces("text/plain;charset=UTF-8")
public Response getUsersWithPermission(@QueryParam("permission") String permission) {
public Response getUsersWithPermission(@QueryParam(PERMISSION) String permission) {
final TimePoint start = TimePoint.now();
try {
final WildcardPermission wildcardPermission = new WildcardPermission(permission);
@@ -338,13 +340,13 @@ public class SecurityResource extends AbstractSecurityResource {
@GET
@Path(HAS_PERMISSION_METHOD)
@Produces("application/json;charset=UTF-8")
public Response getPermission(@QueryParam("permission") final List<String> permissionsAsStrings) {
public Response getPermission(@QueryParam(PERMISSION) final List<String> permissionsAsStrings) {
final JSONArray result = new JSONArray();
for (final String permissionAsString : permissionsAsStrings) {
final JSONObject entry = new JSONObject();
result.add(entry);
entry.put("permission", permissionAsString);
entry.put("granted", SecurityUtils.getSubject().isPermitted(permissionAsString));
entry.put(PERMISSION, permissionAsString);
entry.put(GRANTED, SecurityUtils.getSubject().isPermitted(permissionAsString));
}
return Response.ok(streamingOutput(result), MediaType.APPLICATION_JSON_TYPE).build();
}
@@ -1,6 +1,7 @@
package com.sap.sse.security.util;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.UUID;
@@ -11,6 +12,7 @@ import org.json.simple.parser.ParseException;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.security.shared.HasPermissions;
import com.sap.sse.security.shared.TypeRelativeObjectIdentifier;
import com.sap.sse.security.shared.WildcardPermission;
/**
* Represents a remote instance of a server process or an entire application replica set with a master and zero or more
@@ -35,6 +37,7 @@ public interface SecuredServer {
Pair<UUID, String> getGroupAndUserOwner(HasPermissions type, TypeRelativeObjectIdentifier typeRelativeObjectId)
throws ClientProtocolException, IOException, ParseException;
Iterable<Pair<WildcardPermission, Boolean>> hasPermissions(Iterable<WildcardPermission> permissions) throws UnsupportedEncodingException, MalformedURLException, ClientProtocolException, IOException, ParseException;
/**
* The name of the user authenticated by the credentials used by this facade object.
*/
@@ -5,6 +5,9 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.apache.http.HttpRequest;
@@ -17,6 +20,7 @@ import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
@@ -27,6 +31,7 @@ import com.sap.sse.security.jaxrs.api.SecurityResource;
import com.sap.sse.security.jaxrs.api.UserGroupResource;
import com.sap.sse.security.shared.HasPermissions;
import com.sap.sse.security.shared.TypeRelativeObjectIdentifier;
import com.sap.sse.security.shared.WildcardPermission;
import com.sap.sse.security.util.SecuredServer;
import com.sap.sse.util.LaxRedirectStrategyForAllRedirectResponseCodes;
@@ -80,9 +85,9 @@ public class SecuredServerImpl implements SecuredServer {
@Override
public UUID getUserGroupIdByName(String userGroupName) throws ClientProtocolException, IOException, ParseException {
final URL getRemoteReferencesUrl = new URL(getBaseUrl(), SECURITY_API_PREFIX + UserGroupResource.RESTSECURITY_USERGROUP
final URL getUserGroupIdByNameUrl = new URL(getBaseUrl(), SECURITY_API_PREFIX + UserGroupResource.RESTSECURITY_USERGROUP
+ "?" + UserGroupResource.KEY_GROUP_NAME+"="+userGroupName);
final HttpGet getRequest = new HttpGet(getRemoteReferencesUrl.toString());
final HttpGet getRequest = new HttpGet(getUserGroupIdByNameUrl.toString());
final JSONObject groupJson = (JSONObject) getJsonParsedResponse(getRequest).getA();
final UUID groupId = groupJson == null ? null : UUID.fromString(groupJson.get(UserGroupResource.KEY_GROUP_ID).toString());
return groupId;
@@ -90,9 +95,9 @@ public class SecuredServerImpl implements SecuredServer {
@Override
public Pair<UUID, String> getGroupAndUserOwner(HasPermissions type, TypeRelativeObjectIdentifier typeRelativeObjectId) throws ClientProtocolException, IOException, ParseException {
final URL getRemoteReferencesUrl = new URL(getBaseUrl(), SECURITY_API_PREFIX + OwnershipResource.RESTSECURITY_OWNERSHIP
final URL getGroupAndUserOwnerUrl = new URL(getBaseUrl(), SECURITY_API_PREFIX + OwnershipResource.RESTSECURITY_OWNERSHIP
+ "/" + type.getName() + "/" + typeRelativeObjectId.toString());
final HttpGet getRequest = new HttpGet(getRemoteReferencesUrl.toString());
final HttpGet getRequest = new HttpGet(getGroupAndUserOwnerUrl.toString());
final JSONObject ownershipJson = (JSONObject) getJsonParsedResponse(getRequest).getA();
final Object groupIdValue = ownershipJson.get(OwnershipResource.KEY_GROUP_ID);
final UUID groupId = groupIdValue == null ? null : UUID.fromString(groupIdValue.toString());
@@ -101,10 +106,33 @@ public class SecuredServerImpl implements SecuredServer {
return new Pair<>(groupId, username);
}
@Override
public Iterable<Pair<WildcardPermission, Boolean>> hasPermissions(Iterable<WildcardPermission> permissions) throws ClientProtocolException, IOException, ParseException {
final StringBuilder sb = new StringBuilder(SECURITY_API_PREFIX + SecurityResource.RESTSECURITY + SecurityResource.HAS_PERMISSION_METHOD + "?");
for (final WildcardPermission permission : permissions) {
sb.append(SecurityResource.PERMISSION);
sb.append('=');
sb.append(URLEncoder.encode(permission.toString(), "UTF-8"));
sb.append('&');
}
sb.delete(sb.length()-1, sb.length());
final URL getPermissionsUrl = new URL(getBaseUrl(), sb.toString());
final HttpGet getRequest = new HttpGet(getPermissionsUrl.toString());
final JSONArray permissionsJson = (JSONArray) getJsonParsedResponse(getRequest).getA();
final List<Pair<WildcardPermission, Boolean>> result = new ArrayList<>();
for (final Object o : permissionsJson) {
final JSONObject permissionAndGranted = (JSONObject) o;
final String permissionAsString = permissionAndGranted.get(SecurityResource.PERMISSION).toString();
final Boolean permissionGranted = (Boolean) permissionAndGranted.get(SecurityResource.GRANTED);
result.add(new Pair<>(new WildcardPermission(permissionAsString), permissionGranted));
}
return result;
}
@Override
public String getUsername() throws ClientProtocolException, IOException, ParseException {
final URL getRemoteReferencesUrl = new URL(getBaseUrl(), SECURITY_API_PREFIX + SecurityResource.RESTSECURITY + SecurityResource.ACCESS_TOKEN_METHOD);
final HttpGet getRequest = new HttpGet(getRemoteReferencesUrl.toString());
final URL getUsernameUrl = new URL(getBaseUrl(), SECURITY_API_PREFIX + SecurityResource.RESTSECURITY + SecurityResource.ACCESS_TOKEN_METHOD);
final HttpGet getRequest = new HttpGet(getUsernameUrl.toString());
final JSONObject accessTokenJson = (JSONObject) getJsonParsedResponse(getRequest).getA();
final Object usernameValue = accessTokenJson.get(SecurityResource.USERNAME);
final String username = usernameValue == null ? null : usernameValue.toString();