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

Rework auth to include scopes as well as groups #2092

Merged
merged 29 commits into from
Jun 4, 2020
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
2b70dc5
WIP, rework to include groups + scopes
ssalinas May 13, 2020
f882abe
finish scopes and dual authorizer
ssalinas May 14, 2020
3dc0f3a
cleaner
ssalinas May 14, 2020
6a989a8
first working test
ssalinas May 14, 2020
6f238e9
fix test module
ssalinas May 14, 2020
46b81ea
outline tests
ssalinas May 14, 2020
244b6cc
fill out tests
ssalinas May 14, 2020
86973eb
duplicate binding
ssalinas May 15, 2020
3440779
separate scope for deploy
ssalinas May 15, 2020
8fb48f6
separate scope for deploy
ssalinas May 15, 2020
524e7c0
missing break
ssalinas May 15, 2020
8cd5967
missing break in auth module
ssalinas May 15, 2020
715261f
more guice
ssalinas May 15, 2020
7a3607c
log full output when in trace
ssalinas May 18, 2020
5d1777c
more logging
ssalinas May 18, 2020
2185351
Rework response format for webhook auth
ssalinas May 18, 2020
e6aa1f1
Add files
ssalinas May 18, 2020
1247698
missing break
ssalinas May 18, 2020
0e371c0
One more roudn of format rework
ssalinas May 18, 2020
1c6f550
missed the extended constructors
ssalinas May 18, 2020
2d42b0b
don't log for filter methods
ssalinas May 18, 2020
d2909ed
wire up jita
ssalinas May 19, 2020
eff611a
global read read/write groups for bots
ssalinas May 29, 2020
0f3e931
only have to be currently authed for request to update
ssalinas May 29, 2020
b5354e0
fix unit test
ssalinas May 29, 2020
c4b2695
global write groups can also read
ssalinas Jun 1, 2020
8324489
fix overridden readOnly case
ssalinas Jun 1, 2020
e256784
wrap cache loader in async reloading
ssalinas Jun 1, 2020
8f698fd
One more try at refresh
ssalinas Jun 3, 2020
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 @@ -2,22 +2,16 @@

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Function;
import java.util.Optional;
import javax.annotation.Nonnull;
import java.util.function.Function;

