Skip to content

Commit

Permalink
Adding operation that changes the used MembershipService type
Browse files Browse the repository at this point in the history
  • Loading branch information
armstrongmsg committed Dec 21, 2020
1 parent 5569285 commit 8d409b9
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 3 deletions.
11 changes: 11 additions & 0 deletions src/main/java/cloud/fogbow/ms/api/http/request/Admin.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import cloud.fogbow.common.exceptions.FogbowException;
import cloud.fogbow.ms.api.http.CommonKeys;
import cloud.fogbow.ms.api.parameters.Provider;
import cloud.fogbow.ms.api.parameters.Service;
import cloud.fogbow.ms.constants.ApiDocumentation;
import cloud.fogbow.ms.constants.SystemConstants;
import cloud.fogbow.ms.core.ApplicationFacade;
Expand All @@ -38,6 +39,16 @@ public ResponseEntity<Boolean> reload(
return new ResponseEntity<>(HttpStatus.OK);
}

@ApiOperation(value = ApiDocumentation.Admin.SERVICE)
@RequestMapping(value = "/service", method = RequestMethod.POST)
public ResponseEntity<Boolean> service(
@ApiParam(value = cloud.fogbow.common.constants.ApiDocumentation.Token.SYSTEM_USER_TOKEN)
@RequestHeader(required = false, value = CommonKeys.SYSTEM_USER_TOKEN_HEADER_KEY)String systemUserToken,
@RequestBody Service service) throws FogbowException {
ApplicationFacade.getInstance().updateMembershipService(systemUserToken, service.getClassName());
return new ResponseEntity<>(HttpStatus.OK);
}

