diff options
author | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2021-02-11 15:46:05 +0100 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2021-02-11 15:46:18 +0100 |
commit | 06ea9cecdddcf44c13cf42d53b3df415c2146361 (patch) | |
tree | 29856d7589d2decdcd571b2f7731e8e656c2aa52 /jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filter | |
parent | a782d867784893696b3f505f547b9ccc1a5fcf2b (diff) |
Athenz jdisc filter: support proxied access token from trusted peer
Diffstat (limited to 'jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filter')
-rw-r--r-- | jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filter/security/athenz/AthenzAuthorizationFilterTest.java | 106 |
1 files changed, 93 insertions, 13 deletions
diff --git a/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filter/security/athenz/AthenzAuthorizationFilterTest.java b/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filter/security/athenz/AthenzAuthorizationFilterTest.java index 768c1068dfc..429f02ab42f 100644 --- a/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filter/security/athenz/AthenzAuthorizationFilterTest.java +++ b/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filter/security/athenz/AthenzAuthorizationFilterTest.java @@ -22,7 +22,6 @@ import com.yahoo.vespa.athenz.utils.AthenzIdentities; import com.yahoo.vespa.athenz.zpe.AuthorizationResult; import com.yahoo.vespa.athenz.zpe.Zpe; import org.junit.Test; -import org.mockito.Mockito; import javax.security.auth.x500.X500Principal; import java.math.BigInteger; @@ -48,6 +47,10 @@ import static org.hamcrest.CoreMatchers.nullValue; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -59,10 +62,14 @@ public class AthenzAuthorizationFilterTest { private static final AthenzResourceName RESOURCE_NAME = new AthenzResourceName("domain", "my-resource-name"); private static final ZToken ROLE_TOKEN = new ZToken("v=Z1;d=domain;r=my-role;p=my-domain.my-service"); private static final AthenzAccessToken ACCESS_TOKEN = new AthenzAccessToken(JWT.create().sign(Algorithm.none())); - private static final AthenzIdentity IDENTITY = AthenzIdentities.from("user.john"); + private static final AthenzIdentity USER_IDENTITY = AthenzIdentities.from("user.john"); + private static final AthenzIdentity PROXY_IDENTITY = AthenzIdentities.from("proxy.service"); + private static final AthenzIdentity UNKNOWN_IDENTITY = AthenzIdentities.from("unknown.service"); private static final AthenzRole ROLE = new AthenzRole("my.domain", "my-role"); - private static final X509Certificate IDENTITY_CERTIFICATE = createDummyIdentityCertificate(IDENTITY); - private static final X509Certificate ROLE_CERTIFICATE = createDummyRoleCertificate(ROLE, IDENTITY); + private static final X509Certificate USER_IDENTITY_CERTIFICATE = createDummyIdentityCertificate(USER_IDENTITY); + private static final X509Certificate ROLE_CERTIFICATE = createDummyRoleCertificate(ROLE, USER_IDENTITY); + private static final X509Certificate PROXY_IDENTITY_CERTIFICATE = createDummyIdentityCertificate(PROXY_IDENTITY); + private static final X509Certificate UNKNOWN_IDENTITY_CERTIFICATE = createDummyIdentityCertificate(UNKNOWN_IDENTITY); private static final String ACTION = "update"; private static final String HEADER_NAME = "Athenz-Role-Token"; private static final String ACCEPTED_METRIC_NAME = "jdisc.http.filter.athenz.accepted_requests"; @@ -73,7 +80,7 @@ public class AthenzAuthorizationFilterTest { AthenzAuthorizationFilter filter = createFilter(new AllowingZpe(), List.of()); MockResponseHandler responseHandler = new MockResponseHandler(); - DiscFilterRequest request = createRequest(null, ACCESS_TOKEN, IDENTITY_CERTIFICATE); + DiscFilterRequest request = createRequest(null, ACCESS_TOKEN, USER_IDENTITY_CERTIFICATE); filter.filter(request, responseHandler); assertAuthorizationResult(request, Type.ALLOW); @@ -111,6 +118,66 @@ public class AthenzAuthorizationFilterTest { } @Test + public void accepts_request_with_proxied_access_token() { + Zpe zpe = mock(Zpe.class); + when(zpe.checkAccessAllowed(any(), any(), any(), any())).thenReturn(new AuthorizationResult(Type.ALLOW, ROLE)); + when(zpe.checkAccessAllowed((AthenzAccessToken) any(), any(), any())).thenReturn(new AuthorizationResult(Type.ALLOW, ROLE)); + AthenzAuthorizationFilter filter = createFilter(zpe, List.of(), new NullMetric(), PROXY_IDENTITY); + + MockResponseHandler responseHandler = new MockResponseHandler(); + DiscFilterRequest request = createRequest(null, ACCESS_TOKEN, PROXY_IDENTITY_CERTIFICATE); + filter.filter(request, responseHandler); + + assertAuthorizationResult(request, Type.ALLOW); + assertRequestNotFiltered(responseHandler); + assertMatchedCredentialType(request, EnabledCredentials.ACCESS_TOKEN); + assertMatchedRole(request, ROLE); + + // Verify expected checkAccessAllowed overload is invoked + verify(zpe, times(1)).checkAccessAllowed((AthenzAccessToken) any(), any(), any()); + verify(zpe, never()).checkAccessAllowed(any(), any(), any(), any()); + } + + @Test + public void accepts_request_with_access_token_and_matching_identity_certificate_with_proxy_support_enabled() { + Zpe zpe = mock(Zpe.class); + when(zpe.checkAccessAllowed(any(), any(), any(), any())).thenReturn(new AuthorizationResult(Type.ALLOW, ROLE)); + when(zpe.checkAccessAllowed((AthenzAccessToken) any(), any(), any())).thenReturn(new AuthorizationResult(Type.ALLOW, ROLE)); + AthenzAuthorizationFilter filter = createFilter(zpe, List.of(), new NullMetric(), PROXY_IDENTITY); + + MockResponseHandler responseHandler = new MockResponseHandler(); + DiscFilterRequest request = createRequest(null, ACCESS_TOKEN, USER_IDENTITY_CERTIFICATE); + filter.filter(request, responseHandler); + + assertAuthorizationResult(request, Type.ALLOW); + assertRequestNotFiltered(responseHandler); + assertMatchedCredentialType(request, EnabledCredentials.ACCESS_TOKEN); + assertMatchedRole(request, ROLE); + + // Verify expected checkAccessAllowed overload is invoked + verify(zpe, never()).checkAccessAllowed((AthenzAccessToken) any(), any(), any()); + verify(zpe, times(1)).checkAccessAllowed(any(), any(), any(), any()); + } + + @Test + public void returns_forbidden_when_identity_certificate_has_unknown_proxy_identity() { + Zpe zpe = mock(Zpe.class); + when(zpe.checkAccessAllowed(any(), any(), any(), any())).thenReturn(new AuthorizationResult(Type.DENY, ROLE)); + when(zpe.checkAccessAllowed((AthenzAccessToken) any(), any(), any())).thenReturn(new AuthorizationResult(Type.DENY, ROLE)); + AthenzAuthorizationFilter filter = createFilter(zpe, List.of(), new NullMetric(), PROXY_IDENTITY); + + MockResponseHandler responseHandler = new MockResponseHandler(); + DiscFilterRequest request = createRequest(null, ACCESS_TOKEN, UNKNOWN_IDENTITY_CERTIFICATE); + filter.filter(request, responseHandler); + + assertAuthorizationResult(request, Type.DENY); + + // Verify expected checkAccessAllowed overload is invoked + verify(zpe, never()).checkAccessAllowed((AthenzAccessToken) any(), any(), any()); + verify(zpe, times(1)).checkAccessAllowed(any(), any(), any(), any()); + } + + @Test public void returns_unauthorized_for_request_with_disabled_credential_type() { AthenzAuthorizationFilter filter = createFilter(new AllowingZpe(), List.of(EnabledCredentials.ROLE_CERTIFICATE, EnabledCredentials.ACCESS_TOKEN)); @@ -139,9 +206,9 @@ public class AthenzAuthorizationFilterTest { @Test public void reports_metrics_for_rejected_requests() { MetricMock metric = new MetricMock(); - AthenzAuthorizationFilter filter = createFilter(new DenyingZpe(), List.of(), metric); + AthenzAuthorizationFilter filter = createFilter(new DenyingZpe(), List.of(), metric, null); MockResponseHandler responseHandler = new MockResponseHandler(); - DiscFilterRequest request = createRequest(null, ACCESS_TOKEN, IDENTITY_CERTIFICATE); + DiscFilterRequest request = createRequest(null, ACCESS_TOKEN, USER_IDENTITY_CERTIFICATE); filter.filter(request, responseHandler); assertMetrics(metric, REJECTED_METRIC_NAME, Map.of("zpe-status", "DENY", "status-code", "403")); @@ -150,9 +217,9 @@ public class AthenzAuthorizationFilterTest { @Test public void reports_metrics_for_accepted_requests() { MetricMock metric = new MetricMock(); - AthenzAuthorizationFilter filter = createFilter(new AllowingZpe(), List.of(EnabledCredentials.ACCESS_TOKEN), metric); + AthenzAuthorizationFilter filter = createFilter(new AllowingZpe(), List.of(EnabledCredentials.ACCESS_TOKEN), metric, null); MockResponseHandler responseHandler = new MockResponseHandler(); - DiscFilterRequest request = createRequest(null, ACCESS_TOKEN, IDENTITY_CERTIFICATE); + DiscFilterRequest request = createRequest(null, ACCESS_TOKEN, USER_IDENTITY_CERTIFICATE); filter.filter(request, responseHandler); assertMetrics(metric, ACCEPTED_METRIC_NAME, Map.of("authz-required", "true")); @@ -190,7 +257,7 @@ public class AthenzAuthorizationFilterTest { } private static DiscFilterRequest createRequest(ZToken roleToken, AthenzAccessToken accessToken, X509Certificate clientCert) { - DiscFilterRequest request = Mockito.mock(DiscFilterRequest.class); + DiscFilterRequest request = mock(DiscFilterRequest.class); when(request.getHeader(HEADER_NAME)).thenReturn(roleToken != null ? roleToken.getRawToken() : null); when(request.getHeader(AthenzAccessToken.HTTP_HEADER_NAME)).thenReturn(accessToken != null ? "Bearer " + accessToken.value() : null); when(request.getMethod()).thenReturn("GET"); @@ -201,15 +268,18 @@ public class AthenzAuthorizationFilterTest { } private static AthenzAuthorizationFilter createFilter(Zpe zpe, List<EnabledCredentials.Enum> enabledCredentials) { - return createFilter(zpe, enabledCredentials, new NullMetric()); + return createFilter(zpe, enabledCredentials, new NullMetric(), null); } - private static AthenzAuthorizationFilter createFilter(Zpe zpe, List<EnabledCredentials.Enum> enabledCredentials, Metric metric) { + private static AthenzAuthorizationFilter createFilter(Zpe zpe, List<EnabledCredentials.Enum> enabledCredentials, + Metric metric, AthenzIdentity allowedProxyIdentity) { + List<String> allowedProxyIdentities = allowedProxyIdentity != null ? List.of(allowedProxyIdentity.getFullName()) : List.of(); return new AthenzAuthorizationFilter( new AthenzAuthorizationFilterConfig( new AthenzAuthorizationFilterConfig.Builder() .roleTokenHeaderName(HEADER_NAME) - .enabledCredentials(enabledCredentials)), + .enabledCredentials(enabledCredentials) + .allowedProxyIdentities(allowedProxyIdentities)), new StaticRequestResourceMapper(RESOURCE_NAME, ACTION), zpe, metric); @@ -260,6 +330,11 @@ public class AthenzAuthorizationFilterTest { public AuthorizationResult checkAccessAllowed(AthenzAccessToken accessToken, X509Certificate identityCertificate, AthenzResourceName resourceName, String action) { return new AuthorizationResult(Type.ALLOW, ROLE); } + + @Override + public AuthorizationResult checkAccessAllowed(AthenzAccessToken accessToken, AthenzResourceName resourceName, String action) { + return new AuthorizationResult(Type.ALLOW, ROLE); + } } private static class DenyingZpe implements Zpe { @@ -277,6 +352,11 @@ public class AthenzAuthorizationFilterTest { public AuthorizationResult checkAccessAllowed(AthenzAccessToken accessToken, X509Certificate identityCertificate, AthenzResourceName resourceName, String action) { return new AuthorizationResult(Type.DENY); } + + @Override + public AuthorizationResult checkAccessAllowed(AthenzAccessToken accessToken, AthenzResourceName resourceName, String action) { + return new AuthorizationResult(Type.DENY); + } } private static class MetricMock implements Metric { |