Skip to content

Commit

Permalink
Add initial set of tests for AlisePlugin
Browse files Browse the repository at this point in the history
  • Loading branch information
paulmillar committed Jul 31, 2024
1 parent 9125f1c commit d6dcb9d
Show file tree
Hide file tree
Showing 2 changed files with 234 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.dcache.util;

import com.google.common.collect.Sets;
import java.net.URI;
import java.security.Principal;
import java.util.Collections;
import java.util.Set;
Expand All @@ -9,8 +10,10 @@
import org.dcache.auth.EmailAddressPrincipal;
import org.dcache.auth.ExemptFromNamespaceChecks;
import org.dcache.auth.FQANPrincipal;
import org.dcache.auth.FullNamePrincipal;
import org.dcache.auth.GidPrincipal;
import org.dcache.auth.GroupNamePrincipal;
import org.dcache.auth.OAuthProviderPrincipal;
import org.dcache.auth.OidcSubjectPrincipal;
import org.dcache.auth.UidPrincipal;
import org.dcache.auth.UserNamePrincipal;
Expand Down Expand Up @@ -52,12 +55,25 @@ public PrincipalSetMaker withUid(int uid) {
* Add a username Principal to the set.
*
* @param name the username to add
*
*/
public PrincipalSetMaker withUsername(String username) {
_principals.add(new UserNamePrincipal(username));
return this;
}

/**
* Add a Full Name Principal to the set.
*
* @param name the full name of the user.
*
*/
public PrincipalSetMaker withFullname(String name) {
_principals.add(new FullNamePrincipal(name));
return this;
}


/**
* Add a primary groupname Principal to the set.
*
Expand Down Expand Up @@ -152,6 +168,17 @@ public PrincipalSetMaker withOidc(String sub, String op) {
return this;
}

/**
* Add an OAuth2 Provider (OP) to the set.
*
* @param alias the name/alias of this OAuth2 Provider.
* @param uri the URI identity of the OAuth2 Provider.
*/
public PrincipalSetMaker withOauth2Provider(String alias, URI uri) {
_principals.add(new OAuthProviderPrincipal(alias, uri));
return this;
}

/**
* Add an Email principal to the set.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,220 @@
*/
package org.dcache.gplazma.alise;

import java.net.URI;
import java.security.Principal;
import java.util.Collection;
import java.util.Properties;
import java.util.Set;
import org.dcache.auth.UserNamePrincipal;
import org.dcache.gplazma.AuthenticationException;
import org.dcache.util.PrincipalSetMaker;
import org.dcache.util.Result;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.Before;
import org.mockito.ArgumentCaptor;
import java.util.HashSet;
import java.util.List;
import org.dcache.auth.FullNamePrincipal;

import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasItems;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class AlisePluginTest {

public AlisePluginTest() {
private AlisePlugin plugin;
private Set<Principal> principals;
private LookupAgent agent;
private List<Identity> lookupCalls;

@Before
public void setup() {
plugin = null;
principals = null;
agent = null;
lookupCalls = null;
}

@Test(expected=AuthenticationException.class)
public void shouldFailIfNoSubClaim() throws Exception {
given(anAlisePlugin()
.withProprety("gplazma.alise.issuers", "")
.withAgent(aLookupAgent().thatFailsTestIfCalled()));

whenPluginMapWith(principals().withDn("/O=ACME/CN=Wile E Coyote"));
}

@Test(expected=AuthenticationException.class)
public void shouldFailIfMissingOpPrincipal() throws Exception {
given(anAlisePlugin()
.withProprety("gplazma.alise.issuers", "")
.withAgent(aLookupAgent().thatFailsTestIfCalled()));

whenPluginMapWith(principals().withOidc("paul", "EXAMPLE-OP"));
}

@Test(expected=AuthenticationException.class)
public void shouldFailIfOpNotListed() throws Exception {
given(anAlisePlugin()
.withProprety("gplazma.alise.issuers", "EXAMPLE-OP")
.withAgent(aLookupAgent().thatFailsTestIfCalled()));

whenPluginMapWith(principals().withOidc("paul", "SOME-OTHER-OP"));
}

@Test
public void testSomeMethod() {
public void shouldAcceptSuccessfulLookupWithUsername() throws Exception {
given(anAlisePlugin()
.withProprety("gplazma.alise.issuers", "")
.withAgent(aLookupAgent().thatReturnsSuccess(principals().withUsername("paul"))));

whenPluginMapWith(principals()
.withOidc("paul", "EXAMPLE-OP")
.withOauth2Provider("EXAMPLE-OP", URI.create("https://example.org/")));

assertThat(lookupCalls, contains(new Identity(URI.create("https://example.org/"), "paul")));

assertThat(principals, hasItem(new UserNamePrincipal("paul")));
}

@Test(expected=AuthenticationException.class)
public void shouldFailIfLookupFails() throws Exception {
given(anAlisePlugin()
.withProprety("gplazma.alise.issuers", "")
.withAgent(aLookupAgent().thatReturnsFailure("fnord")));

try {
whenPluginMapWith(principals()
.withOidc("paul", "EXAMPLE-OP")
.withOauth2Provider("EXAMPLE-OP", URI.create("https://example.org/")));
} catch (AuthenticationException e) {
assertThat(e.getMessage(), containsString("fnord"));
throw e;
}
}

@Test
public void shouldAcceptSuccessfulLookupWithUsernameAndFullname() throws Exception {
given(anAlisePlugin()
.withProprety("gplazma.alise.issuers", "")
.withAgent(aLookupAgent().thatReturnsSuccess(principals()
.withUsername("paul")
.withFullname("Paul Millar"))));

whenPluginMapWith(principals()
.withOidc("paul", "EXAMPLE-OP")
.withOauth2Provider("EXAMPLE-OP", URI.create("https://example.org/")));

assertThat(lookupCalls, contains(new Identity(URI.create("https://example.org/"), "paul")));
assertThat(principals, hasItems(new UserNamePrincipal("paul"),
new FullNamePrincipal("Paul Millar")));
}

@Test
public void shouldFilterSuppressedOP() throws Exception {
given(anAlisePlugin()
.withProprety("gplazma.alise.issuers", "EXAMPLE-OP")
.withAgent(aLookupAgent().thatReturnsSuccess(principals()
.withUsername("paul"))));

whenPluginMapWith(principals()
.withOidc("paul", "EXAMPLE-OP")
.withOauth2Provider("EXAMPLE-OP", URI.create("https://example.org/"))
.withOidc("paul", "SOME-OTHER-OP")
.withOauth2Provider("SOME-OTHER-OP", URI.create("https://some-other.example.com/")));

assertThat(lookupCalls, contains(new Identity(URI.create("https://example.org/"), "paul")));
assertThat(principals, hasItems(new UserNamePrincipal("paul")));
}

private AlisePluginBuilder anAlisePlugin() {
return new AlisePluginBuilder();
}

private LookupAgentBuilder aLookupAgent() {
return new LookupAgentBuilder();
}

private PrincipalSetMaker principals() {
return new PrincipalSetMaker();
}

private void given(AlisePluginBuilder builder) {
plugin = builder.build();
}

private void whenPluginMapWith(PrincipalSetMaker maker) throws AuthenticationException {
// PrincipalSetMaker creates an unmodifiable Set; but, for gPlazma, we need a Set that can be modified.
principals = new HashSet<>(maker.build());

plugin.map(principals);

ArgumentCaptor<Identity> identityCaptor = ArgumentCaptor.forClass(Identity.class);
verify(agent).lookup(identityCaptor.capture());
lookupCalls = identityCaptor.getAllValues();
}

private class AlisePluginBuilder {
private final Properties config = new Properties();

private AlisePluginBuilder withProprety(String key, String value) {
config.setProperty(key, value);
return this;
}

private AlisePluginBuilder withAgent(LookupAgentBuilder builder) {
agent = builder.build();
return this;
}

private AlisePlugin build() {
checkState(agent != null);
return new AlisePlugin(config, agent);
}
}

private static class LookupAgentBuilder {
private final LookupAgent agent = mock(LookupAgent.class);
private Result<Collection<Principal>,String> result;
private boolean failTest;

private LookupAgentBuilder thatReturnsFailure(String failure) {
checkState(result == null);
checkState(!failTest);
result = Result.failure(requireNonNull(failure));
return this;
}

private LookupAgentBuilder thatReturnsSuccess(PrincipalSetMaker maker) {
checkState(result == null);
checkState(!failTest);
result = Result.success(maker.build());
return this;
}

private LookupAgentBuilder thatFailsTestIfCalled() {
checkState(result == null);
failTest = true;
return this;
}

private LookupAgent build() {
checkState(result != null || failTest);
if (failTest) {
when(agent.lookup(any())).thenThrow(new AssertionError("Unexpected call to LookupAgent#lookup"));
} else {
when(agent.lookup(any())).thenReturn(result);
}
return agent;
}
}
}

0 comments on commit d6dcb9d

Please sign in to comment.