mirror of
https://github.com/google/nomulus.git
synced 2025-04-30 03:57:51 +02:00
Allow for multiple service accounts in authentication (#1963)
When submitting tasks to Cloud Tasks, we will use the built-in OIDC authentication which runs under the default service account (not the cloud scheduler service account). We want either to work for app-level auth.
This commit is contained in:
parent
8ab2252272
commit
cd0703c815
5 changed files with 30 additions and 12 deletions
|
@ -107,9 +107,9 @@ public final class RegistryConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Config("cloudSchedulerServiceAccountEmail")
|
@Config("serviceAccountEmails")
|
||||||
public static String provideCloudSchedulerServiceAccountEmail(RegistryConfigSettings config) {
|
public static ImmutableList<String> provideServiceAccountEmails(RegistryConfigSettings config) {
|
||||||
return config.gcpProject.cloudSchedulerServiceAccountEmail;
|
return ImmutableList.copyOf(config.gcpProject.serviceAccountEmails);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|
|
@ -54,7 +54,7 @@ public class RegistryConfigSettings {
|
||||||
public String backendServiceUrl;
|
public String backendServiceUrl;
|
||||||
public String toolsServiceUrl;
|
public String toolsServiceUrl;
|
||||||
public String pubapiServiceUrl;
|
public String pubapiServiceUrl;
|
||||||
public String cloudSchedulerServiceAccountEmail;
|
public List<String> serviceAccountEmails;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Configuration options for OAuth settings for authenticating users. */
|
/** Configuration options for OAuth settings for authenticating users. */
|
||||||
|
|
|
@ -22,8 +22,11 @@ gcpProject:
|
||||||
backendServiceUrl: https://localhost
|
backendServiceUrl: https://localhost
|
||||||
toolsServiceUrl: https://localhost
|
toolsServiceUrl: https://localhost
|
||||||
pubapiServiceUrl: https://localhost
|
pubapiServiceUrl: https://localhost
|
||||||
# Service account used by Cloud Scheduler to send authenticated requests.
|
# Service accounts eligible for authorization (e.g. default service account,
|
||||||
cloudSchedulerServiceAccountEmail: cloud-scheduler-email@email.com
|
# account used by Cloud Scheduler) to send authenticated requests.
|
||||||
|
serviceAccountEmails:
|
||||||
|
- default-service-account-email@email.com
|
||||||
|
- cloud-scheduler-email@email.com
|
||||||
|
|
||||||
gSuite:
|
gSuite:
|
||||||
# Publicly accessible domain name of the running G Suite instance.
|
# Publicly accessible domain name of the running G Suite instance.
|
||||||
|
|
|
@ -18,6 +18,7 @@ import static com.google.common.net.HttpHeaders.AUTHORIZATION;
|
||||||
import static google.registry.request.auth.AuthLevel.APP;
|
import static google.registry.request.auth.AuthLevel.APP;
|
||||||
|
|
||||||
import com.google.auth.oauth2.TokenVerifier;
|
import com.google.auth.oauth2.TokenVerifier;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import google.registry.config.RegistryConfig.Config;
|
import google.registry.config.RegistryConfig.Config;
|
||||||
import google.registry.request.auth.AuthModule.ServiceAccount;
|
import google.registry.request.auth.AuthModule.ServiceAccount;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -30,16 +31,16 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
*/
|
*/
|
||||||
public class ServiceAccountAuthenticationMechanism extends IdTokenAuthenticationBase {
|
public class ServiceAccountAuthenticationMechanism extends IdTokenAuthenticationBase {
|
||||||
|
|
||||||
private final String cloudSchedulerEmailPrefix;
|
|
||||||
private static final String BEARER_PREFIX = "Bearer ";
|
private static final String BEARER_PREFIX = "Bearer ";
|
||||||
|
|
||||||
|
private final ImmutableList<String> serviceAccountEmails;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ServiceAccountAuthenticationMechanism(
|
public ServiceAccountAuthenticationMechanism(
|
||||||
@ServiceAccount TokenVerifier tokenVerifier,
|
@ServiceAccount TokenVerifier tokenVerifier,
|
||||||
@Config("cloudSchedulerServiceAccountEmail") String cloudSchedulerEmailPrefix) {
|
@Config("serviceAccountEmails") ImmutableList<String> serviceAccountEmails) {
|
||||||
|
|
||||||
super(tokenVerifier);
|
super(tokenVerifier);
|
||||||
this.cloudSchedulerEmailPrefix = cloudSchedulerEmailPrefix;
|
this.serviceAccountEmails = serviceAccountEmails;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -53,7 +54,7 @@ public class ServiceAccountAuthenticationMechanism extends IdTokenAuthentication
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
AuthResult authResultFromEmail(String emailAddress) {
|
AuthResult authResultFromEmail(String emailAddress) {
|
||||||
if (emailAddress.equals(cloudSchedulerEmailPrefix)) {
|
if (serviceAccountEmails.stream().anyMatch(e -> e.equals(emailAddress))) {
|
||||||
return AuthResult.create(APP);
|
return AuthResult.create(APP);
|
||||||
} else {
|
} else {
|
||||||
return AuthResult.NOT_AUTHENTICATED;
|
return AuthResult.NOT_AUTHENTICATED;
|
||||||
|
|
|
@ -22,6 +22,7 @@ import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload;
|
||||||
import com.google.api.client.json.webtoken.JsonWebSignature;
|
import com.google.api.client.json.webtoken.JsonWebSignature;
|
||||||
import com.google.api.client.json.webtoken.JsonWebSignature.Header;
|
import com.google.api.client.json.webtoken.JsonWebSignature.Header;
|
||||||
import com.google.auth.oauth2.TokenVerifier;
|
import com.google.auth.oauth2.TokenVerifier;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -44,7 +45,8 @@ class ServiceAccountAuthenticationMechanismTest {
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void beforeEach() throws Exception {
|
void beforeEach() throws Exception {
|
||||||
serviceAccountAuthenticationMechanism =
|
serviceAccountAuthenticationMechanism =
|
||||||
new ServiceAccountAuthenticationMechanism(tokenVerifier, "sa-prefix@email.com");
|
new ServiceAccountAuthenticationMechanism(
|
||||||
|
tokenVerifier, ImmutableList.of("sa-prefix@email.com", "cloud-tasks@email.com"));
|
||||||
when(request.getHeader(AUTHORIZATION)).thenReturn("Bearer jwtValue");
|
when(request.getHeader(AUTHORIZATION)).thenReturn("Bearer jwtValue");
|
||||||
Payload payload = new Payload();
|
Payload payload = new Payload();
|
||||||
payload.setEmail("sa-prefix@email.com");
|
payload.setEmail("sa-prefix@email.com");
|
||||||
|
@ -59,6 +61,18 @@ class ServiceAccountAuthenticationMechanismTest {
|
||||||
assertThat(authResult.authLevel()).isEqualTo(AuthLevel.APP);
|
assertThat(authResult.authLevel()).isEqualTo(AuthLevel.APP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSuccess_secondEmail() throws Exception {
|
||||||
|
Payload payload = new Payload();
|
||||||
|
payload.setEmail("cloud-tasks@email.com");
|
||||||
|
token = new JsonWebSignature(new Header(), payload, new byte[0], new byte[0]);
|
||||||
|
when(tokenVerifier.verify("jwtValue")).thenReturn(token);
|
||||||
|
|
||||||
|
AuthResult authResult = serviceAccountAuthenticationMechanism.authenticate(request);
|
||||||
|
assertThat(authResult.isAuthenticated()).isTrue();
|
||||||
|
assertThat(authResult.authLevel()).isEqualTo(AuthLevel.APP);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testFails_authenticateWrongEmail() throws Exception {
|
void testFails_authenticateWrongEmail() throws Exception {
|
||||||
token.getPayload().set("email", "not-service-account-email@email.com");
|
token.getPayload().set("email", "not-service-account-email@email.com");
|
||||||
|
|
Loading…
Add table
Reference in a new issue