package keywhiz.service.resources.automation.v2; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableSet; import io.dropwizard.jackson.Jackson; import java.io.IOException; import java.net.URI; import java.util.Set; import keywhiz.IntegrationTestRule; import keywhiz.KeywhizService; import keywhiz.TestClients; import keywhiz.api.automation.v2.CreateClientRequestV2; import keywhiz.api.automation.v2.CreateGroupRequestV2; import keywhiz.api.automation.v2.CreateSecretRequestV2; import keywhiz.api.automation.v2.GroupDetailResponseV2; import keywhiz.api.model.Client; import keywhiz.api.model.SanitizedSecret; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; import org.junit.rules.RuleChain; import static javax.ws.rs.core.HttpHeaders.LOCATION; import static keywhiz.TestClients.clientRequest; import static keywhiz.client.KeywhizClient.JSON; import static org.assertj.core.api.Assertions.assertThat; public class GroupResourceTest { private static final ObjectMapper mapper = KeywhizService.customizeObjectMapper(Jackson.newObjectMapper()); OkHttpClient mutualSslClient; @ClassRule public static final RuleChain chain = IntegrationTestRule.rule(); @Before public void setUp() { mutualSslClient = TestClients.mutualSslClient(); } @Test public void createGroup_success() throws Exception { Response httpResponse = create(CreateGroupRequestV2.builder().name("group1").build()); assertThat(httpResponse.code()).isEqualTo(201); URI location = URI.create(httpResponse.header(LOCATION)); assertThat(location.getPath()).isEqualTo("/automation/v2/groups/group1"); } @Test public void createGroup_duplicate() throws Exception { CreateGroupRequestV2 request = CreateGroupRequestV2.builder().name("group2").build(); // Initial request OK create(request); // Duplicate request fails Response httpResponse = create(request); assertThat(httpResponse.code()).isEqualTo(409); } @Test public void groupInfo_notFound() throws Exception { Request get = clientRequest("/automation/v2/groups/non-existent").get().build(); Response httpResponse = mutualSslClient.newCall(get).execute(); assertThat(httpResponse.code()).isEqualTo(404); } @Test public void groupInfo_simple() throws Exception { // Sample group create(CreateGroupRequestV2.builder().name("group3").description("desc").build()); GroupDetailResponseV2 groupDetail = lookup("group3"); assertThat(groupDetail.name()).isEqualTo("group3"); assertThat(groupDetail.description()).isEqualTo("desc"); } @Test public void groupInfo_withAssociations() throws Exception { // Sample group create(CreateGroupRequestV2.builder().name("group4").description("desc").build()); // Sample client createClient("client4", "group4"); GroupDetailResponseV2 groupDetail = lookup("group4"); assertThat(groupDetail.name()).isEqualTo("group4"); assertThat(groupDetail.description()).isEqualTo("desc"); } @Test public void secretDetailForGroup() throws Exception { // Sample group create(CreateGroupRequestV2.builder().name("groupWithSecrets").description("desc").build()); // Sample client createSecret("groupWithSecrets", "test-secret"); Set<SanitizedSecret> secrets = secretsInfo("groupWithSecrets"); assertThat(secrets).hasSize(1); assertThat(secrets.iterator().next().name()).isEqualTo("test-secret"); } @Test public void clientDetailForGroup() throws Exception { // Sample group create(CreateGroupRequestV2.builder().name("groupWithClients").description("desc").build()); // Sample client createClient("test-client", "groupWithClients"); Set<Client> clients = clientsInfo("groupWithClients"); assertThat(clients).hasSize(1); assertThat(clients.iterator().next().getName()).isEqualTo("test-client"); } @Test public void groupListing() throws Exception { Set<String> groupsBefore = listing(); Set<String> expected = ImmutableSet.<String>builder() .addAll(groupsBefore) .add("group5") .build(); create(CreateGroupRequestV2.builder().name("group5").build()); assertThat(listing()).containsAll(expected); } @Test public void deleteGroup_success() throws Exception { create(CreateGroupRequestV2.builder().name("group6").build()); Response httpResponse = delete("group6"); assertThat(httpResponse.code()).isEqualTo(204); } @Test public void deleteGroup_notFound() throws Exception { Response httpResponse = delete("non-existent"); assertThat(httpResponse.code()).isEqualTo(404); } private Response createClient(String client, String... groups) throws IOException { ClientResourceTest clientResourceTest = new ClientResourceTest(); clientResourceTest.mutualSslClient = mutualSslClient; Response response = clientResourceTest.create( CreateClientRequestV2.builder().name(client).groups(groups).build()); assertThat(response.code()).isEqualTo(201); return response; } private Response createSecret(String group, String secret) throws IOException { SecretResourceTest secretResourceTest = new SecretResourceTest(); secretResourceTest.mutualSslClient = mutualSslClient; Response response = secretResourceTest.create( CreateSecretRequestV2.builder().name(secret).content("test").groups(group).build()); assertThat(response.code()).isEqualTo(201); return response; } Response create(CreateGroupRequestV2 request) throws IOException { RequestBody body = RequestBody.create(JSON, mapper.writeValueAsString(request)); Request post = clientRequest("/automation/v2/groups").post(body).build(); return mutualSslClient.newCall(post).execute(); } GroupDetailResponseV2 lookup(String group) throws IOException { Request get = clientRequest("/automation/v2/groups/" + group).get().build(); Response httpResponse = mutualSslClient.newCall(get).execute(); assertThat(httpResponse.code()).isEqualTo(200); return mapper.readValue(httpResponse.body().byteStream(), GroupDetailResponseV2.class); } Set<SanitizedSecret> secretsInfo(String group) throws IOException { Request get = clientRequest("/automation/v2/groups/" + group + "/secrets").get().build(); Response httpResponse = mutualSslClient.newCall(get).execute(); assertThat(httpResponse.code()).isEqualTo(200); return mapper.readValue(httpResponse.body().byteStream(), new TypeReference<Set<SanitizedSecret>>(){}); } Set<Client> clientsInfo(String group) throws IOException { Request get = clientRequest("/automation/v2/groups/" + group + "/clients").get().build(); Response httpResponse = mutualSslClient.newCall(get).execute(); assertThat(httpResponse.code()).isEqualTo(200); return mapper.readValue(httpResponse.body().byteStream(), new TypeReference<Set<Client>>(){}); } Set<String> listing() throws IOException { Request get = clientRequest("/automation/v2/groups").get().build(); Response httpResponse = mutualSslClient.newCall(get).execute(); assertThat(httpResponse.code()).isEqualTo(200); return mapper.readValue(httpResponse.body().byteStream(), new TypeReference<Set<String>>(){}); } Response delete(String name) throws IOException { Request delete = clientRequest("/automation/v2/groups/" + name).delete().build(); return mutualSslClient.newCall(delete).execute(); } }