@ApiOperation(value = ApiDocumentation.Admin.ADD_PROVIDER)
@RequestMapping(value = "/provider", method = RequestMethod.POST)
public ResponseEntity<Boolean> addProvider(
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/cloud/fogbow/ms/api/parameters/Service.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package cloud.fogbow.ms.api.parameters;

public class Service {
private String className;

public String getClassName() {
return className;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public static class Admin {
+ "to authorized operations from other providers";
public static final String REMOVE_REQUESTER = "Removes given provider from the list of requesters, used by the MembershipService "
+ "to authorized operations from other providers";
public static final String SERVICE = "Changes membership service plugin to the given class name";

This comment has been minimized.

Copy link
@fubica

fubica Dec 22, 2020

Collaborator

All messages should end with a full stop.

This comment has been minimized.

Copy link
@armstrongmsg

armstrongmsg Dec 22, 2020

Author

Fixed.


}
}
1 change: 1 addition & 0 deletions src/main/java/cloud/fogbow/ms/constants/Messages.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public static class Log {
public static final String ADDING_NEW_PROVIDER = "Adding provider: %s";
public static final String ADDING_REQUESTER_PROVIDER = "Adding requester: %s";
public static final String ADDING_TARGET_PROVIDER = "Adding target: %s";
public static final String CHANGING_MEMBERSHIP_PLUGIN = "Changing membership plugin to: %s";

This comment has been minimized.

Copy link
@fubica

fubica Dec 22, 2020

Collaborator

All messages should end with a full stop.

This comment has been minimized.

Copy link
@armstrongmsg

armstrongmsg Dec 22, 2020

Author

Fixed.

public static final String GET_PUBLIC_KEY = "Get public key received.";
public static final String INTERNAL_SERVER_ERROR = "Internal server error.";
public static final String RELOADING_AUTHORIZATION_PLUGIN = "Reloading authorization plugin.";
Expand Down
24 changes: 24 additions & 0 deletions src/main/java/cloud/fogbow/ms/core/ApplicationFacade.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import cloud.fogbow.common.plugins.authorization.AuthorizationPlugin;
import cloud.fogbow.common.util.CryptoUtil;
import cloud.fogbow.common.util.ServiceAsymmetricKeysHolder;
import cloud.fogbow.ms.constants.ConfigurationPropertyKeys;
import cloud.fogbow.ms.constants.Messages;
import cloud.fogbow.ms.core.authorization.AdminOperation;

Expand Down Expand Up @@ -85,6 +86,10 @@ public void setMembershipService(MembershipService membershipService) {
this.membershipService = membershipService;
}

public MembershipService getMembershipService() {
return membershipService;
}

public void setAuthorizationPlugin(AuthorizationPlugin<AdminOperation> authorizationPlugin) {
this.authorizationPlugin = authorizationPlugin;
}
Expand Down Expand Up @@ -231,6 +236,25 @@ private void doReload() throws ConfigurationErrorException {
}
}

public void updateMembershipService(String userToken, String className) throws FogbowException {
RSAPublicKey asPublicKey = MSPublicKeysHolder.getInstance().getAsPublicKey();
SystemUser systemUser = AuthenticationUtil.authenticate(asPublicKey, userToken);
this.authorizationPlugin.isAuthorized(systemUser, new AdminOperation());

setAsReloading();

try {
LOGGER.info(String.format(Messages.Log.CHANGING_MEMBERSHIP_PLUGIN, className));
MembershipService membershipService = PluginInstantiator.getMembershipService(className);
setMembershipService(membershipService);

PropertiesHolder.getInstance().setProperty(ConfigurationPropertyKeys.MEMBERSHIP_SERVICE_CLASS_KEY, className);
PropertiesHolder.getInstance().updatePropertiesFile();
} finally {
finishReloading();
}
}

private void setAsReloading() {
this.reloading = true;
}
Expand Down
12 changes: 10 additions & 2 deletions src/main/java/cloud/fogbow/ms/core/PluginInstantiator.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class PluginInstantiator {
public static MembershipService getMembershipService() throws ConfigurationErrorException {
if (PropertiesHolder.getInstance().getProperties().containsKey(ConfigurationPropertyKeys.MEMBERSHIP_SERVICE_CLASS_KEY)) {
String className = PropertiesHolder.getInstance().getProperty(ConfigurationPropertyKeys.MEMBERSHIP_SERVICE_CLASS_KEY);
return (MembershipService) PluginInstantiator.classFactory.createPluginInstance(className);
return getMembershipService(className);
} else {
return new AllowList();
}
Expand All @@ -22,10 +22,18 @@ public static MembershipService getMembershipService() throws ConfigurationError
public static AuthorizationPlugin<AdminOperation> getAuthorizationPlugin() throws ConfigurationErrorException {
if (PropertiesHolder.getInstance().getProperties().containsKey(ConfigurationPropertyKeys.AUTHORIZATION_PLUGIN_CLASS_KEY)) {
String className = PropertiesHolder.getInstance().getProperty(ConfigurationPropertyKeys.AUTHORIZATION_PLUGIN_CLASS_KEY);
return (AuthorizationPlugin<AdminOperation>) PluginInstantiator.classFactory.createPluginInstance(className);
return getAuthorizationPlugin(className);
} else {
return new AdminAuthorizationPlugin();
}
}

public static AuthorizationPlugin<AdminOperation> getAuthorizationPlugin(String className) {
return (AuthorizationPlugin<AdminOperation>) PluginInstantiator.classFactory.createPluginInstance(className);
}

public static MembershipService getMembershipService(String className) {
return (MembershipService) PluginInstantiator.classFactory.createPluginInstance(className);
}

}
48 changes: 47 additions & 1 deletion src/test/java/cloud/fogbow/ms/core/ApplicationFacadeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@
import cloud.fogbow.common.models.SystemUser;
import cloud.fogbow.common.plugins.authorization.AuthorizationPlugin;
import cloud.fogbow.common.util.PublicKeysHolder;
import cloud.fogbow.ms.constants.ConfigurationPropertyKeys;
import cloud.fogbow.ms.core.authorization.AdminAuthorizationPlugin;
import cloud.fogbow.ms.core.authorization.AdminOperation;

@RunWith(PowerMockRunner.class)
@PrepareForTest({AuthenticationUtil.class, MSPublicKeysHolder.class,
PropertiesHolder.class, PublicKeysHolder.class})
PropertiesHolder.class, PublicKeysHolder.class,
PluginInstantiator.class })
public class ApplicationFacadeTest {

private ApplicationFacade facade;
Expand All @@ -41,10 +43,13 @@ public class ApplicationFacadeTest {
private String userId = "userId";
private String userName = "userName";
private String provider = "provider";

private String newMembershipServiceClassName = "newclass";

private SystemUser systemUser;
private RSAPublicKey key;
private AdminOperation operation;
private PropertiesHolder propertiesHolder;

@Before
public void setUp() throws FogbowException {
Expand Down Expand Up @@ -74,6 +79,47 @@ public void setUp() throws FogbowException {
this.facade.setAuthorizationPlugin(authorizationPlugin);
}

// test case: When invoking the updateMembershipService method, it must
// authorize the operation, call the PluginInstantiator to get a new
// MembershipService instance and set this instance as the one used
// by the facade. Also, the configuration file must be updated.
@Test
public void testUpdateMembershipService() throws FogbowException {
// set up
MembershipService membershipService = Mockito.mock(MembershipService.class);

PowerMockito.mockStatic(PropertiesHolder.class);
this.propertiesHolder = Mockito.mock(PropertiesHolder.class);
BDDMockito.given(PropertiesHolder.getInstance()).willReturn(this.propertiesHolder);

PowerMockito.mockStatic(PluginInstantiator.class);
BDDMockito.given(PluginInstantiator.getMembershipService(newMembershipServiceClassName)).willReturn(membershipService);


this.facade.updateMembershipService(token, newMembershipServiceClassName);


// verify membership service is updated
assertEquals(this.facade.getMembershipService(), membershipService);

// verify authorization
Mockito.verify(authorizationPlugin, Mockito.times(1)).isAuthorized(systemUser, operation);

// verify configuration is update
Mockito.verify(propertiesHolder, Mockito.times(1)).setProperty(ConfigurationPropertyKeys.MEMBERSHIP_SERVICE_CLASS_KEY,
newMembershipServiceClassName);
Mockito.verify(propertiesHolder, Mockito.times(1)).updatePropertiesFile();
}

// test case: When invoking the updateMembershipService and the operation
// is not authorized, it must throw an UnauthorizedRequestException.
@Test(expected = UnauthorizedRequestException.class)
public void testUpdateMembershipServiceUnauthorizedOperation() throws FogbowException {
Mockito.doThrow(new UnauthorizedRequestException()).when(this.authorizationPlugin).isAuthorized(systemUser, operation);

this.facade.updateMembershipService(token, newMembershipServiceClassName);
}

// test case: When invoking the listMembers method, it
// must call the listMembers method of the MembershipService
// instance it holds and return a list containing the same
Expand Down

0 comments on commit 8d409b9

Please sign in to comment.