diff --git a/SingularityService/src/main/java/com/hubspot/singularity/SingularityService.java b/SingularityService/src/main/java/com/hubspot/singularity/SingularityService.java index bebd51fda6..3b912b0267 100644 --- a/SingularityService/src/main/java/com/hubspot/singularity/SingularityService.java +++ b/SingularityService/src/main/java/com/hubspot/singularity/SingularityService.java @@ -100,7 +100,7 @@ public void initialize(final Bootstrap bootstrap) { GuiceBundle.Builder guiceBundleBuilder = GuiceBundle .defaultBuilder(SingularityConfiguration.class) - .modules(getServiceModule(), getObjectMapperModule(), new SingularityAuthModule()) + .modules(getServiceModule(), getObjectMapperModule(), getAuthModule()) .modules(additionalModules) .enableGuiceEnforcer(false) .stage(getGuiceStage()); @@ -171,6 +171,10 @@ public Module getObjectMapperModule() { .in(Scopes.SINGLETON); } + public Module getAuthModule() { + return new SingularityAuthModule(); + } + /** * Dropwizard bundles used in addition to the bundles required by Singularity. This is an extension point when embedding * Singularity into a custom service. diff --git a/SingularityService/src/main/java/com/hubspot/singularity/auth/SingularityAuthModule.java b/SingularityService/src/main/java/com/hubspot/singularity/auth/SingularityAuthModule.java index 171c5ec0f9..5b6d0cda97 100644 --- a/SingularityService/src/main/java/com/hubspot/singularity/auth/SingularityAuthModule.java +++ b/SingularityService/src/main/java/com/hubspot/singularity/auth/SingularityAuthModule.java @@ -19,15 +19,21 @@ import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import java.util.HashSet; +import java.util.Optional; import java.util.Set; public class SingularityAuthModule extends DropwizardAwareModule { public static final String WEBHOOK_AUTH_HTTP_CLIENT = "singularity.webhook.auth.http.client"; + private Optional> authorizerClass = Optional.empty(); public SingularityAuthModule() {} + public void setAuthorizerClass(Class authorizerClass) { + this.authorizerClass = Optional.of(authorizerClass); + } + @Override public void configure(Binder binder) { binder @@ -64,27 +70,10 @@ public void configure(Binder binder) { } } - switch (getConfiguration().getAuthConfiguration().getAuthMode()) { - case GROUPS_SCOPES: - binder - .bind(SingularityAuthorizer.class) - .to(SingularityGroupsScopesAuthorizer.class) - .in(Scopes.SINGLETON); - break; - case GROUPS_LOG_SCOPES: - binder - .bind(SingularityAuthorizer.class) - .to(SingularityDualAuthorizer.class) - .in(Scopes.SINGLETON); - break; - case GROUPS: - default: - binder - .bind(SingularityAuthorizer.class) - .to(SingularityGroupsAuthorizer.class) - .in(Scopes.SINGLETON); - break; - } + binder + .bind(SingularityAuthorizer.class) + .to(authorizerClass.orElseGet(this::getAuthClassFromConfig)) + .in(Scopes.SINGLETON); switch (getConfiguration().getAuthConfiguration().getAuthResponseParser()) { case RAW: @@ -110,4 +99,16 @@ public void configure(Binder binder) { getConfiguration().getAuthConfiguration().getDatastore().getAuthDatastoreClass() ); } + + private Class getAuthClassFromConfig() { + switch (getConfiguration().getAuthConfiguration().getAuthMode()) { + case GROUPS_SCOPES: + return SingularityGroupsScopesAuthorizer.class; + case GROUPS_LOG_SCOPES: + return SingularityDualAuthorizer.class; + case GROUPS: + default: + return SingularityGroupsAuthorizer.class; + } + } } diff --git a/SingularityService/src/main/java/com/hubspot/singularity/auth/SingularityAuthorizer.java b/SingularityService/src/main/java/com/hubspot/singularity/auth/SingularityAuthorizer.java index 0dc440aba6..e0d7a8e8a7 100644 --- a/SingularityService/src/main/java/com/hubspot/singularity/auth/SingularityAuthorizer.java +++ b/SingularityService/src/main/java/com/hubspot/singularity/auth/SingularityAuthorizer.java @@ -10,6 +10,7 @@ import com.google.common.collect.Sets; import com.hubspot.singularity.InvalidSingularityTaskIdException; import com.hubspot.singularity.SingularityAuthorizationScope; +import com.hubspot.singularity.SingularityDeploy; import com.hubspot.singularity.SingularityRequest; import com.hubspot.singularity.SingularityRequestWithState; import com.hubspot.singularity.SingularityTaskId; @@ -31,7 +32,7 @@ public SingularityAuthorizer(RequestManager requestManager, boolean authEnabled) this.authEnabled = authEnabled; } - static boolean groupsIntersect(Set a, Set b) { + public static boolean groupsIntersect(Set a, Set b) { return !Sets.intersection(a, b).isEmpty(); } @@ -67,6 +68,13 @@ protected abstract void checkForAuthorization( Optional action ); + public void checkForAuthorization( + SingularityRequest request, + SingularityDeploy deploy, + SingularityUser user, + SingularityAuthorizationScope scope + ) {} + public boolean isAuthorizedForRequest( SingularityRequest request, SingularityUser user, @@ -91,6 +99,16 @@ protected abstract boolean isAuthorizedForRequest( Optional action ); + public void checkForAuthorizedChanges( + SingularityRequest newRequest, + Optional oldRequest, + SingularityUser user + ) { + if (oldRequest.isPresent()) { + checkForAuthorizedChanges(newRequest, oldRequest.get(), user); + } + } + public abstract void checkForAuthorizedChanges( SingularityRequest request, SingularityRequest oldRequest, diff --git a/SingularityService/src/main/java/com/hubspot/singularity/auth/SingularityGroupsScopesAuthorizer.java b/SingularityService/src/main/java/com/hubspot/singularity/auth/SingularityGroupsScopesAuthorizer.java index 210c7ee104..ca5fa823bc 100644 --- a/SingularityService/src/main/java/com/hubspot/singularity/auth/SingularityGroupsScopesAuthorizer.java +++ b/SingularityService/src/main/java/com/hubspot/singularity/auth/SingularityGroupsScopesAuthorizer.java @@ -27,7 +27,7 @@ public class SingularityGroupsScopesAuthorizer extends SingularityAuthorizer { SingularityGroupsScopesAuthorizer.class ); - private final AuthConfiguration authConfiguration; + protected final AuthConfiguration authConfiguration; private final ScopesConfiguration scopesConfiguration; private final SingularityEventListener singularityEventListener; @@ -227,7 +227,7 @@ private boolean isJita(SingularityUser user) { return groupsIntersect(authConfiguration.getJitaGroups(), user.getGroups()); } - private boolean isAdmin(SingularityUser user) { + protected boolean isAdmin(SingularityUser user) { return hasScope(user, SingularityAuthorizationScope.ADMIN); } @@ -290,7 +290,7 @@ private void checkForbiddenForGroups( ); } - private Set getGroups( + protected Set getGroups( SingularityRequest request, SingularityAuthorizationScope scope ) { diff --git a/SingularityService/src/main/java/com/hubspot/singularity/resources/DeployResource.java b/SingularityService/src/main/java/com/hubspot/singularity/resources/DeployResource.java index b26ebcb036..b861e4c020 100644 --- a/SingularityService/src/main/java/com/hubspot/singularity/resources/DeployResource.java +++ b/SingularityService/src/main/java/com/hubspot/singularity/resources/DeployResource.java @@ -164,6 +164,13 @@ public SingularityRequestParent deploy( ); SingularityRequest request = requestWithState.getRequest(); + authorizationHelper.checkForAuthorization( + request, + deploy, + user, + SingularityAuthorizationScope.WRITE + ); + final Optional updatedValidatedRequest; if (deployRequest.getUpdatedRequest().isPresent()) { authorizationHelper.checkForAuthorizedChanges( diff --git a/SingularityService/src/main/java/com/hubspot/singularity/resources/RequestResource.java b/SingularityService/src/main/java/com/hubspot/singularity/resources/RequestResource.java index 6b3b999c20..082b3b10d1 100644 --- a/SingularityService/src/main/java/com/hubspot/singularity/resources/RequestResource.java +++ b/SingularityService/src/main/java/com/hubspot/singularity/resources/RequestResource.java @@ -193,13 +193,14 @@ private void submitRequest( ? Optional.of(oldRequestWithState.get().getRequest()) : Optional.empty(); + authorizationHelper.checkForAuthorizedChanges(request, oldRequest, user); + if (oldRequest.isPresent()) { authorizationHelper.checkForAuthorization( oldRequest.get(), user, SingularityAuthorizationScope.WRITE ); - authorizationHelper.checkForAuthorizedChanges(request, oldRequest.get(), user); validator.checkActionEnabled(SingularityAction.UPDATE_REQUEST); } else { validator.checkActionEnabled(SingularityAction.CREATE_REQUEST);