public class SingularityRequestWithState {
private final SingularityRequest request;
private final RequestState state;
private final long timestamp;

public static Function<SingularityRequestWithState, String> REQUEST_STATE_TO_REQUEST_ID = new Function<SingularityRequestWithState, String>() {

@Override
public String apply(@Nonnull SingularityRequestWithState input) {
return input.getRequest().getId();
}
};
public static Function<SingularityRequestWithState, String> REQUEST_STATE_TO_REQUEST_ID = input ->
input.getRequest().getId();

public static String getRequestState(
Optional<SingularityRequestWithState> maybeRequestWithState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
import static com.google.common.collect.ImmutableSet.copyOf;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import java.security.Principal;
import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
Expand All @@ -17,6 +19,7 @@ public class SingularityUser implements Principal {
private final Optional<String> name;
private final Optional<String> email;
private final Set<String> groups;
private final Set<String> scopes;
private final boolean authenticated;

public static SingularityUser DEFAULT_USER = new SingularityUser(
Expand All @@ -36,18 +39,44 @@ public SingularityUser(
this(id, name, email, groups, true);
}

public SingularityUser(
String id,
Optional<String> name,
Optional<String> email,
Set<String> groups,
boolean authenticated
) {
this(id, name, email, groups, Collections.emptySet(), authenticated);
}

public SingularityUser withOnlyGroups() {
Set<String> mergedGroups = new HashSet<>();
mergedGroups.addAll(groups);
mergedGroups.addAll(scopes);
return new SingularityUser(
id,
name,
email,
mergedGroups,
Collections.emptySet(),
authenticated
);
}

@JsonCreator
public SingularityUser(
@JsonProperty("id") String id,
@JsonProperty("name") Optional<String> name,
@JsonProperty("email") Optional<String> email,
@JsonProperty("groups") Set<String> groups,
@JsonProperty("scopes") Set<String> scopes,
@JsonProperty("authenticated") boolean authenticated
) {
this.id = id;
this.name = name;
this.email = email;
this.groups = copyOf(groups);
this.scopes = scopes != null ? copyOf(scopes) : Collections.emptySet();
this.authenticated = authenticated;
}

Expand All @@ -66,37 +95,54 @@ public Optional<String> getEmail() {
return email;
}

@JsonIgnore
public Optional<String> getEmailOrDefault(Optional<String> defaultDomain) {
if (email.isPresent()) {
return email;
}
if (defaultDomain.isPresent()) {
return Optional.of(String.format("%s@%s", id, defaultDomain));
}
return Optional.empty();
}

@Schema(description = "Groups this user is a part of")
public Set<String> getGroups() {
return groups;
}

@Schema(description = "Scopes this user has")
public Set<String> getScopes() {
return scopes;
}

@Schema(description = "True if the user was successfully authenticated")
public boolean isAuthenticated() {
return authenticated;
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (obj instanceof SingularityUser) {
final SingularityUser that = (SingularityUser) obj;
return (
Objects.equals(this.authenticated, that.authenticated) &&
Objects.equals(this.id, that.id) &&
Objects.equals(this.name, that.name) &&
Objects.equals(this.email, that.email) &&
Objects.equals(this.groups, that.groups)
);
if (o == null || getClass() != o.getClass()) {
return false;
}
return false;
SingularityUser that = (SingularityUser) o;
return (
authenticated == that.authenticated &&
Objects.equals(id, that.id) &&
Objects.equals(name, that.name) &&
Objects.equals(email, that.email) &&
Objects.equals(groups, that.groups) &&
Objects.equals(scopes, that.scopes)
);
}

@Override
public int hashCode() {
return Objects.hash(id, name, email, groups, authenticated);
return Objects.hash(id, name, email, groups, scopes, authenticated);
}

@Override
Expand All @@ -112,6 +158,8 @@ public String toString() {
email +
", groups=" +
groups +
", scopes=" +
scopes +
", authenticated=" +
authenticated +
'}'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@
import com.google.inject.Module;
import com.google.inject.Scopes;
import com.google.inject.Stage;
import com.google.inject.util.Modules;
import com.hubspot.dropwizard.guicier.GuiceBundle;
import com.hubspot.jackson.datatype.protobuf.ProtobufModule;
import com.hubspot.singularity.auth.SingularityAuthModule;
import com.hubspot.singularity.bundles.CorsBundle;
import com.hubspot.singularity.config.ApiPaths;
import com.hubspot.singularity.config.MergingSourceProvider;
import com.hubspot.singularity.config.SingularityConfiguration;
import com.hubspot.singularity.data.history.SingularityDbModule;
import com.hubspot.singularity.guice.DropwizardObjectMapperProvider;
import io.dropwizard.Application;
import io.dropwizard.Bundle;
Expand All @@ -34,7 +33,6 @@
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.Optional;

@OpenAPIDefinition(
info = @Info(title = "Singularity"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import com.google.inject.Singleton;
import com.hubspot.dropwizard.guicier.DropwizardAwareModule;
import com.hubspot.mesos.client.SingularityMesosClientModule;
import com.hubspot.singularity.auth.SingularityAuthenticatorClass;
import com.hubspot.singularity.auth.dw.SingularityAuthenticatorClass;
import com.hubspot.singularity.config.IndexViewConfiguration;
import com.hubspot.singularity.config.SingularityConfiguration;
import com.hubspot.singularity.data.SingularityDataModule;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package com.hubspot.singularity;
package com.hubspot.singularity.auth;

import com.google.inject.Binder;
import com.google.inject.Scopes;
import com.google.inject.multibindings.Multibinder;
import com.google.inject.name.Names;
import com.hubspot.dropwizard.guicier.DropwizardAwareModule;
import com.hubspot.singularity.auth.SingularityAuthFeature;
import com.hubspot.singularity.auth.SingularityAuthenticatorClass;
import com.hubspot.singularity.auth.SingularityAuthorizationHelper;
import com.hubspot.singularity.SingularityAsyncHttpClient;
import com.hubspot.singularity.auth.authenticator.SingularityAuthenticator;
import com.hubspot.singularity.auth.authenticator.SingularityMultiMethodAuthenticator;
import com.hubspot.singularity.auth.datastore.SingularityAuthDatastore;
import com.hubspot.singularity.auth.dw.SingularityAuthFeature;
import com.hubspot.singularity.auth.dw.SingularityAuthenticatorClass;
import com.hubspot.singularity.config.AuthConfiguration;
import com.hubspot.singularity.config.SingularityConfiguration;
import com.ning.http.client.AsyncHttpClient;
Expand All @@ -25,6 +25,9 @@ public SingularityAuthModule() {}

@Override
public void configure(Binder binder) {
binder
.bind(AuthConfiguration.class)
.toInstance(getConfiguration().getAuthConfiguration());
Multibinder<SingularityAuthenticator> multibinder = Multibinder.newSetBinder(
binder,
SingularityAuthenticator.class
Expand All @@ -50,13 +53,33 @@ 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);
case GROUPS:
default:
binder
.bind(SingularityAuthorizer.class)
.to(SingularityGroupsAuthorizer.class)
.in(Scopes.SINGLETON);
}

binder.bind(SingularityAuthFeature.class);
binder.bind(SingularityMultiMethodAuthenticator.class);
binder
.bind(SingularityAuthDatastore.class)
.to(
getConfiguration().getAuthConfiguration().getDatastore().getAuthDatastoreClass()
);
binder.bind(SingularityAuthorizationHelper.class).in(Scopes.SINGLETON);
binder.bind(SingularityAuthorizer.class).in(Scopes.SINGLETON);
}
}
Loading