diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 68820a59c9524000cdc9aaca1c894d11f5836888..30825df0ed200a3dadd94dc2ecca2dfbaaee0a0f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -19,6 +19,8 @@ variables: IBM_HELM_CONFIG_PATH: devops/ibm/ibm-notification-config IBM_HELM_DEPLOY_PATH: devops/ibm/ibm-notification-deploy + ACCEPTANCE_TEST_DIR: "notification-acceptance-test" + include: - project: "osdu/platform/ci-cd-pipelines" file: "standard-setup.yml" diff --git a/NOTICE b/NOTICE index 308cfc73e2c28da781e67f8ee4d99a747ccb04c3..6ae25fd454ad7dffe4a8a0cb5f907eb2bc70bf73 100644 --- a/NOTICE +++ b/NOTICE @@ -102,7 +102,7 @@ The following software have components provided under the terms of this license: - Jackson-dataformat-YAML (from https://github.com/FasterXML/jackson, https://github.com/FasterXML/jackson-dataformats-text) - Jackson-module-parameter-names (from https://repo1.maven.org/maven2/com/fasterxml/jackson/module/jackson-module-parameter-names) - Jakarta Dependency Injection (from https://github.com/eclipse-ee4j/injection-api) -- Jakarta RESTful WS API (from https://github.com/eclipse-ee4j/jaxrs-api, https://maven.atlassian.com/3rdparty/jakarta/ws/rs/jakarta.ws.rs-api, https://repo1.maven.org/maven2/jakarta/ws/rs/jakarta.ws.rs-api) +- Jakarta RESTful WS API (from https://github.com/eclipse-ee4j/jaxrs-api, https://repo1.maven.org/maven2/jakarta/ws/rs/jakarta.ws.rs-api) - Jakarta Servlet (from https://projects.eclipse.org/projects/ee4j.servlet) - Jakarta Validation API (from https://beanvalidation.org) - Java Architecture for XML Binding (from http://jaxb.java.net/, https://repo1.maven.org/maven2/javax/xml/bind/jaxb-api) @@ -294,7 +294,7 @@ The following software have components provided under the terms of this license: - Jakarta Activation API (from https://github.com/eclipse-ee4j/jaf, https://github.com/jakartaee/jaf-api, https://repo1.maven.org/maven2/jakarta/activation/jakarta.activation-api) - Jakarta Annotations API (from https://projects.eclipse.org/projects/ee4j.ca) - Jakarta Messaging API (from https://projects.eclipse.org/projects/ee4j.jms) -- Jakarta RESTful WS API (from https://github.com/eclipse-ee4j/jaxrs-api, https://maven.atlassian.com/3rdparty/jakarta/ws/rs/jakarta.ws.rs-api, https://repo1.maven.org/maven2/jakarta/ws/rs/jakarta.ws.rs-api) +- Jakarta RESTful WS API (from https://github.com/eclipse-ee4j/jaxrs-api, https://repo1.maven.org/maven2/jakarta/ws/rs/jakarta.ws.rs-api) - Jakarta WebSocket - Client API (from https://projects.eclipse.org/projects/ee4j.websocket) - Jakarta WebSocket - Server API (from https://projects.eclipse.org/projects/ee4j.websocket, https://repo1.maven.org/maven2/org/jboss/spec/javax/websocket/jboss-websocket-api_1.1_spec) - Jakarta XML Binding API (from https://repo1.maven.org/maven2/jakarta/xml/bind/jakarta.xml.bind-api, https://repo1.maven.org/maven2/org/jboss/spec/javax/xml/bind/jboss-jaxb-api_2.3_spec) @@ -401,7 +401,7 @@ The following software have components provided under the terms of this license: - Jakarta Annotations API (from https://projects.eclipse.org/projects/ee4j.ca) - Jakarta Dependency Injection (from https://github.com/eclipse-ee4j/injection-api) - Jakarta Messaging API (from https://projects.eclipse.org/projects/ee4j.jms) -- Jakarta RESTful WS API (from https://github.com/eclipse-ee4j/jaxrs-api, https://maven.atlassian.com/3rdparty/jakarta/ws/rs/jakarta.ws.rs-api, https://repo1.maven.org/maven2/jakarta/ws/rs/jakarta.ws.rs-api) +- Jakarta RESTful WS API (from https://github.com/eclipse-ee4j/jaxrs-api, https://repo1.maven.org/maven2/jakarta/ws/rs/jakarta.ws.rs-api) - Jakarta Servlet (from https://projects.eclipse.org/projects/ee4j.servlet) - Jakarta Validation API (from https://beanvalidation.org) - Jakarta WebSocket - Client API (from https://projects.eclipse.org/projects/ee4j.websocket) @@ -419,7 +419,7 @@ The following software have components provided under the terms of this license: - Jakarta Annotations API (from https://projects.eclipse.org/projects/ee4j.ca) - Jakarta Dependency Injection (from https://github.com/eclipse-ee4j/injection-api) - Jakarta Messaging API (from https://projects.eclipse.org/projects/ee4j.jms) -- Jakarta RESTful WS API (from https://github.com/eclipse-ee4j/jaxrs-api, https://maven.atlassian.com/3rdparty/jakarta/ws/rs/jakarta.ws.rs-api, https://repo1.maven.org/maven2/jakarta/ws/rs/jakarta.ws.rs-api) +- Jakarta RESTful WS API (from https://github.com/eclipse-ee4j/jaxrs-api, https://repo1.maven.org/maven2/jakarta/ws/rs/jakarta.ws.rs-api) - Jakarta Servlet (from https://projects.eclipse.org/projects/ee4j.servlet) - Jakarta Validation API (from https://beanvalidation.org) - Jakarta WebSocket - Client API (from https://projects.eclipse.org/projects/ee4j.websocket) @@ -551,7 +551,7 @@ efsl-1.0 ======================================================================== The following software have components provided under the terms of this license: -- Jakarta RESTful WS API (from https://github.com/eclipse-ee4j/jaxrs-api, https://maven.atlassian.com/3rdparty/jakarta/ws/rs/jakarta.ws.rs-api, https://repo1.maven.org/maven2/jakarta/ws/rs/jakarta.ws.rs-api) +- Jakarta RESTful WS API (from https://github.com/eclipse-ee4j/jaxrs-api, https://repo1.maven.org/maven2/jakarta/ws/rs/jakarta.ws.rs-api) ======================================================================== gpl-2.0-classpath diff --git a/devops/core-plus/pipeline/override-stages.yml b/devops/core-plus/pipeline/override-stages.yml index 1a0a49ee0ac87ce15d4815e1ae552ee8f0726c61..689963d128961fd94630b243a9095f0804994c88 100644 --- a/devops/core-plus/pipeline/override-stages.yml +++ b/devops/core-plus/pipeline/override-stages.yml @@ -1,5 +1,6 @@ variables: CORE_SERVICE: notification + GSA_TEST_ENABLED: "true" core-test: variables: diff --git a/notification-acceptance-test/docs/README.md b/notification-acceptance-test/docs/README.md new file mode 100644 index 0000000000000000000000000000000000000000..b685bab86318b894fac3a938131ad7b50260a0c3 --- /dev/null +++ b/notification-acceptance-test/docs/README.md @@ -0,0 +1,75 @@ +### Running E2E Tests + +You will need to have the following environment variables defined. + +| name | value | description | sensitive? | source | +|---------------------------------|------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|------------|--------| +| `CLIENT_TENANT` | eg. `osdu` | Client tenant used for testing | no | - | +| `OSDU_TENANT` | eg. `osdu` | OSDU tenant used for testing | no | - | +| `GROUP_ID` | eg. `group` | Group ID used for testing. Group id, used in storage record ACL. Full group will be "data.default.viewers@{{data-partition-id}}.{{group_id}}" | no | - | +| `TOPIC_ID` | eg. `records-changed` | Topic ID | no | - | +| `HMAC_SECRET` | eg. `123456789` | String in hex , must match pattern ^[a-zA-Z0-9]{8,30}+$ & be in register variable SUBSCRIBER_SECRET | yes | - | +| `NOTIFICATION_BASE_URL` | eg. `https://osdu.core-dev.gcp.gnrg-osdu.projects.epam.com/api/notification/v1/` | Endpoint of notification service | no | - | +| `REGISTER_BASE_URL` | eg. `https://osdu.core-dev.gcp.gnrg-osdu.projects.epam.com/api/register/v1` | Endpoint of register service | no | - | +| `REGISTER_CUSTOM_PUSH_URL_HMAC` | eg. `https://osdu.core-dev.gcp.gnrg-osdu.projects.epam.com/api/register/v1/test/challenge/hmac-integration-test` | Endpoint of register custom push URL HMAC | no | - | +| `LEGAL_HOST` | eg. `https://osdu.core-dev.gcp.gnrg-osdu.projects.epam.com/api/legal/v1` | Endpoint of legal service | no | - | +| `STORAGE_HOST` | eg. `https://osdu.core-dev.gcp.gnrg-osdu.projects.epam.com/api/storage/v2` | Endpoint of storage service | no | - | +| `GSA_TEST_ENABLED` | eg. `true` or `false` | Enabler for GSA tests | no | - | +Authentication can be provided as OIDC config: + +| name | value | description | sensitive? | source | +|------------------------------------------------|-----------------------------------------|-------------------------------------------------------|------------|--------| +| `TEST_DE_ADMIN_OPENID_PROVIDER_CLIENT_ID` | `********` | Service account client id which has admins api access | yes | - | +| `TEST_DE_ADMIN_OPENID_PROVIDER_CLIENT_SECRET` | `********` | Service account secret which has admins api access | yes | - | +| `TEST_DE_EDITOR_OPENID_PROVIDER_CLIENT_ID` | `********` | Service account client id which has editor api access | yes | - | +| `TEST_DE_EDITOR_OPENID_PROVIDER_CLIENT_SECRET` | `********` | Service account secret which has editor api access | yes | - | +| `TEST_DE_OPS_OPENID_PROVIDER_CLIENT_ID` | `********` | Service account client id which has full api access | yes | - | +| `TEST_DE_OPS_OPENID_PROVIDER_CLIENT_SECRET` | `********` | Service account secret which has full api access | yes | - | +| `TEST_NO_ACCESS_OPENID_PROVIDER_CLIENT_ID` | `********` | Service account client id which has not api access | yes | - | +| `TEST_NO_ACCESS_OPENID_PROVIDER_CLIENT_SECRET` | `********` | Service account secret which has not api access | yes | - | +| `TEST_OPENID_PROVIDER_URL` | `https://keycloak.com/auth/realms/osdu` | OpenID provider url | yes | - | + +Or tokens can be used directly from env variables: + +| name | value | description | sensitive? | source | +|------------------------|------------|----------------------|------------|--------| +| `DE_ADMIN_USER_TOKEN` | `********` | DE_ADMIN_USER Token | yes | - | +| `DE_EDITOR_USER_TOKEN` | `********` | DE_EDITOR_USER Token | yes | - | +| `DE_OPS_USER_TOKEN` | `********` | DE_OPS_USER Token | yes | - | +| `NO_ACCESS_USER_TOKEN` | `********` | NO_ACCESS_USER Token | yes | - | + +**Entitlements configuration for integration accounts** + +| DE_OPS_TESTER | DE_ADMIN_TESTER | DE_EDITOR_TESTER | DE_NO_ACCESS_TESTER | +|-----------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------|---------------------------------------------------------------------|------------------------------------------| +| notification.pubsub<br/>service.entitlements.user<br/>users<br/>users.datalake.ops</br> | service.entitlements.user<br/>users<br/>users.datalake.admins</br>service.legal.admin | service.entitlements.user<br/>users<br/>users.datalake.editors</br> | service.entitlements.user<br/>users<br/> | + +Above variables should be configured in the release pipeline to run integration tests. You should also replace them with proper values if you wish to run tests locally. + +### Commands to run tests +Execute following command to build code and run all the integration tests: + + ```bash + # Note: this assumes that the environment variables for acceptance tests as outlined + # above are already exported in your environment. + # build + install integration test core + $ (cd notification-acceptance-test && mvn clean verify) + ``` + +## License + +Copyright © Google LLC + +Copyright © EPAM Systems + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +[http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/notification-acceptance-test/pom.xml b/notification-acceptance-test/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..bd3ee4ff18ac245e10da466da35e0fdea4903072 --- /dev/null +++ b/notification-acceptance-test/pom.xml @@ -0,0 +1,187 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ Copyright 2017-2020, Schlumberger + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.opengroup.osdu.notification</groupId> + <artifactId>notification-acceptance-test</artifactId> + <version>0.28.0-SNAPSHOT</version> + <name>notification-acceptance-test</name> + + <parent> + <groupId>org.opengroup.osdu</groupId> + <artifactId>os-notification</artifactId> + <version>0.28.0-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <properties> + <java.version>17</java.version> + <maven.compiler.target>${java.version}</maven.compiler.target> + <maven.compiler.source>${java.version}</maven.compiler.source> + <jackson-databind.version>2.15.2</jackson-databind.version> + <jackson.version>2.15.2</jackson.version> + </properties> + + <dependencies> + <dependency> + <groupId>org.opengroup.osdu</groupId> + <artifactId>os-core-common</artifactId> + <version>0.25.0-rc2</version> + </dependency> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>1.18.26</version> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <version>5.10.4</version> + </dependency> + <dependency> + <groupId>org.junit.platform</groupId> + <artifactId>junit-platform-console</artifactId> + <version>1.10.4</version> + </dependency> + <dependency> + <groupId>com.nimbusds</groupId> + <artifactId>oauth2-oidc-sdk</artifactId> + <version>9.15</version> + </dependency> + <dependency> + <groupId>jakarta.xml.bind</groupId> + <artifactId>jakarta.xml.bind-api</artifactId> + <version>4.0.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.sun.xml.bind</groupId> + <artifactId>jaxb-core</artifactId> + <version>4.0.0</version> + </dependency> + <dependency> + <groupId>com.sun.xml.bind</groupId> + <artifactId>jaxb-impl</artifactId> + <version>4.0.0</version> + </dependency> + <dependency> + <groupId>org.opengroup.osdu</groupId> + <artifactId>os-core-common</artifactId> + <version>0.25.0-rc2</version> + <exclusions> + <exclusion> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-logging</artifactId> + </exclusion> + <exclusion> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-api</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>javax.json</groupId> + <artifactId>javax.json-api</artifactId> + <version>1.1.4</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-core</artifactId> + <version>${jackson.version}</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <version>${jackson-databind.version}</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-annotations</artifactId> + <version>${jackson.version}</version> + </dependency> + <dependency> + <groupId>org.glassfish</groupId> + <artifactId>javax.json</artifactId> + <version>1.1.4</version> + </dependency> + <dependency> + <groupId>com.google.oauth-client</groupId> + <artifactId>google-oauth-client</artifactId> + <version>1.34.1</version> + </dependency> + <dependency> + <groupId>com.google.api-client</groupId> + <artifactId>google-api-client</artifactId> + <version>2.2.0</version> + <exclusions> + <exclusion> + <groupId>com.google.guava</groupId> + <artifactId>guava-jdk5</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>com.sun.jersey</groupId> + <artifactId>jersey-client</artifactId> + <version>1.19.4</version> + </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>2.10.1</version> + </dependency> + <dependency> + <groupId>com.google.auth</groupId> + <artifactId>google-auth-library-oauth2-http</artifactId> + <version>0.19.0</version> + </dependency> + <dependency> + <groupId>io.jsonwebtoken</groupId> + <artifactId>jjwt</artifactId> + <version>0.9.1</version> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + <version>3.13.0</version> + </dependency> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>1.18.22</version> + <scope>compile</scope> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>3.0.0</version> + <configuration> + <systemPropertyVariables> + <DE_OPS_TESTER>${DE_OPS_TESTER}</DE_OPS_TESTER> + <DE_ADMIN_TESTER>${DE_ADMIN_TESTER}</DE_ADMIN_TESTER> + <DE_EDITOR_TESTER>${DE_EDITOR_TESTER}</DE_EDITOR_TESTER> + <DE_NO_ACCESS_TESTER>${DE_NO_ACCESS_TESTER}</DE_NO_ACCESS_TESTER> + </systemPropertyVariables> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/api/PubsubEndpointGSADescriptor.java b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/api/PubsubEndpointGSADescriptor.java new file mode 100644 index 0000000000000000000000000000000000000000..476c1b684115c2bbf9bfc5706b10fbc4fc2d4e43 --- /dev/null +++ b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/api/PubsubEndpointGSADescriptor.java @@ -0,0 +1,64 @@ +/* + * Copyright 2017-2020, Schlumberger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.opengroup.osdu.notification.api; + +import org.opengroup.osdu.notification.util.Config; +import org.opengroup.osdu.notification.util.RestDescriptor; +import org.opengroup.osdu.notification.util.TestUtils; + +import java.util.HashMap; +import java.util.Map; + +public class PubsubEndpointGSADescriptor extends RestDescriptor { + + @Override + public String getPath() { + return "push-handlers/records-changed"; + } + + @Override + public String getHttpMethod() { + return "POST"; + } + + @Override + public String getValidBody() { + return "{\n" + + "\t\"message\": {\n" + + "\t\"attributes\": {\n" + + "\t\"correlation-id\": \"39137f49-67d6-4001-a6aa-15521ef4f49e\",\n" + + "\t\"data-partition-id\": \"" + TestUtils.getOsduTenant() + "\"},\n" + + "\t\"data\": \"W3sia2luZCI6InRlc3RraW5kIiwiaWQiOiJ0ZXN0aWQiLCJvcGVyYXRpb250eXBlIjoiY3JlYXRlIn0seyJraW5kIjoidGVzdGtpbmQyIiwiaWQiOiJ0ZXN0aWQyIiwib3BlcmF0aW9udHlwZSI6InVwZGF0ZSJ9XQ\",\n" + + "\t\"messageId\": \"136969346945\"},\n" + + "\t\"subscription\":\"" + Config.Instance().NotificationId + "\"\n" + + "}"; + } + + @Override + public Map<String,String> getOsduTenantHeaders(){ + Map<String, String> headers = new HashMap<>(); + headers.put("data-partition-id", Config.Instance().OsduTenant); + return headers; + } + + @Override + public Map<String,String> getCustomerTenantHeaders(){ + Map<String, String> headers = new HashMap<>(); + headers.put("data-partition-id", Config.Instance().ClientTenant); + return headers; + } +} diff --git a/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/api/PubsubEndpointHMACDescriptor.java b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/api/PubsubEndpointHMACDescriptor.java new file mode 100644 index 0000000000000000000000000000000000000000..60791c283f2088c22626c67c1d79951e2272fa7e --- /dev/null +++ b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/api/PubsubEndpointHMACDescriptor.java @@ -0,0 +1,66 @@ +/* + * Copyright 2017-2020, Schlumberger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.opengroup.osdu.notification.api; + +import org.opengroup.osdu.notification.util.Config; +import org.opengroup.osdu.notification.util.RestDescriptor; +import org.opengroup.osdu.notification.util.TestUtils; + +import java.util.HashMap; +import java.util.Map; + +public class PubsubEndpointHMACDescriptor extends RestDescriptor { + + @Override + public String getPath() { + return "push-handlers/records-changed"; + } + + @Override + public String getHttpMethod() { + return "POST"; + } + + @Override + public String getValidBody() { + return "{\n" + + "\t\"message\": {\n" + + "\t\"attributes\": {\n" + + "\t\"correlation-id\": \"39137f49-67d6-4001-a6aa-15521ef4f49e\",\n" + + "\t\"data-partition-id\": \"" + TestUtils.getOsduTenant() + "\"\n" + + "\t},\n" + + "\t\"data\": \"W3sia2luZCI6InRlc3RraW5kIiwiaWQiOiJ0ZXN0aWQiLCJvcGVyYXRpb250eXBlIjoiY3JlYXRlIn0seyJraW5kIjoidGVzdGtpbmQyIiwiaWQiOiJ0ZXN0aWQyIiwib3BlcmF0aW9udHlwZSI6InVwZGF0ZSJ9XQ\",\n" + + "\t\"messageId\": \"136969346945\"\n" + + "\t},\n" + + "\t\"subscription\": \""+ arg() +"\"\n" + + "}\n"; + } + + @Override + public Map<String,String> getOsduTenantHeaders(){ + Map<String, String> headers = new HashMap<>(); + headers.put("data-partition-id", Config.Instance().OsduTenant); + return headers; + } + + @Override + public Map<String,String> getCustomerTenantHeaders(){ + Map<String, String> headers = new HashMap<>(); + headers.put("data-partition-id", Config.Instance().ClientTenant); + return headers; + } +} diff --git a/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/api/TestPushEndpointGsa.java b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/api/TestPushEndpointGsa.java new file mode 100644 index 0000000000000000000000000000000000000000..bfd04c2be94c4b6e26ab890427be0ff6ecfd0244 --- /dev/null +++ b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/api/TestPushEndpointGsa.java @@ -0,0 +1,171 @@ +/* + * Copyright 2020-2023 Google LLC + * Copyright 2020-2023 EPAM Systems, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.opengroup.osdu.notification.api; + + +import static org.junit.jupiter.api.Assumptions.assumeTrue; +import static org.opengroup.osdu.notification.util.Constants.GROUP_ID; + +import com.google.common.base.Strings; +import com.sun.jersey.api.client.ClientResponse; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.function.Predicate; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.opengroup.osdu.core.common.model.http.DpsHeaders; +import org.opengroup.osdu.core.common.model.notification.GsaSecret; +import org.opengroup.osdu.core.common.model.notification.GsaSecretValue; +import org.opengroup.osdu.core.common.model.notification.Secret; +import org.opengroup.osdu.core.common.model.notification.Subscription; +import org.opengroup.osdu.core.common.notification.ISubscriptionService; +import org.opengroup.osdu.core.common.notification.SubscriptionAPIConfig; +import org.opengroup.osdu.core.common.notification.SubscriptionException; +import org.opengroup.osdu.core.common.notification.SubscriptionFactory; +import org.opengroup.osdu.notification.util.*; + +public class TestPushEndpointGsa{ + public static final String REGISTER_BASE_URL = "REGISTER_BASE_URL"; + public static final String TOPIC_ID = "TOPIC_ID"; + public static final String INTEGRATION_AUDIENCE = "INTEGRATION_AUDIENCE"; + public static final String OSDU_TENANT = "OSDU_TENANT"; + public static final String STORAGE_HOST = "STORAGE_HOST"; + public static final String LEGAL_HOST = "LEGAL_HOST"; + public static final String DE_OPS_TESTER = "DE_OPS_TESTER"; + private final static Predicate<String> contentAcceptanceTester = s -> s.trim().startsWith("{"); + private String subscriptionId = null; + private String notificationId = null; + private static ISubscriptionService subscriptionService; + private static SubscriptionFactory factory; + private TestUtils testUtils = new TokenTestUtils(); + private final String suffix = String.valueOf(System.currentTimeMillis()); + private String baseRegisterUrl; + private String topic; + private String tenant; + private String integrationAudience; + private String storageHost; + private String legalHost; + private String groupId; + private static final String LEGAL_TAG_NAME = "notification-test-gsa"; + private ServicesUtils servicesUtils; + + @BeforeAll + public static void classSetup() throws Exception { + // Check if GSA tests are enabled + assumeTrue(Config.Instance().GSATestIsEnabled); + } + + @AfterEach + public void deleteResource() throws Exception { + if (Objects.isNull(subscriptionService)) { + Map<String, String> headers = new HashMap<>(); + headers.put(DpsHeaders.DATA_PARTITION_ID, System.getProperty(OSDU_TENANT, System.getenv(OSDU_TENANT))); + headers.put(DpsHeaders.AUTHORIZATION, testUtils.getOpsToken()); + DpsHeaders dpsHeaders = DpsHeaders.createFromMap(headers); + subscriptionService = factory.create(dpsHeaders); + } + + subscriptionService.delete(subscriptionId); + servicesUtils.deleteStorageRecords(3, suffix); + servicesUtils.deleteLegalTag(LEGAL_TAG_NAME); + } + + @BeforeEach + public void createResource() throws Exception { + baseRegisterUrl = System.getProperty(REGISTER_BASE_URL, System.getenv(REGISTER_BASE_URL)); + topic = System.getProperty(TOPIC_ID, System.getenv(TOPIC_ID)); + integrationAudience = System.getProperty(INTEGRATION_AUDIENCE, System.getenv(INTEGRATION_AUDIENCE)); + tenant = System.getProperty(OSDU_TENANT, System.getenv(OSDU_TENANT)); + if (Strings.isNullOrEmpty(integrationAudience)) { + integrationAudience = tenant; + } + storageHost = System.getProperty(STORAGE_HOST, System.getenv(STORAGE_HOST)); + legalHost = System.getProperty(LEGAL_HOST, System.getenv(LEGAL_HOST)); + groupId = System.getProperty(GROUP_ID, System.getenv(GROUP_ID)); + servicesUtils = new ServicesUtils(storageHost, legalHost, testUtils, tenant, groupId); + servicesUtils.createLegalTag(LEGAL_TAG_NAME); + createResourceInPartition(tenant); + } + + @Test + public void testPushEndpoint() throws Exception { + servicesUtils.createStorageRecords(suffix, 3, LEGAL_TAG_NAME); + Thread.sleep(10000); + assertNotNull(subscriptionId); + assertNotNull(notificationId); + Map<String, String> headers = new HashMap<>(); + headers.put(DpsHeaders.DATA_PARTITION_ID, tenant); + ClientResponse clientResponse = testUtils.send(baseRegisterUrl, "/test-state/state", "GET", testUtils.getOpsToken(), null, "", + headers, false); + Map<String, Number> response = new HashMap<>(); + response = testUtils.getResult(clientResponse, 200, response.getClass()); + assertNotNull(response); + assertTrue(response.containsKey(suffix)); + assertTrue(response.get(suffix).longValue() >= 3); + } + + private void createResourceInPartition(String partitionId) throws Exception { + + SubscriptionAPIConfig config = SubscriptionAPIConfig.builder().rootUrl(baseRegisterUrl).build(); + factory = new SubscriptionFactory(config); + + Map<String, String> headers = new HashMap<>(); + headers.put(DpsHeaders.DATA_PARTITION_ID, partitionId); + headers.put(DpsHeaders.AUTHORIZATION, testUtils.getOpsToken()); + DpsHeaders dpsHeaders = DpsHeaders.createFromMap(headers); + subscriptionService = factory.create(dpsHeaders); + + Subscription subscription = new Subscription(); + subscription.setName("subscription-integration-test-gsa-" + suffix); + subscription.setDescription("subscription created for gsa integration test " + suffix); + subscription.setTopic(topic); + subscription.setPushEndpoint(getPushUrl()); + + Secret gsaSecret = new GsaSecret(); + GsaSecretValue gsaSecretValue = new GsaSecretValue(); + gsaSecretValue.setAudience(integrationAudience); + + String opsTester = new DecodedContentExtractor(System.getProperty(DE_OPS_TESTER, System.getenv(DE_OPS_TESTER)), + contentAcceptanceTester).getContent(); + + gsaSecretValue.setKey(opsTester); + gsaSecret.setSecretType("GSA"); + ((GsaSecret) gsaSecret).setValue(gsaSecretValue); + subscription.setSecret(gsaSecret); + try { + Subscription subscriptionCreated = subscriptionService.create(subscription); + notificationId = subscriptionCreated.getNotificationId(); + subscriptionId = subscriptionCreated.getId(); + } catch (SubscriptionException e) { + System.out.println("Subscription exception inner response : " + e.getHttpResponse()); + throw e; + } + } + + private String getPushUrl() { + return baseRegisterUrl + "/test-state/gsa-challenge/" + suffix; + } +} diff --git a/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/api/TestPushEndpointHMAC.java b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/api/TestPushEndpointHMAC.java new file mode 100644 index 0000000000000000000000000000000000000000..2bf0f37da6f5e5908ca4432960981461666545f8 --- /dev/null +++ b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/api/TestPushEndpointHMAC.java @@ -0,0 +1,141 @@ +/* + * Copyright 2020-2023 Google LLC + * Copyright 2020-2023 EPAM Systems, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.opengroup.osdu.notification.api; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.opengroup.osdu.notification.util.Constants.GROUP_ID; + +import com.sun.jersey.api.client.ClientResponse; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.opengroup.osdu.core.common.model.http.DpsHeaders; +import org.opengroup.osdu.core.common.model.notification.HmacSecret; +import org.opengroup.osdu.core.common.model.notification.Subscription; +import org.opengroup.osdu.core.common.notification.ISubscriptionService; +import org.opengroup.osdu.core.common.notification.SubscriptionAPIConfig; +import org.opengroup.osdu.core.common.notification.SubscriptionException; +import org.opengroup.osdu.core.common.notification.SubscriptionFactory; +import org.opengroup.osdu.notification.util.*; + +public class TestPushEndpointHMAC{ + public static final String REGISTER_BASE_URL = "REGISTER_BASE_URL"; + public static final String TOPIC_ID = "TOPIC_ID"; + public static final String HMAC_SECRET = "HMAC_SECRET"; + public static final String OSDU_TENANT = "OSDU_TENANT"; + public static final String STORAGE_HOST = "STORAGE_HOST"; + public static final String LEGAL_HOST = "LEGAL_HOST"; + private String subscriptionId = null; + private String notificationId = null; + private ISubscriptionService subscriptionService; + private static SubscriptionFactory factory; + private TestUtils testUtils = new TokenTestUtils(); + private final String suffix = String.valueOf(System.currentTimeMillis()); + private String baseRegisterUrl; + private String topic; + private String hmacSecretValue; + private String tenant; + private String storageHost; + private String legalHost; + private String groupId; + private static final String LEGAL_TAG_NAME = "notification-test-hmac"; + private ServicesUtils servicesUtils; + + @AfterEach + public void deleteResource() throws Exception { + if (Objects.isNull(subscriptionService)) { + Map<String, String> headers = new HashMap<>(); + headers.put(DpsHeaders.DATA_PARTITION_ID, System.getProperty(OSDU_TENANT, System.getenv(OSDU_TENANT))); + headers.put(DpsHeaders.AUTHORIZATION, testUtils.getOpsToken()); + DpsHeaders dpsHeaders = DpsHeaders.createFromMap(headers); + subscriptionService = factory.create(dpsHeaders); + } + + subscriptionService.delete(subscriptionId); + servicesUtils.deleteStorageRecords(3, suffix); + servicesUtils.deleteLegalTag(LEGAL_TAG_NAME); + } + + @BeforeEach + public void createResource() throws Exception { + baseRegisterUrl = System.getProperty(REGISTER_BASE_URL, System.getenv(REGISTER_BASE_URL)); + topic = System.getProperty(TOPIC_ID, System.getenv(TOPIC_ID)); + hmacSecretValue = System.getProperty(HMAC_SECRET, System.getenv(HMAC_SECRET)); + tenant = System.getProperty(OSDU_TENANT, System.getenv(OSDU_TENANT)); + storageHost = System.getProperty(STORAGE_HOST, System.getenv(STORAGE_HOST)); + legalHost = System.getProperty(LEGAL_HOST, System.getenv(LEGAL_HOST)); + groupId = System.getProperty(GROUP_ID, System.getenv(GROUP_ID)); + servicesUtils = new ServicesUtils(storageHost, legalHost, testUtils, tenant, groupId); + servicesUtils.createLegalTag(LEGAL_TAG_NAME); + createResourceInPartition(tenant); + } + + @Test + public void testPushEndpoint() throws Exception { + servicesUtils.createStorageRecords(suffix, 3, LEGAL_TAG_NAME); + Thread.sleep(10000); + assertNotNull(subscriptionId); + assertNotNull(notificationId); + Map<String, String> headers = new HashMap<>(); + headers.put(DpsHeaders.DATA_PARTITION_ID, tenant); + ClientResponse clientResponse = testUtils.send(baseRegisterUrl, "/test-state/state", "GET", testUtils.getOpsToken(), null, "", + headers, false); + Map<String, Number> response = new HashMap<>(); + response = testUtils.getResult(clientResponse, 200, response.getClass()); + assertNotNull(response); + assertTrue(response.containsKey(suffix)); + assertTrue(response.get(suffix).longValue() >= 3); + } + + private void createResourceInPartition(String partitionId) throws Exception { + + SubscriptionAPIConfig config = SubscriptionAPIConfig.builder().rootUrl(baseRegisterUrl).build(); + factory = new SubscriptionFactory(config); + + Map<String, String> headers = new HashMap<>(); + headers.put(DpsHeaders.DATA_PARTITION_ID, partitionId); + headers.put(DpsHeaders.AUTHORIZATION, testUtils.getOpsToken()); + DpsHeaders dpsHeaders = DpsHeaders.createFromMap(headers); + subscriptionService = factory.create(dpsHeaders); + + Subscription subscription = new Subscription(); + subscription.setName("subscription-integration-test-hmac-" + suffix); + subscription.setDescription("subscription created for hmac integration test " + suffix); + subscription.setTopic(topic); + subscription.setPushEndpoint(getPushUrl()); + HmacSecret secret = new HmacSecret(); + secret.setValue(hmacSecretValue); + + subscription.setSecret(secret); + try { + Subscription subscriptionCreated = subscriptionService.create(subscription); + notificationId = subscriptionCreated.getNotificationId(); + subscriptionId = subscriptionCreated.getId(); + } catch (SubscriptionException e) { + System.out.println("Subscription exception inner response : " + e.getHttpResponse()); + throw e; + } + } + private String getPushUrl() { + return baseRegisterUrl + "/test-state/challenge/" + suffix; + } +} diff --git a/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/config/OpenIDProviderConfig.java b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/config/OpenIDProviderConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..58994bd3e7f5f09d1ed8c7ccb604c3d33da70e99 --- /dev/null +++ b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/config/OpenIDProviderConfig.java @@ -0,0 +1,129 @@ +/* + Copyright 2002-2022 Google LLC + Copyright 2002-2022 EPAM Systems, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.opengroup.osdu.notification.config; + +import com.nimbusds.oauth2.sdk.http.HTTPRequest; +import com.nimbusds.oauth2.sdk.http.HTTPResponse; +import com.nimbusds.oauth2.sdk.id.Issuer; +import com.nimbusds.openid.connect.sdk.op.OIDCProviderConfigurationRequest; +import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class OpenIDProviderConfig { + + private String opsClientId; + private String opsClientSecret; + private String adminClientId; + private String adminClientSecret; + private String editorClientId; + private String editorClientSecret; + private String noAccessClientId; + private String noAccessClientSecret; + private String url; + private final String[] scopes = {"openid"}; + private static final OpenIDProviderConfig openIDProviderConfig = new OpenIDProviderConfig(); + private static OIDCProviderMetadata providerMetadata; + + public static OpenIDProviderConfig Instance() { + try { + openIDProviderConfig.opsClientId = System.getProperty("TEST_DE_OPS_OPENID_PROVIDER_CLIENT_ID", + System.getenv("TEST_DE_OPS_OPENID_PROVIDER_CLIENT_ID")); + openIDProviderConfig.opsClientSecret = System.getProperty( + "TEST_DE_OPS_OPENID_PROVIDER_CLIENT_SECRET", + System.getenv("TEST_DE_OPS_OPENID_PROVIDER_CLIENT_SECRET")); + + openIDProviderConfig.adminClientId = System.getProperty( + "TEST_DE_ADMIN_OPENID_PROVIDER_CLIENT_ID", + System.getenv("TEST_DE_ADMIN_OPENID_PROVIDER_CLIENT_ID")); + openIDProviderConfig.adminClientSecret = System.getProperty( + "TEST_DE_ADMIN_OPENID_PROVIDER_CLIENT_SECRET", + System.getenv("TEST_DE_ADMIN_OPENID_PROVIDER_CLIENT_SECRET")); + + openIDProviderConfig.editorClientId = System.getProperty( + "TEST_DE_EDITOR_OPENID_PROVIDER_CLIENT_ID", + System.getenv("TEST_DE_EDITOR_OPENID_PROVIDER_CLIENT_ID")); + openIDProviderConfig.editorClientSecret = System.getProperty( + "TEST_DE_EDITOR_OPENID_PROVIDER_CLIENT_SECRET", + System.getenv("TEST_DE_EDITOR_OPENID_PROVIDER_CLIENT_SECRET")); + + openIDProviderConfig.noAccessClientId = System.getProperty( + "TEST_NO_ACCESS_OPENID_PROVIDER_CLIENT_ID", + System.getenv("TEST_NO_ACCESS_OPENID_PROVIDER_CLIENT_ID")); + openIDProviderConfig.noAccessClientSecret = System.getProperty( + "TEST_NO_ACCESS_OPENID_PROVIDER_CLIENT_SECRET", + System.getenv("TEST_NO_ACCESS_OPENID_PROVIDER_CLIENT_SECRET")); + + openIDProviderConfig.url = + System.getProperty("TEST_OPENID_PROVIDER_URL", System.getenv("TEST_OPENID_PROVIDER_URL")); + Issuer issuer = new Issuer(openIDProviderConfig.url); + OIDCProviderConfigurationRequest request = new OIDCProviderConfigurationRequest(issuer); + HTTPRequest httpRequest = request.toHTTPRequest(); + HTTPResponse httpResponse = httpRequest.send(); + providerMetadata = OIDCProviderMetadata.parse(httpResponse.getContentAsJSONObject()); + } catch (Exception e) { + throw new RuntimeException("Malformed token provider configuration", e); + } + return openIDProviderConfig; + } + + public String getOpsClientId() { + return opsClientId; + } + + public String getOpsClientSecret() { + return opsClientSecret; + } + + public String getAdminClientId() { + return adminClientId; + } + + public String getAdminClientSecret() { + return adminClientSecret; + } + + public String getEditorClientId() { + return editorClientId; + } + + public String getEditorClientSecret() { + return editorClientSecret; + } + + public String getNoAccessClientId() { + return noAccessClientId; + } + + public String getNoAccessClientSecret() { + return noAccessClientSecret; + } + + public String getUrl() { + return url; + } + + public String[] getScopes() { + return scopes; + } + + public OIDCProviderMetadata getProviderMetadata() { + return providerMetadata; + } +} + diff --git a/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/Config.java b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/Config.java new file mode 100644 index 0000000000000000000000000000000000000000..5c3e0a02670b204b21c6ee0358840c0fe90003f6 --- /dev/null +++ b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/Config.java @@ -0,0 +1,95 @@ +/* + * Copyright 2017-2020, Schlumberger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.opengroup.osdu.notification.util; + +public class Config { + public String HostUrl; + public String OsduTenant; + public String ClientTenant; + public String IntegrationAudience; + public String GSAPushUrl; + public String HMACPushUrl; + public String RegisterServicePath; + public String StorageServicePath; + public String LegalServicePath; + public String Topic; + public String hmacSecretValue; + public String NotificationId; + public String DE_OPS_TESTER = System.getProperty("DE_OPS_TESTER", System.getenv("DE_OPS_TESTER")); + public String RetryCount; + public String TimeOutSeconds; + public Boolean GSATestIsEnabled; + private static Config config = new Config(); + + public static Config Instance() { + String env = getEnvironment(); + config.ClientTenant = getEnvironmentVariableOrDefaultValue("CLIENT_TENANT", "nonexistenttenant"); + config.IntegrationAudience = "osdu"; + config.OsduTenant = getEnvironmentVariableOrDefaultValue("OSDU_TENANT", "opendes"); + config.Topic = getEnvironmentVariableOrDefaultValue("TOPIC_ID", "records-changed"); + config.TimeOutSeconds = getEnvironmentVariableOrDefaultValue("TIME_OUT_SECONDS", "60"); + config.RetryCount = getEnvironmentVariableOrDefaultValue("RETRY_COUNT", "3"); + config.hmacSecretValue = System.getProperty("HMAC_SECRET", System.getenv("HMAC_SECRET")); + config.GSATestIsEnabled = Boolean.parseBoolean(getEnvironmentVariableOrDefaultValue("GSA_TEST_ENABLED", "false").trim().toLowerCase()); + + String registerUrl = System.getProperty("REGISTER_BASE_URL", System.getenv("REGISTER_BASE_URL")); + config.HostUrl = System.getProperty("NOTIFICATION_BASE_URL", System.getenv("NOTIFICATION_BASE_URL")); + config.GSAPushUrl = registerUrl + "/test/gsa-challenge/"; + //Adding this so CPs can point to custom HMAC push endpoints + config.HMACPushUrl = getEnvironmentVariableOrDefaultValue("REGISTER_CUSTOM_PUSH_URL_HMAC", registerUrl + "/test/challenge/"); + //Adding a new variable NOTIFICATION_REGISTER_BASE_URL since REGISTER_BASE_URL is used by Register integration tests which needs a trailing \ + String regUrl = getEnvironmentVariable("NOTIFICATION_REGISTER_BASE_URL"); + config.StorageServicePath = getEnvironmentVariable("STORAGE_HOST"); + config.LegalServicePath = System.getProperty("LEGAL_URL", System.getenv("LEGAL_URL")); + if (regUrl == null) { + config.RegisterServicePath = registerUrl; + } else { + config.RegisterServicePath = regUrl + "/api/register/v1"; + } + + System.out.println("HostUrl=" + config.HostUrl); + System.out.println("config.Topic=" + config.Topic); + System.out.println("config.HMACPushUrl=" + config.HMACPushUrl); + System.out.println("config.RegisterServicePath=" + config.RegisterServicePath); + System.out.println("config.StorageServicePath=" + config.StorageServicePath); + return config; + } + + public boolean isLocalHost() { + return HostUrl.contains("//localhost"); + } + + public static boolean isGke() { + return "DEV_GKE".equalsIgnoreCase(getEnvironment()); + } + + private static String getEnvironment() { + return System.getProperty("ENVIRONMENT", System.getenv("ENVIRONMENT")); + } + + private static String getEnvironmentVariableOrDefaultValue(String key, String defaultValue) { + String environmentVariable = getEnvironmentVariable(key); + if (environmentVariable == null) { + environmentVariable = defaultValue; + } + return environmentVariable; + } + + private static String getEnvironmentVariable(String propertyKey) { + return System.getProperty(propertyKey, System.getenv(propertyKey)); + } +} diff --git a/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/Constants.java b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/Constants.java new file mode 100644 index 0000000000000000000000000000000000000000..7889fab81ba31cbd3f5c840c2aca9d838c02aa21 --- /dev/null +++ b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/Constants.java @@ -0,0 +1,6 @@ +package org.opengroup.osdu.notification.util; + +public class Constants { + + public static final String GROUP_ID = "GROUP_ID"; +} diff --git a/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/DecodedContentExtractor.java b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/DecodedContentExtractor.java new file mode 100644 index 0000000000000000000000000000000000000000..106e582fb90cd7c4fc249de76600cd84653d795f --- /dev/null +++ b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/DecodedContentExtractor.java @@ -0,0 +1,126 @@ +/* + * Copyright 2020-2024 Google LLC + * Copyright 2020-2024 EPAM Systems, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.opengroup.osdu.notification.util; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.InvalidPathException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Base64; +import java.util.function.Predicate; +import lombok.RequiredArgsConstructor; +import lombok.extern.java.Log; + +@Log +@RequiredArgsConstructor +public class DecodedContentExtractor { + private final String inputFilenameOrContent; + private final Predicate<String> contentAcceptanceTester; + private boolean validOutputContentFound; + private String outputContent; + + public String getContent() { + + validOutputContentFound = false; + outputContent = null; + + log.info("Treat value as a content"); + if (inputFilenameOrContent.trim().isEmpty()) { + log.info("provided value is empty. Output as is."); + return setValidOutputContent(inputFilenameOrContent); + } + + if (!treatValueAsAContent(inputFilenameOrContent)) { + log.info("Value is not a valid content. Treat value as a filename"); + if (!treatValueAsAFileName(inputFilenameOrContent)){ + log.info("Value is not a filename with a valid content"); + } + + } + + return getValidOutputContentIfFound(); + } + + private boolean treatValueAsAContent(String input) { + if (contentAcceptanceTester.test(input)) { + log.info("the value is a valid content. Output as is."); + setValidOutputContent(input); + return true; + } + String output; + try { + output = new String(Base64.getDecoder().decode(input)); + log.info("the value is probably Base64 encoded. Just decoded"); + if (contentAcceptanceTester.test(output)) { + log.info("the decoded value is a valid content. Output decoded value."); + setValidOutputContent(output); + } else { + log.info("the decoded value is not a valid content."); + } + } catch (IllegalArgumentException e) { + log.info("the value is not Base64 encoded. "); + } + + return validOutputContentFound; + } + + private boolean treatValueAsAFileName(String filename) { + + if (treatFileContent(filename)) return true; + + try { + filename = new String(Base64.getDecoder().decode(filename)); + log.info("the filename is probably Base64 encoded. Just decoded"); + if (treatFileContent(filename)) return true; + } catch (IllegalArgumentException e) { + log.info("the filename is not Base64 encoded. "); + } + return validOutputContentFound; + } + + private boolean treatFileContent(String filename) { + try { + Path path = Paths.get(filename); + if (Files.exists(path)) { + log.info("the filename is of existing file. Read file."); + try { + String fileContent = new String(Files.readAllBytes(path)); + if (treatValueAsAContent(fileContent)) { + return true; + } + } catch (IOException | SecurityException | OutOfMemoryError ex) { + log.info(() -> ("unable to read the file: " + ex.getClass().getSimpleName())); + } + } + } catch (InvalidPathException ex) { + log.info("the filename is not valid or the file doesn't exist."); + } + return false; + } + + private String setValidOutputContent(String outputContent) { + this.outputContent = outputContent; + this.validOutputContentFound = true; + return getValidOutputContentIfFound(); + } + + public String getValidOutputContentIfFound() { + return validOutputContentFound ? outputContent : null; + } +} diff --git a/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/FileUtils.java b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/FileUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..e3af459967382cd0600f8f6a51a6a2135641cda8 --- /dev/null +++ b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/FileUtils.java @@ -0,0 +1,38 @@ +/* + * Copyright 2020-2023 Google LLC + * Copyright 2020-2023 EPAM Systems, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.opengroup.osdu.notification.util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +public class FileUtils { + public String readFromLocalFilePath(String filePath) throws IOException { + InputStream inStream = this.getClass().getResourceAsStream(filePath); + BufferedReader br = new BufferedReader(new InputStreamReader(inStream)); + StringBuilder stringBuilder = new StringBuilder(); + + String eachLine = ""; + while ((eachLine = br.readLine()) != null) { + stringBuilder.append(eachLine); + } + + return stringBuilder.toString(); + } +} diff --git a/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/HttpClient.java b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/HttpClient.java new file mode 100644 index 0000000000000000000000000000000000000000..1df1321be243b60b237a710b1d03523e67e25ca6 --- /dev/null +++ b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/HttpClient.java @@ -0,0 +1,108 @@ +/* + * Copyright 2020-2023 Google LLC + * Copyright 2020-2023 EPAM Systems, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.opengroup.osdu.notification.util; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.Gson; +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; +import java.net.URI; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.util.Map; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import javax.ws.rs.core.MediaType; +import org.apache.commons.lang3.StringUtils; + +public class HttpClient { + private HttpClient(){ + } + + public static ClientResponse send(String url, String path, String httpMethod, + Map<String, String> headers, + String requestBody, String query) throws Exception { + + String normalizedUrl = new URI(String.format("%s/%s", url, path)).normalize().toString(); + normalizedUrl = StringUtils.removeEnd(normalizedUrl, "/"); + log(httpMethod, normalizedUrl + query, headers, requestBody); + Client client = getClient(); + + WebResource webResource = client.resource(normalizedUrl + query); + WebResource.Builder builder = webResource.accept(MediaType.APPLICATION_JSON) + .type(MediaType.APPLICATION_JSON); + headers.forEach(builder::header); + + if ("POST".equals(httpMethod) && StringUtils.isEmpty(requestBody)) { + requestBody = "{}"; //solves 411 error when sending empty-body POST request + } + + return builder.method(httpMethod, ClientResponse.class, requestBody); + } + + private static void log(String method, String url, Map<String, String> headers, String body) { + System.out.println(String.format("%s: %s", method, url)); + System.out.println(body); + } + + @SuppressWarnings("unchecked") + public static <T> T getResult(ClientResponse response, int exepectedStatus, Class<T> classOfT) { + assertEquals(exepectedStatus, response.getStatus()); + if (exepectedStatus == 204) { + return null; + } + + assertEquals("application/json; charset=UTF-8", response.getType().toString()); + String json = response.getEntity(String.class); + if (classOfT == String.class) { + return (T) json; + } + + Gson gson = new Gson(); + return gson.fromJson(json, classOfT); + } + + protected static Client getClient() { + TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + @Override + public void checkClientTrusted(X509Certificate[] certs, String authType) { + } + + @Override + public void checkServerTrusted(X509Certificate[] certs, String authType) { + } + }}; + + try { + SSLContext sc = SSLContext.getInstance("TLS"); + sc.init(null, trustAllCerts, new SecureRandom()); + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + } catch (Exception e) { + } + return Client.create(); + } +} diff --git a/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/OpenIDTokenProvider.java b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/OpenIDTokenProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..0b5d220ae7616453c0033f1c5f3cb8cb2b0a4d59 --- /dev/null +++ b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/OpenIDTokenProvider.java @@ -0,0 +1,138 @@ +/* + Copyright 2002-2022 Google LLC + Copyright 2002-2022 EPAM Systems, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.opengroup.osdu.notification.util; + +import com.nimbusds.oauth2.sdk.AuthorizationGrant; +import com.nimbusds.oauth2.sdk.ClientCredentialsGrant; +import com.nimbusds.oauth2.sdk.ParseException; +import com.nimbusds.oauth2.sdk.Scope; +import com.nimbusds.oauth2.sdk.TokenRequest; +import com.nimbusds.oauth2.sdk.TokenResponse; +import com.nimbusds.oauth2.sdk.auth.ClientAuthentication; +import com.nimbusds.oauth2.sdk.auth.ClientSecretBasic; +import com.nimbusds.oauth2.sdk.auth.Secret; +import com.nimbusds.oauth2.sdk.id.ClientID; +import com.nimbusds.openid.connect.sdk.OIDCTokenResponseParser; +import java.io.IOException; +import java.net.URI; +import java.util.Objects; +import net.minidev.json.JSONObject; +import org.opengroup.osdu.notification.config.OpenIDProviderConfig; + +public class OpenIDTokenProvider { + + private static final OpenIDProviderConfig openIDProviderConfig = OpenIDProviderConfig.Instance(); + private static final String ID_TOKEN = "id_token"; + private final AuthorizationGrant clientGrant = new ClientCredentialsGrant(); + private final URI tokenEndpointURI; + private final Scope scope; + private final ClientAuthentication opsClientAuthentication; + private final ClientAuthentication adminClientAuthentication; + private final ClientAuthentication editorClientAuthentication; + private final ClientAuthentication noAccessClientAuthentication; + + public OpenIDTokenProvider() { + this.tokenEndpointURI = openIDProviderConfig.getProviderMetadata().getTokenEndpointURI(); + this.scope = new Scope(openIDProviderConfig.getScopes()); + this.opsClientAuthentication = + new ClientSecretBasic( + new ClientID(openIDProviderConfig.getOpsClientId()), + new Secret(openIDProviderConfig.getOpsClientSecret()) + ); + this.adminClientAuthentication = + new ClientSecretBasic( + new ClientID(openIDProviderConfig.getAdminClientId()), + new Secret(openIDProviderConfig.getAdminClientSecret()) + ); + this.editorClientAuthentication = + new ClientSecretBasic( + new ClientID(openIDProviderConfig.getEditorClientId()), + new Secret(openIDProviderConfig.getEditorClientSecret()) + ); + this.noAccessClientAuthentication = + new ClientSecretBasic( + new ClientID(openIDProviderConfig.getNoAccessClientId()), + new Secret(openIDProviderConfig.getNoAccessClientSecret()) + ); + } + + public String getOpsAccessToken() { + try { + TokenRequest request = + new TokenRequest(this.tokenEndpointURI, this.opsClientAuthentication, this.clientGrant, + this.scope); + return requestToken(request); + } catch (ParseException | IOException e) { + throw new RuntimeException( + "Unable get credentials from TEST_DE_OPS_OPENID_PROVIDER_CLIENT_ID variables", e); + } + } + + public String getAdminAccessToken() { + try { + TokenRequest request = + new TokenRequest(this.tokenEndpointURI, this.adminClientAuthentication, this.clientGrant, + this.scope); + return requestToken(request); + } catch (ParseException | IOException e) { + throw new RuntimeException( + "Unable get credentials from TEST_DE_ADMIN_OPENID_PROVIDER_CLIENT_ID variables", e); + } + } + + public String getEditorAccessToken() { + try { + TokenRequest request = + new TokenRequest(this.tokenEndpointURI, this.editorClientAuthentication, this.clientGrant, + this.scope); + return requestToken(request); + } catch (ParseException | IOException e) { + throw new RuntimeException( + "Unable get credentials from TEST_DE_EDITOR_OPENID_PROVIDER_CLIENT_ID variables", e); + } + } + + public String getNoAccessToken() { + try { + TokenRequest request = + new TokenRequest(this.tokenEndpointURI, this.noAccessClientAuthentication, + this.clientGrant, this.scope); + return requestToken(request); + } catch (ParseException | IOException e) { + throw new RuntimeException( + "Unable get credentials from TEST_NO_ACCESS_OPENID_PROVIDER_CLIENT_ID variables", e); + } + } + + private String requestToken(TokenRequest tokenRequest) throws ParseException, IOException { + + TokenResponse parse = OIDCTokenResponseParser.parse(tokenRequest.toHTTPRequest().send()); + + if (!parse.indicatesSuccess()) { + throw new RuntimeException("Unable get credentials variables"); + } + + JSONObject jsonObject = parse.toSuccessResponse().toJSONObject(); + String idTokenValue = jsonObject.getAsString(ID_TOKEN); + if (Objects.isNull(idTokenValue) || idTokenValue.isEmpty()) { + throw new RuntimeException("Unable get credentials variables"); + } + return idTokenValue; + } + +} diff --git a/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/RestDescriptor.java b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/RestDescriptor.java new file mode 100644 index 0000000000000000000000000000000000000000..08bab7e551b06c5f172aead358a159d99801257b --- /dev/null +++ b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/RestDescriptor.java @@ -0,0 +1,72 @@ +/* + * Copyright 2017-2020, Schlumberger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.opengroup.osdu.notification.util; + +import com.sun.jersey.api.client.ClientResponse; + +import java.util.Map; + +public abstract class RestDescriptor { + + public RestDescriptor() { + } + + private String arg = ""; + + public String arg() { + return arg; + } + + public abstract String getPath(); + + public abstract String getHttpMethod(); + + public abstract String getValidBody(); + + public abstract Map<String, String> getOsduTenantHeaders(); + + public abstract Map<String, String> getCustomerTenantHeaders(); + + public String getQuery() { + return ""; + } + + public ClientResponse runHttp(String arg, String token) throws Exception { + this.arg = arg; + return TestUtils.send(getPath(), getHttpMethod(), token, getValidBody(), getQuery(), getOsduTenantHeaders(), true); + } + + public ClientResponse run(String arg, String token) throws Exception { + this.arg = arg; + return TestUtils.send(getPath(), getHttpMethod(), token, getValidBody(), getQuery(), getOsduTenantHeaders(), false); + } + + public ClientResponse runOnCustomerTenant(String arg, String token) throws Exception { + this.arg = arg; + return TestUtils.send(getPath(), getHttpMethod(), token, getValidBody(), getQuery(), getCustomerTenantHeaders(), false); + } + + public ClientResponse runOptions(String arg, String token) throws Exception { + this.arg = arg; + return TestUtils.send(getPath(), "OPTIONS", token, "", "", getOsduTenantHeaders(), false); + } + + public ClientResponse run(String url, String arg, String token) throws Exception { + this.arg = arg; + return TestUtils.send(url, getPath(), getHttpMethod(), token, getValidBody(), getQuery(), getOsduTenantHeaders(), false); + } +} \ No newline at end of file diff --git a/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/ServicesUtils.java b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/ServicesUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..2eaf64b6c072230574047df9ce11c9aa1e450f26 --- /dev/null +++ b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/ServicesUtils.java @@ -0,0 +1,96 @@ +/* + * Copyright 2020-2023 Google LLC + * Copyright 2020-2023 EPAM Systems, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.opengroup.osdu.notification.util; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.sun.jersey.api.client.ClientResponse; +import java.util.HashMap; +import java.util.Map; +import org.opengroup.osdu.core.common.model.http.DpsHeaders; + +public class ServicesUtils { + private String storageHost; + private String legalHost; + private TestUtils testUtils; + private String partitionId; + private String groupId; + private FileUtils fileUtils; + + public ServicesUtils(String storageHost, String legalHost, TestUtils testUtils, String partitionId, String groupId) { + this.storageHost = storageHost; + this.legalHost = legalHost; + this.testUtils = testUtils; + this.partitionId = partitionId; + this.groupId = groupId; + this.fileUtils = new FileUtils(); + } + + public ClientResponse createLegalTag(String tagName) throws Exception { + String legalBody = fileUtils.readFromLocalFilePath("/LegalTag.json"); + legalBody = legalBody.replace("{{tagName}}", tagName); + Map<String, String> headers = new HashMap<>(); + headers.put(DpsHeaders.DATA_PARTITION_ID, partitionId); + headers.put(DpsHeaders.AUTHORIZATION, testUtils.getAdminToken()); + + ClientResponse legalResponse = HttpClient.send(legalHost, "legaltags", "POST", headers, legalBody, ""); + + boolean createdOrAlreadyExists = legalResponse.getStatus() == 201 || legalResponse.getStatus() == 409; + assertTrue(createdOrAlreadyExists); + return legalResponse; + } + + public void deleteLegalTag(String tagName) throws Exception{ + Map<String, String> headers = new HashMap<>(); + headers.put(DpsHeaders.DATA_PARTITION_ID, partitionId); + headers.put(DpsHeaders.AUTHORIZATION, testUtils.getAdminToken()); + ClientResponse legalResponse = HttpClient.send(legalHost, String.format("legaltags/%s", tagName), "DELETE", + headers, "", ""); + assertEquals(204, legalResponse.getStatus()); + } + + public void createStorageRecords(String suffix, int count, String legalTag) throws Exception{ + String body = fileUtils.readFromLocalFilePath("/StorageRecord.json"); + body = body.replace("{{data-partition-id}}", partitionId); + body = body.replace("{{legal-tag}}", partitionId + "-" + legalTag); + body = body.replace("{{group_id}}", groupId); + for (int i = 0; i < count; i++) { + String actualBody = body.replace("{{ids-suffix}}", suffix + String.valueOf(i)); + Map<String, String> headers = new HashMap<>(); + headers.put(DpsHeaders.DATA_PARTITION_ID, partitionId); + headers.put(DpsHeaders.AUTHORIZATION, testUtils.getAdminToken()); + ClientResponse storageResponse = HttpClient.send(storageHost, "records", "PUT", + headers, actualBody, ""); + assertEquals(201, storageResponse.getStatus()); + } + } + + public void deleteStorageRecords(int count, String suffix) throws Exception{ + for (int i = 0; i < count; i++) { + Map<String, String> headers = new HashMap<>(); + headers.put(DpsHeaders.DATA_PARTITION_ID, partitionId); + headers.put(DpsHeaders.AUTHORIZATION, testUtils.getAdminToken()); + String recordId = partitionId + ":dataset--ConnectedSource.Generic:notification-test-" + suffix + i; + ClientResponse storageResponse = HttpClient.send(storageHost, "records/" + recordId, "DELETE", + headers, "", ""); + assertEquals(204, storageResponse.getStatus()); + } + } + +} diff --git a/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/TestUtils.java b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/TestUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..ee4f21322ae7edff314b1e83a7d12af203f7be44 --- /dev/null +++ b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/TestUtils.java @@ -0,0 +1,229 @@ +/* + * Copyright 2017-2020, Schlumberger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.opengroup.osdu.notification.util; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import java.net.URL; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.util.*; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public abstract class TestUtils { + + protected String serviceAccountFile; + protected static String opsToken = null; + protected static String adminToken = null; + protected static String editorToken = null; + protected static String noAccessToken = null; + + public static String getApiPath(String api, boolean enforceHttp) throws Exception { + String baseUrl = Config.Instance().HostUrl; + if (enforceHttp) + baseUrl = baseUrl.replaceFirst("https", "http"); + URL mergedURL = new URL(baseUrl + api); + return mergedURL.toString(); + } + + public static String getApiPath(String baseUrl, String api, boolean enforceHttp) throws Exception { + if (enforceHttp) + baseUrl = baseUrl.replaceFirst("https", "http"); + URL mergedURL = new URL(baseUrl + api); + return mergedURL.toString(); + } + + public static String getOsduTenant() { + return Config.Instance().OsduTenant; + } + + public static String getCustomerTenant() { + return Config.Instance().ClientTenant; + } + + public abstract String getOpsToken() throws Exception; + + public abstract String getAdminToken() throws Exception; + + public abstract String getEditorToken() throws Exception; + + public abstract String getNoAccessToken() throws Exception; + + public static ClientResponse send(String path, String httpMethod, String token, String requestBody, String query, + Map<String, String> headers, boolean enforceHttp) + throws Exception { + ClientResponse response = null; + Client client = getClient(); + client.setConnectTimeout(300000); + client.setReadTimeout(300000); + client.setFollowRedirects(false); + String url = getApiPath(path + query, enforceHttp); + WebResource webResource = client.resource(url); + int count = 1; + int MaxRetry = 3; + while (count < MaxRetry) { + try { + headers.put("correlation-id", headers.getOrDefault("correlation-id", UUID.randomUUID().toString())); + WebResource.Builder builder = webResource.type(MediaType.APPLICATION_JSON) + .header("Authorization", token); + headers.forEach((k, v) -> builder.header(k, v)); + //removing Auth header before logging + headers.remove("Authorization"); + log.info(String.format("\nRequest URL: %s %s\nRequest Headers: %s\nRequest Body: %s", httpMethod, url, headers, indentatedBody(requestBody))); + log.info(String.format("Attempt: #%s/%s, CorrelationId: %s", count, MaxRetry, headers.get("correlation-id"))); + response = builder.method(httpMethod, ClientResponse.class, requestBody); + if (response.getStatusInfo().getFamily().equals(Response.Status.Family.valueOf("SERVER_ERROR"))) { + count++; + Thread.sleep(5000); + continue; + } else { + break; + } + } catch (Exception ex) { + log.error("Exception While Making Request: ", ex); + count++; + if (count == MaxRetry) { + throw new AssertionError("Error: Send request error", ex); + } + } finally { + //log response body + log.info("sending response from TestUtils send method"); + if(response!=null) + log.info(String.format("\nThis is the response received : %s\nResponse Headers: %s\nResponse Status code: %s", response, response.getHeaders(), response.getStatus())); + } + } + return response; + } + + public static ClientResponse send(String url, String path, String httpMethod, String token, String requestBody, + String query, Map<String, String> headers, boolean enforceHttp) + throws Exception { + ClientResponse response = null; + Client client = getClient(); + client.setConnectTimeout(300000); + client.setReadTimeout(300000); + client.setFollowRedirects(false); + String URL = getApiPath(url, path + query, enforceHttp); + WebResource webResource = client.resource(URL); + int count = 1; + int MaxRetry = 3; + while (count < MaxRetry) { + try { + headers.put("correlation-id", headers.getOrDefault("correlation-id", UUID.randomUUID().toString())); + WebResource.Builder builder = webResource.type(MediaType.APPLICATION_JSON); + if (!token.isEmpty()) { + log.info("Token is not empty so adding to request header"); + builder.header("Authorization", token); + } + headers.forEach((k, v) -> builder.header(k, v)); + //removing Auth header before logging + headers.remove("Authorization"); + log.info(String.format("\nRequest URL: %s %s\nRequest Headers: %s\nRequest Body: %s", httpMethod, URL, headers, indentatedBody(requestBody))); + log.info(String.format("Attempt: #%s/%s, CorrelationId: %s", count, MaxRetry, headers.get("correlation-id"))); + response = builder.method(httpMethod, ClientResponse.class, requestBody); + if (response.getStatusInfo().getFamily().equals(Response.Status.Family.valueOf("SERVER_ERROR"))) { + count++; + Thread.sleep(5000); + continue; + } else { + break; + } + } catch (Exception ex) { + log.error("Exception While Making Request: ", ex); + count++; + if (count == MaxRetry) { + throw new AssertionError("Error: Send request error", ex); + } + } finally { + //log response body + log.info("sending response from TestUtils send method"); + if(response!=null) + log.info(String.format("\nThis is the response received : %s\nResponse Headers: %s\nResponse Status code: %s", response, response.getHeaders(), response.getStatus())); + } + } + return response; + } + + public static String indentatedBody(String responseBody) { + JsonParser jsonParser = new JsonParser(); + if( responseBody== null) + return responseBody; + JsonElement jsonElement = jsonParser.parse(responseBody); + String indentedResponseEntity =new GsonBuilder().setPrettyPrinting().create().toJson(jsonElement); + return indentedResponseEntity; + } + + @SuppressWarnings("unchecked") + public <T> T getResult(ClientResponse response, int exepectedStatus, Class<T> classOfT) { + String json = response.getEntity(String.class); + + assertEquals(exepectedStatus, response.getStatus()); + if (exepectedStatus == 204) { + return null; + } + + assertEquals(MediaType.APPLICATION_JSON, response.getType().toString()); + if (classOfT == String.class) { + return (T) json; + } + + Gson gson = new Gson(); + return gson.fromJson(json, classOfT); + } + + public static Client getClient() { + TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + @Override + public void checkClientTrusted(X509Certificate[] certs, String authType) { + } + + @Override + public void checkServerTrusted(X509Certificate[] certs, String authType) { + } + }}; + + try { + SSLContext sc = SSLContext.getInstance("TLS"); + sc.init(null, trustAllCerts, new SecureRandom()); + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + } catch (Exception e) { + log.error("Exception occurred", e); + } + log.info("Creating client"); + return Client.create(); + } +} \ No newline at end of file diff --git a/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/TokenTestUtils.java b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/TokenTestUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..76c0845035573e167123ba019ffed28b29cf4227 --- /dev/null +++ b/notification-acceptance-test/src/test/java/org/opengroup/osdu/notification/util/TokenTestUtils.java @@ -0,0 +1,66 @@ +/* + Copyright 2002-2022 Google LLC + Copyright 2002-2022 EPAM Systems, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.opengroup.osdu.notification.util; + +import com.google.common.base.Strings; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class TokenTestUtils extends TestUtils { + + public static final String DE_ADMIN_USER_TOKEN = "DE_ADMIN_USER_TOKEN"; + public static final String DE_EDITOR_USER_TOKEN = "DE_EDITOR_USER_TOKEN"; + public static final String DE_OPS_USER_TOKEN = "DE_OPS_USER_TOKEN"; + public static final String NO_ACCESS_USER_TOKEN = "NO_ACCESS_USER_TOKEN"; + private OpenIDTokenProvider tokenProvider; + + public TokenTestUtils() { + adminToken = System.getProperty(DE_ADMIN_USER_TOKEN, System.getenv(DE_ADMIN_USER_TOKEN)); + editorToken = System.getProperty(DE_EDITOR_USER_TOKEN, System.getenv(DE_EDITOR_USER_TOKEN)); + opsToken = System.getProperty(DE_OPS_USER_TOKEN, System.getenv(DE_OPS_USER_TOKEN)); + noAccessToken = System.getProperty(NO_ACCESS_USER_TOKEN, System.getenv(NO_ACCESS_USER_TOKEN)); + + if (Strings.isNullOrEmpty(adminToken) || Strings.isNullOrEmpty(editorToken) || Strings.isNullOrEmpty(opsToken) || Strings.isNullOrEmpty(noAccessToken)) { + tokenProvider = new OpenIDTokenProvider(); + adminToken = getAdminToken(); + editorToken = getEditorToken(); + opsToken = getOpsToken(); + noAccessToken = getNoAccessToken(); + } + } + + @Override + public synchronized String getOpsToken() { + return "Bearer " + tokenProvider.getOpsAccessToken(); + } + + @Override + public synchronized String getAdminToken() { + return "Bearer " + tokenProvider.getAdminAccessToken(); + } + + @Override + public synchronized String getEditorToken() { + return "Bearer " + tokenProvider.getEditorAccessToken(); + } + + @Override + public synchronized String getNoAccessToken() { + return "Bearer " + tokenProvider.getNoAccessToken(); + } +} \ No newline at end of file diff --git a/notification-acceptance-test/src/test/resources/LegalTag.json b/notification-acceptance-test/src/test/resources/LegalTag.json new file mode 100644 index 0000000000000000000000000000000000000000..e9629c72a833ef80a685f15d028679e75ac6edb6 --- /dev/null +++ b/notification-acceptance-test/src/test/resources/LegalTag.json @@ -0,0 +1,16 @@ +{ + "name": "{{tagName}}", + "properties": { + "countryOfOrigin": [ + "US" + ], + "contractId": "A1234", + "expirationDate": 2222222222222, + "originator": "Default", + "dataType": "Public Domain Data", + "securityClassification": "Public", + "personalData": "No Personal Data", + "exportClassification": "EAR99" + }, + "description": "Test legal tag for notification" +} \ No newline at end of file diff --git a/notification-acceptance-test/src/test/resources/StorageRecord.json b/notification-acceptance-test/src/test/resources/StorageRecord.json new file mode 100644 index 0000000000000000000000000000000000000000..c4a8e395f201baf6ce31ca39d0de01968a2439a3 --- /dev/null +++ b/notification-acceptance-test/src/test/resources/StorageRecord.json @@ -0,0 +1,33 @@ +[ + { + "id": "{{data-partition-id}}:dataset--ConnectedSource.Generic:notification-test-{{ids-suffix}}", + "kind": "{{data-partition-id}}:wks:dataset--ConnectedSource.Generic:1.0.0", + "data": { + "Name": "name", + "DatasetProperties": { + "ConnectedSourceDataJobId": "no-data", + "ConnectedSourceRegistryEntryId": "no-data", + "SourceDataPartitionId": "no-data", + "SourceRecordId": "no-data" + } + }, + "namespace": "{{data-partition-id}}:osdu", + "legal": { + "legaltags": [ + "{{legal-tag}}" + ], + "otherRelevantDataCountries": [ + "US" + ], + "status": "compliant" + }, + "acl": { + "viewers": [ + "data.default.viewers@{{data-partition-id}}.{{group_id}}" + ], + "owners": [ + "data.default.owners@{{data-partition-id}}.{{group_id}}" + ] + } + } +] \ No newline at end of file diff --git a/notification-acceptance-test/src/test/resources/logback-test.xml b/notification-acceptance-test/src/test/resources/logback-test.xml new file mode 100644 index 0000000000000000000000000000000000000000..22c6175d45f368b69c4006deb9ebf3ff5084579a --- /dev/null +++ b/notification-acceptance-test/src/test/resources/logback-test.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configuration> + <include resource="org/springframework/boot/logging/logback/defaults.xml"/> + <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <pattern>%yellow([%thread]) %highlight(| %-5level |) %green(%d) %cyan(| %logger{15} |) %highlight(%msg) %n</pattern> + <charset>utf8</charset> + </encoder> + </appender> + <root level="INFO"> + <appender-ref ref="CONSOLE" /> + </root> +</configuration>