Skip to content

Commit

Permalink
[quarkus2] Added tests for token propagation (#436)
Browse files Browse the repository at this point in the history
* Added tests for token propagation (#433)

* Added tests for token propagation

Signed-off-by: Helber Belmiro <[email protected]>

---------

Signed-off-by: Helber Belmiro <[email protected]>

* Replaced jakarta with javax

---------

Signed-off-by: Helber Belmiro <[email protected]>
Co-authored-by: Helber Belmiro <[email protected]>
  • Loading branch information
github-actions[bot] and hbelmiro authored Aug 11, 2023
1 parent e461b08 commit 60d6605
Show file tree
Hide file tree
Showing 11 changed files with 424 additions and 0 deletions.
5 changes: 5 additions & 0 deletions integration-tests/security/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@
<artifactId>wiremock-jre8</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package io.quarkiverse.openapi.generator.it.security;

import javax.ws.rs.POST;
import javax.ws.rs.Path;

import org.eclipse.microprofile.rest.client.inject.RestClient;

@Path("/token_propagation")
public class TokenPropagationResource {

@RestClient
org.acme.externalservice1.api.DefaultApi defaultApi1;

@RestClient
org.acme.externalservice2.api.DefaultApi defaultApi2;

@RestClient
org.acme.externalservice3.api.DefaultApi defaultApi3;

@RestClient
org.acme.externalservice4.api.DefaultApi defaultApi4;

@RestClient
org.acme.externalservice5.api.DefaultApi defaultApi5;

@POST
@Path("service1")
public String service1() {
defaultApi1.executeQuery1();
return "hello";
}

@POST
@Path("service2")
public String service2() {
defaultApi2.executeQuery2();
return "hello";
}

@POST
@Path("service3")
public String service3() {
defaultApi3.executeQuery3();
return "hello";
}

@POST
@Path("service4")
public String service4() {
defaultApi4.executeQuery4();
return "hello";
}

@POST
@Path("service5")
public String service5() {
defaultApi5.executeQuery5();
return "hello";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
openapi: 3.0.3
info:
title: token-propagation-external-service1 API
version: 2.0.0-SNAPSHOT
paths:
/token-propagation-external-service1/executeQuery1:
post:
operationId: executeQuery1
responses:
"200":
description: OK
security:
- service1-http-bearer: []
components:
securitySchemes:
service1-http-bearer:
type: http
scheme: bearer
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
openapi: 3.0.3
info:
title: external-service2 API
version: 2.0.0-SNAPSHOT
paths:
/token-propagation-external-service2/executeQuery2:
post:
operationId: executeQuery2
responses:
"200":
description: OK
security:
- service2-oauth2: []
components:
securitySchemes:
service2-oauth2:
type: oauth2
flows:
clientCredentials:
authorizationUrl: https://example.com/oauth
tokenUrl: https://example.com/oauth/token
scopes: {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
openapi: 3.0.3
info:
title: token-propagation-external-service3 API
version: 2.0.0-SNAPSHOT
paths:
/token-propagation-external-service3/executeQuery3:
post:
operationId: executeQuery3
responses:
"200":
description: OK
security:
- service3-http-bearer: []
components:
securitySchemes:
service3-http-bearer:
type: http
scheme: bearer
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
openapi: 3.0.3
info:
title: external-service4 API
version: 2.0.0-SNAPSHOT
paths:
/token-propagation-external-service4/executeQuery4:
post:
operationId: executeQuery4
responses:
"200":
description: OK
security:
- service4-oauth2: []
components:
securitySchemes:
service4-oauth2:
type: oauth2
flows:
clientCredentials:
authorizationUrl: https://example.com/oauth
tokenUrl: https://example.com/oauth/token
scopes: {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
openapi: 3.0.3
info:
title: external-service5 API
version: 2.0.0-SNAPSHOT
paths:
/token-propagation-external-service5/executeQuery5:
post:
operationId: executeQuery5
responses:
"200":
description: OK
security:
- service5-oauth2: []
components:
securitySchemes:
service5-oauth2:
type: oauth2
flows:
clientCredentials:
authorizationUrl: https://example.com/oauth
tokenUrl: https://example.com/oauth/token
scopes: {}
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,55 @@ quarkus.openapi-generator.open_weather_no_security_yaml.auth.app_id.api-key=1234
# KOGITO-6458 (https://issues.redhat.com/browse/KOGITO-6458) - generate auth bindings even if security definition is missing
# Note: The property value is the name of an existing securityScheme in the spec file
quarkus.openapi-generator.codegen.default.security.scheme=app_id

#Token propagation
quarkus.openapi-generator.codegen.spec.token_propagation_external_service1_yaml.base-package=org.acme.externalservice1
quarkus.openapi-generator.codegen.spec.token_propagation_external_service2_yaml.base-package=org.acme.externalservice2
quarkus.openapi-generator.codegen.spec.token_propagation_external_service3_yaml.base-package=org.acme.externalservice3
quarkus.openapi-generator.codegen.spec.token_propagation_external_service4_yaml.base-package=org.acme.externalservice4
quarkus.openapi-generator.codegen.spec.token_propagation_external_service5_yaml.base-package=org.acme.externalservice5

quarkus.rest-client.token_propagation_external_service1_yaml.url=${propagation-external-service-mock.url}
quarkus.rest-client.token_propagation_external_service2_yaml.url=${propagation-external-service-mock.url}
quarkus.rest-client.token_propagation_external_service3_yaml.url=${propagation-external-service-mock.url}
quarkus.rest-client.token_propagation_external_service4_yaml.url=${propagation-external-service-mock.url}
quarkus.rest-client.token_propagation_external_service5_yaml.url=${propagation-external-service-mock.url}

# default propagation for token_propagation_external_service1 invocation
quarkus.openapi-generator.token_propagation_external_service1_yaml.auth.service1_http_bearer.token-propagation=true
# default propagation for token_propagation_external_service2 invocation
quarkus.openapi-generator.token_propagation_external_service2_yaml.auth.service2_oauth2.token-propagation=true
# propagate the token coming in the header SERVICE3_HEADER_TO_PROPAGATE for token_propagation_external_service3 invocation
quarkus.openapi-generator.token_propagation_external_service3_yaml.auth.service3_http_bearer.token-propagation=true
quarkus.openapi-generator.token_propagation_external_service3_yaml.auth.service3_http_bearer.header-name=SERVICE3_HEADER_TO_PROPAGATE
# propagate the token coming in the header SERVICE4_HEADER_TO_PROPAGATE for token_propagation_external_service4 invocation
quarkus.openapi-generator.token_propagation_external_service4_yaml.auth.service4_oauth2.token-propagation=true
quarkus.openapi-generator.token_propagation_external_service4_yaml.auth.service4_oauth2.header-name=SERVICE4_HEADER_TO_PROPAGATE

# Oidc clients for the services that has oauth2 security.
# Oidc client used by the token_propagation_external_service2
quarkus.oidc-client.service2_oauth2.auth-server-url=${keycloak.mock.service.url}
quarkus.oidc-client.service2_oauth2.token-path=${keycloak.mock.service.token-path}
quarkus.oidc-client.service2_oauth2.discovery-enabled=false
quarkus.oidc-client.service2_oauth2.client-id=kogito-app
quarkus.oidc-client.service2_oauth2.grant.type=client
quarkus.oidc-client.service2_oauth2.credentials.client-secret.method=basic
quarkus.oidc-client.service2_oauth2.credentials.client-secret.value=secret

# Oidc client used by the token_propagation_external_service4
quarkus.oidc-client.service4_oauth2.auth-server-url=${keycloak.mock.service.url}
quarkus.oidc-client.service4_oauth2.token-path=${keycloak.mock.service.token-path}
quarkus.oidc-client.service4_oauth2.discovery-enabled=false
quarkus.oidc-client.service4_oauth2.client-id=kogito-app
quarkus.oidc-client.service4_oauth2.grant.type=client
quarkus.oidc-client.service4_oauth2.credentials.client-secret.method=basic
quarkus.oidc-client.service4_oauth2.credentials.client-secret.value=secret

# Oidc client used by the token_propagation_external_service5
quarkus.oidc-client.service5_oauth2.auth-server-url=${keycloak.mock.service.url}
quarkus.oidc-client.service5_oauth2.token-path=${keycloak.mock.service.token-path}
quarkus.oidc-client.service5_oauth2.discovery-enabled=false
quarkus.oidc-client.service5_oauth2.client-id=kogito-app
quarkus.oidc-client.service5_oauth2.grant.type=client
quarkus.oidc-client.service5_oauth2.credentials.client-secret.method=basic
quarkus.oidc-client.service5_oauth2.credentials.client-secret.value=secret
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package io.quarkiverse.openapi.generator.it.security;

import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.configureFor;
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
import static com.github.tomakehurst.wiremock.client.WireMock.post;
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE;
import static javax.ws.rs.core.MediaType.APPLICATION_FORM_URLENCODED;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;

import java.util.HashMap;
import java.util.Map;

import com.github.tomakehurst.wiremock.WireMockServer;

import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;

/**
* Lightweight Keycloak mock to use when an OidcClient is required, and we don't want/need to start a full Keycloak
* container as part of the tests, etc. Keep the things simple.
*/
public class KeycloakServiceMock implements QuarkusTestResourceLifecycleManager {

public static final String KEY_CLOAK_SERVICE_URL = "keycloak.mock.service.url";
public static final String KEY_CLOAK_SERVICE_TOKEN_PATH = "keycloak.mock.service.token-path";
public static final String REALM = "kogito-tests";
public static final String KEY_CLOAK_SERVICE_TOKEN_PATH_VALUE = "/realms/" + REALM + "/protocol/openid-connect/token";
public static final String CLIENT_ID = "kogito-app";
public static final String SECRET = "secret";
public static final String KEYCLOAK_ACCESS_TOKEN = "KEYCLOAK_ACCESS_TOKEN";
public static final String KEYCLOAK_REFRESH_TOKEN = "KEYCLOAK_REFRESH_TOKEN";
public static final String KEYCLOAK_SESSION_STATE = "KEYCLOAK_SESSION_STATE";

public static final String AUTH_REQUEST_BODY = "grant_type=client_credentials";

private WireMockServer wireMockServer;

@Override
public Map<String, String> start() {
wireMockServer = new WireMockServer(options().dynamicPort());
wireMockServer.start();
configureFor(wireMockServer.port());

stubFor(post(KEY_CLOAK_SERVICE_TOKEN_PATH_VALUE)
.withHeader(CONTENT_TYPE, equalTo(APPLICATION_FORM_URLENCODED))
.withBasicAuth(CLIENT_ID, SECRET)
.withRequestBody(equalTo(AUTH_REQUEST_BODY))
.willReturn(aResponse()
.withHeader(CONTENT_TYPE, APPLICATION_JSON)
.withBody(getTokenResult())));

Map<String, String> properties = new HashMap<>();
properties.put(KEY_CLOAK_SERVICE_URL, wireMockServer.baseUrl());
properties.put(KEY_CLOAK_SERVICE_TOKEN_PATH, KEY_CLOAK_SERVICE_TOKEN_PATH_VALUE);
return properties;
}

private static String getTokenResult() {
return "{\n" +
" \"access_token\": \"" + KEYCLOAK_ACCESS_TOKEN + "\",\n" +
" \"expires_in\": 300,\n" +
" \"refresh_expires_in\": 1800,\n" +
" \"refresh_token\": \"" + KEYCLOAK_REFRESH_TOKEN + "\",\n" +
" \"token_type\": \"bearer\",\n" +
" \"not-before-policy\": 0,\n" +
" \"session_state\": \"" + KEYCLOAK_SESSION_STATE + "\",\n" +
" \"scope\": \"email profile\"\n" +
"}";
}

@Override
public void stop() {
if (wireMockServer != null) {
wireMockServer.stop();
}
}
}
Loading

0 comments on commit 60d6605

Please sign in to comment.