From f910572cb791d3f5c60fd391c6e79a42421d1231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9line=20Pelletier?= <82821620+celinepelletier@users.noreply.github.com> Date: Fri, 21 Jun 2024 11:36:27 -0400 Subject: [PATCH] :boom: fix: SKFP-1033 remove legacy code (#300) --- JenkinsfileNext | 16 -- .../core/service/CavaticaService.java | 55 ---- .../kidsfirst/web/rest/CavaticaResource.java | 67 ----- .../web/rest/FenceResourceDeprecated.java | 107 -------- .../io/kidsfirst/web/rest/KeysResource.java | 58 ----- .../java/io/kidsfirst/keys/CavaticaTests.java | 160 ------------ .../kidsfirst/keys/FenceDeprecatedTests.java | 234 ------------------ .../java/io/kidsfirst/keys/KeyStoreTests.java | 109 -------- 8 files changed, 806 deletions(-) delete mode 100644 JenkinsfileNext delete mode 100644 src/main/java/io/kidsfirst/core/service/CavaticaService.java delete mode 100644 src/main/java/io/kidsfirst/web/rest/CavaticaResource.java delete mode 100644 src/main/java/io/kidsfirst/web/rest/FenceResourceDeprecated.java delete mode 100644 src/main/java/io/kidsfirst/web/rest/KeysResource.java delete mode 100644 src/test/java/io/kidsfirst/keys/CavaticaTests.java delete mode 100644 src/test/java/io/kidsfirst/keys/FenceDeprecatedTests.java delete mode 100644 src/test/java/io/kidsfirst/keys/KeyStoreTests.java diff --git a/JenkinsfileNext b/JenkinsfileNext deleted file mode 100644 index 69151f3..0000000 --- a/JenkinsfileNext +++ /dev/null @@ -1,16 +0,0 @@ -@Library(value='kids-first/aws-infra-jenkins-shared-libraries', changelog=false) _ -ecs_service_type_1_standard { - jenkinsfile_name = "JenkinsfileNext" - projectName = "kf-key-manager-next" - internal_app = "false" - environments = "qa,prd" - docker_image_type = "debian" - dependencies = "ecr" - create_default_iam_role = "0" - entrypoint_command = "java -jar /opt/kidsfirst/keys/keys.jar" - quick_deploy = "true" - create_additional_internal_alb = "1" - container_port = "8080" - health_check_path = "/status" - additional_ssl_cert_domain_name = "*.kidsfirstdrc.org" -} diff --git a/src/main/java/io/kidsfirst/core/service/CavaticaService.java b/src/main/java/io/kidsfirst/core/service/CavaticaService.java deleted file mode 100644 index 012ae7d..0000000 --- a/src/main/java/io/kidsfirst/core/service/CavaticaService.java +++ /dev/null @@ -1,55 +0,0 @@ -package io.kidsfirst.core.service; - -import io.netty.channel.ChannelOption; -import io.netty.handler.timeout.ReadTimeoutHandler; -import io.netty.handler.timeout.WriteTimeoutHandler; -import lombok.val; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; -import org.springframework.http.client.reactive.ReactorClientHttpConnector; -import org.springframework.stereotype.Service; -import org.springframework.web.reactive.function.client.WebClient; -import reactor.core.publisher.Mono; -import reactor.netty.http.client.HttpClient; - -import java.time.Duration; -import java.util.concurrent.TimeUnit; - -@Service -public class CavaticaService { - - private final WebClient client; - - public CavaticaService(@Value("${application.cavatica_root}") String cavaticaRoot) { - val httpClient = HttpClient.create() - .followRedirect(true) - .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000) - .responseTimeout(Duration.ofMillis(10000)) - .doOnConnected(conn -> - conn.addHandlerLast(new ReadTimeoutHandler(10000, TimeUnit.MILLISECONDS)) - .addHandlerLast(new WriteTimeoutHandler(5000, TimeUnit.MILLISECONDS))); - this.client = WebClient.builder() - .clientConnector(new ReactorClientHttpConnector(httpClient)) - - .baseUrl(cavaticaRoot) - .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .build(); - } - - public Mono sendCavaticaRequest(String cavaticaKey, String path, String method, String body) { - return client - .method(HttpMethod.valueOf(method)) - .uri(path).bodyValue(body) - .header("X-SBG-Auth-Token", cavaticaKey) - .exchangeToMono(r -> { - if (r.statusCode().is2xxSuccessful()) { - return r.bodyToMono(String.class); - } else { - return r.createException() - .flatMap(Mono::error); - } - }); - } -} diff --git a/src/main/java/io/kidsfirst/web/rest/CavaticaResource.java b/src/main/java/io/kidsfirst/web/rest/CavaticaResource.java deleted file mode 100644 index 239a41b..0000000 --- a/src/main/java/io/kidsfirst/web/rest/CavaticaResource.java +++ /dev/null @@ -1,67 +0,0 @@ -package io.kidsfirst.web.rest; - -import io.kidsfirst.core.service.CavaticaService; -import io.kidsfirst.core.service.SecretService; -import lombok.val; -import net.minidev.json.JSONObject; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import reactor.core.publisher.Mono; - -import java.util.Arrays; -import java.util.Map; - -@RestController -@RequestMapping("/cavatica") -public class CavaticaResource { - - private final SecretService secretService; - private final CavaticaService cavaticaService; - - private final String[] HTTP_ALLOWED_METHODS = new String[]{"GET", "POST", "PUT", "PATCH", "DELETE"}; - - public CavaticaResource(SecretService secretService, CavaticaService cavaticaService) { - this.secretService = secretService; - this.cavaticaService = cavaticaService; - } - - @PostMapping(produces = MediaType.APPLICATION_JSON_VALUE) - public Mono> cavatica(@RequestBody(required = false) JSONObject requestBody, JwtAuthenticationToken authentication) { - val userId = authentication.getTokenAttributes().get("sub").toString(); - val cavaticaKey = getCavaticaKey(userId); - - // Path - val path = (String) requestBody.get("path"); - if (path == null) { - throw new IllegalArgumentException("No Parameter found for 'path' in body."); - } - - // Method - String method = ((String) requestBody.get("method")).toUpperCase(); - if (Arrays.stream(HTTP_ALLOWED_METHODS).noneMatch(allowed -> allowed.equals(method))) { - return Mono.just(ResponseEntity.badRequest().build()); - } - - // Body - val bodyMap = (Map) requestBody.get("body"); - val body = bodyMap != null ? new JSONObject(bodyMap) : null; - val bodyString = body == null ? "" : body.toJSONString(); - - return cavaticaKey.flatMap(key -> cavaticaService.sendCavaticaRequest(key, path, method, bodyString)) - .map(ResponseEntity::ok) - .defaultIfEmpty(ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()); - } - - private Mono getCavaticaKey(String userId) throws IllegalArgumentException { - return secretService.fetchAndDecrypt(userId, "cavatica"); - - } - - -} diff --git a/src/main/java/io/kidsfirst/web/rest/FenceResourceDeprecated.java b/src/main/java/io/kidsfirst/web/rest/FenceResourceDeprecated.java deleted file mode 100644 index 3db81be..0000000 --- a/src/main/java/io/kidsfirst/web/rest/FenceResourceDeprecated.java +++ /dev/null @@ -1,107 +0,0 @@ -package io.kidsfirst.web.rest; - -import io.kidsfirst.core.service.FenceService; -import io.kidsfirst.core.service.SecretService; -import lombok.extern.slf4j.Slf4j; -import lombok.val; -import net.minidev.json.JSONObject; -import org.springframework.http.ResponseEntity; -import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; -import org.springframework.web.bind.annotation.*; -import reactor.core.publisher.Mono; -import reactor.util.function.Tuple2; - -@RestController -@RequestMapping("/") -@Slf4j -public class FenceResourceDeprecated { - - private final FenceService fenceService; - private final SecretService secretService; - - public FenceResourceDeprecated(FenceService fenceService, SecretService secretService) { - this.fenceService = fenceService; - this.secretService = secretService; - } - - @GetMapping("/auth-client") - public Mono getAuthClient(@RequestParam("fence") String fenceKey) throws IllegalArgumentException { - val fence = fenceService.getFence(fenceKey); - //No UserID check - no auth required - val body = new JSONObject(); - body.put("client_id", fence.getClientId()); - body.put("redirect_uri", fence.getRedirectUri()); - body.put("scope", fence.getScope()); - - return Mono.just(body); - } - - @GetMapping("/token") - public Mono> getTokens(@RequestParam("fence") String fenceKey, JwtAuthenticationToken authentication) { - val userId = authentication.getTokenAttributes().get("sub").toString(); - - val fence = fenceService.getFence(fenceKey); - - val accessToken = secretService.fetchAccessToken(fence, userId); - val refreshToken = secretService.fetchRefreshToken(fence, userId); - - return accessToken - .zipWith(refreshToken) - .map(Tuple2::getT1) - .map(token -> { - - val body = new JSONObject(); - body.put("access_token", token); - return ResponseEntity.ok(body); - - }) - .defaultIfEmpty(ResponseEntity.notFound().build()) - .onErrorReturn(ResponseEntity.notFound().build()); - - } - - @PostMapping("/refresh") - public Mono> refresh(@RequestParam("fence") String fenceKey, JwtAuthenticationToken authentication) { - val userId = authentication.getTokenAttributes().get("sub").toString(); - val fence = fenceService.getFence(fenceKey); - val storedRefresh = secretService.fetchRefreshToken(fence, userId); - return storedRefresh - .flatMap(refresh -> fenceService.refreshTokens(refresh, fence)) - .flatMap(tokens -> { - val body = new JSONObject(); - body.put("access_token", tokens.getAccessToken().getValue()); - body.put("refresh_token", tokens.getRefreshToken().getValue()); - return secretService.persistTokens(fence, userId, tokens) - .then(Mono.just(ResponseEntity.ok().body(body))); - } - ).defaultIfEmpty(ResponseEntity.notFound().build()); - } - - - @PostMapping("/token") - public Mono> requestTokens(@RequestParam("code") String - authCode, @RequestParam("fence") String fenceKey, JwtAuthenticationToken authentication) { - val userId = authentication.getTokenAttributes().get("sub").toString(); - val fence = fenceService.getFence(fenceKey); - return fenceService.requestTokens(authCode, fence) - .flatMap(t -> { - val body = new JSONObject(); - body.put("access_token", t.getAccessToken().getValue()); - body.put("refresh_token", t.getRefreshToken().getValue()); - val response = ResponseEntity.ok().body(body); - return secretService.persistTokens(fence, userId, t, true).then(Mono.just(response)); - }) - .defaultIfEmpty(ResponseEntity.notFound().build()); - - } - - @DeleteMapping("/token") - public Mono> deleteToken(@RequestParam("fence") String fenceKey, JwtAuthenticationToken - authentication) { - val userId = authentication.getTokenAttributes().get("sub").toString(); - val fence = fenceService.getFence(fenceKey); - return secretService.removeFenceTokens(fence, userId).then(Mono.just(ResponseEntity.ok().build())); - } - - -} diff --git a/src/main/java/io/kidsfirst/web/rest/KeysResource.java b/src/main/java/io/kidsfirst/web/rest/KeysResource.java deleted file mode 100644 index fb3b3eb..0000000 --- a/src/main/java/io/kidsfirst/web/rest/KeysResource.java +++ /dev/null @@ -1,58 +0,0 @@ -package io.kidsfirst.web.rest; - -import io.kidsfirst.core.model.Secret; -import io.kidsfirst.core.service.SecretService; -import lombok.extern.slf4j.Slf4j; -import lombok.val; -import net.minidev.json.JSONObject; -import org.springframework.http.MediaType; -import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; -import org.springframework.web.bind.annotation.*; -import reactor.core.publisher.Mono; - -@Slf4j -@RestController -@RequestMapping("/key-store") -public class KeysResource { - - private final SecretService secretService; - - public KeysResource(SecretService secretService){ - this.secretService = secretService; - } - - @GetMapping(produces = MediaType.TEXT_PLAIN_VALUE) - public Mono getSecret(@RequestParam("service") String service, JwtAuthenticationToken authentication){ - val userId = authentication.getTokenAttributes().get("sub").toString(); - - return secretService.fetchAndDecrypt(userId, service); - } - - @PutMapping - public Mono saveSecret(@RequestBody JSONObject body, JwtAuthenticationToken authentication){ - val userId = authentication.getTokenAttributes().get("sub").toString(); - - // === 1. Get service and secretValue from event - val service = (String)body.get("service"); - val secretValue = (String)body.get("secret"); - - // === 2. Create a Secret to hold the data - val secret = new Secret(userId, service, secretValue, null); - - // === 3. Save to dynamo DB - return secretService.encryptAndSave(secret).then(); - - - } - - @DeleteMapping - public Mono deleteSecret(@RequestBody JSONObject body, JwtAuthenticationToken authentication){ - val userId = authentication.getTokenAttributes().get("sub").toString(); - val service = (String)body.get("service"); - - return secretService.deleteSecret(service, userId).then(); - - } - - -} \ No newline at end of file diff --git a/src/test/java/io/kidsfirst/keys/CavaticaTests.java b/src/test/java/io/kidsfirst/keys/CavaticaTests.java deleted file mode 100644 index d0ea0dc..0000000 --- a/src/test/java/io/kidsfirst/keys/CavaticaTests.java +++ /dev/null @@ -1,160 +0,0 @@ -package io.kidsfirst.keys; - -import com.github.tomakehurst.wiremock.junit5.WireMockExtension; -import lombok.extern.slf4j.Slf4j; -import lombok.val; -import net.minidev.json.JSONObject; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; -import org.springframework.http.MediaType; -import org.springframework.test.context.DynamicPropertyRegistry; -import org.springframework.test.context.DynamicPropertySource; - -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; -import static com.github.tomakehurst.wiremock.client.WireMock.*; - - -@Slf4j -public class CavaticaTests extends AbstractTest { - - protected static String defaultAccessToken = ""; - private final String cavaticaURI = "/cavatica"; - private final String cavaticaResponseBody = "{" + - " \"href\": \"https://cavatica-api.sbgenomics.com/v2/users/RFranklin\"," + - " \"username\": \"RFranklin\"," + - " \"email\": \"rosalind.franklin@sbgenomics.com\"," + - " \"first_name\": \"Rosalind\"," + - " \"last_name\": \"Franklin\"," + - " \"tags\": [" + - " {" + - " \"tag\": \"tcga-oa\"," + - " \"expires_at\": 3053937952000" + - " }," + - " {" + - " \"tag\": \"tcga-ca\"," + - " \"expires_at\": 1506729600000" + - " }" + - " ]," + - " \"affiliation\": \"Seven Bridges\"," + - " \"phone\": \"\"," + - " \"address\": \"\"," + - " \"city\": \"London\"," + - " \"state\": \"\"," + - " \"country\": \"United Kingdom\"," + - " \"zip_code\": \"\"" + - "}"; - - @BeforeAll - static void initTest(){ - val userAndToken = createUserAndSecretAndObtainAccessToken("cavatica", "cavatica_secret"); - defaultAccessToken = userAndToken.getAccessToken(); - } - - @RegisterExtension - static WireMockExtension cavaticaWM = WireMockExtension.newInstance() - .options(wireMockConfig().dynamicPort()) - .build(); - - @DynamicPropertySource - static void setCavaticaUri(DynamicPropertyRegistry registry) { - registry.add("application.cavatica_root", - () -> cavaticaWM.baseUrl()); - } - - @Test - public void testCavaticaPreflight() { - webClient.options() - .uri(cavaticaURI) - .exchange() - .expectStatus().is2xxSuccessful() - .expectHeader().value("Allow", matchValues("POST", "OPTIONS")); - } - - @Test - void testCavaticaPostWithoutToken() { - JSONObject content = new JSONObject(); - content.put("path", "/user"); - content.put("method", "GET"); - - JSONObject body = new JSONObject(); - body.put("key1", "value1"); - body.put("key2", "value2"); - content.put("body", body); - - webClient.post() - .uri(cavaticaURI) - .bodyValue(content.toJSONString()) - .accept(MediaType.APPLICATION_JSON) - .exchange() - .expectStatus().isUnauthorized(); - } - - @Test - void testHealthStatus() { - webClient.get().uri("/status") - .exchange() - .expectStatus().isOk() - .expectBody().json("{\"status\": \"OK\"}"); - } - - @Test - void testCavaticaPostWithoutBody() { - JSONObject content = new JSONObject(); - content.put("path", "/user"); - content.put("method", "GET"); - cavaticaWM.stubFor(get("/user").willReturn(ok(cavaticaResponseBody))); - webClient.post() - .uri("/cavatica") - .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + defaultAccessToken) - .bodyValue(content.toJSONString()) - .exchange() - .expectStatus().isOk() - .expectBody().json(cavaticaResponseBody); - - } - - - @Test - void testCavaticaPostWithBody() { - JSONObject content = new JSONObject(); - content.put("path", "/user"); - content.put("method", "GET"); - - JSONObject body = new JSONObject(); - body.put("key1", "value1"); - body.put("key2", "value2"); - content.put("body", body); - - cavaticaWM.stubFor(get("/user").willReturn(ok(cavaticaResponseBody))); - webClient.post() - .uri("/cavatica") - .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + defaultAccessToken) - .bodyValue(content.toJSONString()) - .exchange() - .expectStatus().isOk() - .expectBody().json(cavaticaResponseBody); - } - - @Test - void testCavaticaUnsupported() { - JSONObject content = new JSONObject(); - content.put("path", "/user"); - content.put("method", "UNSUPORTED"); - cavaticaWM.stubFor(get("/user").willReturn(ok(cavaticaResponseBody))); - webClient.post() - .uri("/cavatica") - .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + defaultAccessToken) - .bodyValue(content.toJSONString()) - .exchange() - .expectStatus().isEqualTo(400); - } - - -} diff --git a/src/test/java/io/kidsfirst/keys/FenceDeprecatedTests.java b/src/test/java/io/kidsfirst/keys/FenceDeprecatedTests.java deleted file mode 100644 index 6bcb4ea..0000000 --- a/src/test/java/io/kidsfirst/keys/FenceDeprecatedTests.java +++ /dev/null @@ -1,234 +0,0 @@ -package io.kidsfirst.keys; - -import com.github.tomakehurst.wiremock.junit5.WireMockExtension; -import io.kidsfirst.core.model.Secret; -import lombok.extern.slf4j.Slf4j; -import lombok.val; -import net.minidev.json.JSONObject; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; -import org.springframework.http.MediaType; -import org.springframework.test.context.DynamicPropertyRegistry; -import org.springframework.test.context.DynamicPropertySource; - -import java.time.temporal.ChronoUnit; -import java.util.concurrent.ExecutionException; - -import static com.github.tomakehurst.wiremock.client.WireMock.ok; -import static com.github.tomakehurst.wiremock.client.WireMock.post; -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; -import static java.time.Instant.now; -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -@Slf4j -public class FenceDeprecatedTests extends AbstractTest { - - - private final String fenceAuthClientUri = "/auth-client"; - private final String fenceTokenUri = "/token"; - private final String fenceRefreshUri = "/refresh"; - - protected static String defaultAccessToken = ""; - @BeforeAll - static void initTest(){ - val userAndToken = createUserAndSecretAndObtainAccessToken("cavatica", "cavatica_secret"); - defaultAccessToken = userAndToken.getAccessToken(); - } - - @RegisterExtension - static WireMockExtension gen3VM = WireMockExtension.newInstance() - .options(wireMockConfig().dynamicPort()) - .build(); - - @DynamicPropertySource - static void setGen3Uri(DynamicPropertyRegistry registry) { - registry.add("application.fence.gen3.token_endpoint", - () -> gen3VM.baseUrl()); - } - - - @Test - void testFenceAuthClientPreflight() { - webClient.options() - .uri(fenceAuthClientUri) - .exchange() - .expectStatus().is2xxSuccessful() - .expectHeader().value("Allow", matchValues("GET", "HEAD", "OPTIONS")); - - } - - @Test - void testFenceDCFAuthClientGET() { - webClient.get() - .uri(uriBuilder -> uriBuilder - .path(fenceAuthClientUri) - .queryParam("fence", "dcf") - .build()) - .header("Authorization", "Bearer " + defaultAccessToken) - - .exchange() - .expectStatus().is2xxSuccessful() - .expectBody().jsonPath("$.scope").exists() - .json("{\"scope\":\"openid\",\"redirect_uri\":\"https://portal.kidsfirstdrc.org/dcf_redirect/\",\"client_id\":\"dcf_client_id\"}"); - - } - - @Test - void testFenceGEN3AuthClientGET() { - webClient.get() - .uri(uriBuilder -> uriBuilder - .path(fenceAuthClientUri) - .queryParam("fence", "gen3") - .build()) - .header("Authorization", "Bearer " + defaultAccessToken) - - .exchange() - .expectStatus().is2xxSuccessful() - .expectBody().jsonPath("$.scope").exists() - .json("{\"scope\":\"openid%20user\",\"redirect_uri\":\"https://portal.kidsfirstdrc.org/gen3_redirect/\",\"client_id\":\"gen3_client_id\"}"); - } - - - @Test - void testFenceRefreshPreflight() { - webClient.options() - .uri(fenceRefreshUri) - .exchange() - .expectStatus().is2xxSuccessful() - .expectHeader() - .value("Allow", matchValues("POST", "OPTIONS")); - - } - - @Test - void testFenceRefreshPOST() throws Exception { - val expirationRefresh = now().plus(10, ChronoUnit.SECONDS).getEpochSecond(); - val userIdAndToken = createUserAndSecretAndObtainAccessToken("fence_gen3_refresh", "secret", expirationRefresh); - JSONObject content = new JSONObject(); - content.put("access_token", "this_is_access_token"); - content.put("refresh_token", "this_is_a_fresh_refresh_token"); - content.put("token_type", "BEARER"); - gen3VM.stubFor(post("/").willReturn(ok(content.toJSONString()).withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE))); - webClient - .post() - .uri(uriBuilder -> uriBuilder - .path(fenceRefreshUri) - .queryParam("fence", "gen3") - .build()) - .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + userIdAndToken.getAccessToken()) - .exchange() - .expectStatus().isOk() - .expectBody() - .jsonPath("$.access_token").value(o -> assertThat(o).isEqualTo("this_is_access_token")) - .jsonPath("$.refresh_token").value(o -> assertThat(o).isEqualTo("this_is_a_fresh_refresh_token")); - - val accessSecret = secretTable.getItem(new Secret(userIdAndToken.getUserId(), "fence_gen3_access", null, null)).get(); - assertThat(accessSecret).isNotNull(); - assertThat(accessSecret.getSecret()).isEqualTo("encrypted_compressed_this_is_access_token"); - - val refreshSecret = secretTable.getItem(new Secret(userIdAndToken.getUserId(), "fence_gen3_refresh", null, null)).get(); - assertThat(refreshSecret).isNotNull(); - assertThat(refreshSecret.getSecret()).isEqualTo("encrypted_compressed_this_is_a_fresh_refresh_token"); - assertThat(refreshSecret.getExpiration()).isEqualTo(expirationRefresh); - - } - - - @Test - void testFenceTokenPreflight() { - webClient.options() - .uri(fenceTokenUri) - .exchange() - .expectStatus().is2xxSuccessful() - .expectHeader() - - .value("Allow", matchValues("GET", "HEAD", "DELETE", "POST", "OPTIONS")); - - } - - @Test - void testFenceTokenDELETE() throws ExecutionException, InterruptedException { - val userIdAndToken = createUserAndSecretAndObtainAccessToken("fence_gen3_access", "secret"); - createSecret("fence_gen3_refresh", userIdAndToken.getUserId(), "secret"); - webClient - .delete() - .uri(uriBuilder -> uriBuilder - .path(fenceTokenUri) - .queryParam("fence", "gen3") - .build()) - .accept(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + userIdAndToken.getAccessToken()) - .exchange().expectStatus().isOk(); - val accessSecret = secretTable.getItem(new Secret(userIdAndToken.getUserId(), "fence_gen3_access", null, null)).get(); - assertThat(accessSecret).isNull(); - - val refreshSecret = secretTable.getItem(new Secret(userIdAndToken.getUserId(), "fence_gen3_refresh", null, null)).get(); - assertThat(refreshSecret).isNull(); - - - } - - - - @Test - void testFenceGEN3TokenGET() { - val userIdAndToken = createUserAndSecretAndObtainAccessToken("fence_gen3_access", "this_is_access_token"); - createSecret("fence_gen3_refresh", userIdAndToken.getUserId(), "this_is_refresh_token"); - webClient - .get() - .uri(uriBuilder -> uriBuilder - .path(fenceTokenUri) - .queryParam("fence", "gen3") - .build()) - .accept(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + userIdAndToken.getAccessToken()) - .exchange() - .expectStatus().isOk() - .expectBody() - .jsonPath("$.access_token").value(o -> assertThat(o).isEqualTo("this_is_access_token")); - - } - - @Test - void testFenceTokenPOST() throws Exception { - val expiration = now().minus(10, ChronoUnit.SECONDS).getEpochSecond(); - val userIdAndToken = createUserAndSecretAndObtainAccessToken("fence_gen3_access", "this_is_access_token", expiration); - createUserAndSecretAndObtainAccessToken("fence_gen3_refresh", "this_is_refresh_token", expiration); - JSONObject content = new JSONObject(); - content.put("access_token", "this_is_fresh_access_token"); - content.put("refresh_token", "this_is_fresh_refresh_token"); - content.put("token_type", "BEARER"); - content.put("expires_in", 1200); - gen3VM.stubFor(post("/").willReturn(ok(content.toJSONString()).withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE))); - webClient - .post() - .uri(uriBuilder -> uriBuilder - .path(fenceTokenUri) - .queryParam("fence", "gen3") - .queryParam("code", "anAuthCodeValue") - .build()) - .accept(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + userIdAndToken.getAccessToken()) - .exchange() - .expectStatus().isOk() - .expectBody() - .jsonPath("$.access_token").value(o -> assertThat(o).isEqualTo("this_is_fresh_access_token")) - .jsonPath("$.refresh_token").value(o -> assertThat(o).isEqualTo("this_is_fresh_refresh_token")); - - val accessSecret = secretTable.getItem(new Secret(userIdAndToken.getUserId(), "fence_gen3_access", null, null)).get(); - assertThat(accessSecret).isNotNull(); - assertThat(accessSecret.getSecret()).isEqualTo("encrypted_compressed_this_is_fresh_access_token"); - assertThat(accessSecret.getExpiration()).isGreaterThan(expiration); - - val refreshSecret = secretTable.getItem(new Secret(userIdAndToken.getUserId(), "fence_gen3_refresh", null, null)).get(); - assertThat(refreshSecret).isNotNull(); - assertThat(refreshSecret.getSecret()).isEqualTo("encrypted_compressed_this_is_fresh_refresh_token"); - assertThat(refreshSecret.getExpiration()).isGreaterThan(expiration); - - - } - -} diff --git a/src/test/java/io/kidsfirst/keys/KeyStoreTests.java b/src/test/java/io/kidsfirst/keys/KeyStoreTests.java deleted file mode 100644 index 7c586bc..0000000 --- a/src/test/java/io/kidsfirst/keys/KeyStoreTests.java +++ /dev/null @@ -1,109 +0,0 @@ -package io.kidsfirst.keys; - -import io.kidsfirst.core.model.Secret; -import lombok.extern.slf4j.Slf4j; -import lombok.val; -import net.minidev.json.JSONObject; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; - -import java.util.concurrent.ExecutionException; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -@Slf4j -public class KeyStoreTests extends AbstractTest { - - private final String keyStoreUri = "/key-store"; - protected static String defaultAccessToken = ""; - @BeforeAll - static void initTest(){ - val userAndToken = createUserAndSecretAndObtainAccessToken("cavatica", "cavatica_secret"); - defaultAccessToken = userAndToken.getAccessToken(); - } - - @Test - void testKeyStorePreflight() { - webClient.options() - .uri(keyStoreUri) - .exchange() - .expectStatus().is2xxSuccessful() - .expectHeader() - - .value("Allow", matchValues("PUT", "DELETE", "GET", "HEAD", "OPTIONS")); - - - } - - @Test - void testKeyStoreGETContentTypeDifferentThanTextPlain() { - webClient.get() - .uri(keyStoreUri) - .accept(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + defaultAccessToken) - .exchange() - .expectStatus().isEqualTo(406) - .expectHeader(); - - } - - @Test - void testKeyStoreGET() { - val body = webClient.get() - .uri(uriBuilder -> uriBuilder - .path(keyStoreUri) - .queryParam("service", "cavatica") - .build()) - .accept(MediaType.TEXT_PLAIN) - .header("Authorization", "Bearer " + defaultAccessToken) - .exchange() - .expectStatus().isOk() - .expectBody().returnResult().getResponseBody(); - assert body != null; - assertThat(new String(body)).isEqualTo("cavatica_secret"); - } - - @Test - void testKeyStoreDELETE() throws ExecutionException, InterruptedException { - val userIdAndToken = createUserAndSecretAndObtainAccessToken("cavatica", "my_secret"); - JSONObject body = new JSONObject(); - body.put("service", "cavatica"); - webClient - .method(HttpMethod.DELETE) - .uri(keyStoreUri) - .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + userIdAndToken.getAccessToken()) - .bodyValue(body.toJSONString()) - .exchange() - .expectStatus().isOk(); - val secret = secretTable.getItem(new Secret(userIdAndToken.getUserId(), "cavatica", null, null)).get(); - assertThat(secret).isNull(); - } - - @Test - void testKeyStorePUT() throws Exception { - String my_secret = "my_secret"; - JSONObject body = new JSONObject(); - body.put("service", "cavatica"); - body.put("secret", my_secret); - val userIdAndToken = createUserAndSecretAndObtainAccessToken("cavatica", my_secret); - webClient - .put() - .uri(keyStoreUri) - .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + userIdAndToken.getAccessToken()) - .bodyValue(body.toJSONString()) - .exchange() - .expectStatus().isOk() - .expectBody(); - - val secret = secretTable.getItem(new Secret(userIdAndToken.getUserId(), "cavatica", null, null)).get(); - assertThat(secret).isNotNull(); - assertThat(secret.getSecret()).isEqualTo("encrypted_" + my_secret); - } - -}