diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3bc4d47c84f89f5d6d9149e7f6515a0c58d85998..0d301d39a7172eff7cfa3c20a354be0489731534 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -157,7 +157,7 @@ azure_test: image: community.opengroup.org:5555/osdu/platform/deployment-and-operations/base-containers-azure/azure-maven17:v0.0.1 aws-test-java: - image: $CI_REGISTRY/osdu/platform/deployment-and-operations/base-containers-aws/aws-maven/aws-maven:v2.0 + image: $CI_REGISTRY/osdu/platform/deployment-and-operations/base-containers-aws/aws-maven/aws-maven:v2.1 fossa-analyze: diff --git a/NOTICE b/NOTICE index 9abc551c8ba291682535717edc47756f169298be..ea15b7badf57b0578176ed848237850c04a1ee0d 100644 --- a/NOTICE +++ b/NOTICE @@ -34,7 +34,6 @@ The following software have components provided under the terms of this license: - AMQP 1.0 JMS Spring Boot Starter (from https://repo1.maven.org/maven2/org/amqphub/spring/amqp-10-jms-spring-boot-starter) - API Common (from https://github.com/googleapis, https://github.com/googleapis/api-common-java, https://repo1.maven.org/maven2/com/google/api/api-common) - ASM based accessors helper used by json-smart (from https://urielch.github.io/) -- AWS Java SDK for AWS Elemental MediaLive (from https://aws.amazon.com/sdkforjava) - AWS Java SDK for AWS KMS (from https://aws.amazon.com/sdkforjava) - AWS Java SDK for AWS Lambda (from https://aws.amazon.com/sdkforjava) - AWS Java SDK for AWS STS (from https://aws.amazon.com/sdkforjava) @@ -54,7 +53,7 @@ The following software have components provided under the terms of this license: - Apache Commons Codec (from http://commons.apache.org/proper/commons-codec/, https://commons.apache.org/proper/commons-codec/) - Apache Commons IO (from http://commons.apache.org/io/, https://commons.apache.org/proper/commons-io/, https://repo1.maven.org/maven2/commons-io/commons-io) - Apache Commons Lang (from https://commons.apache.org/proper/commons-lang/) -- Apache Commons Logging (from http://commons.apache.org/logging/, http://commons.apache.org/proper/commons-logging/) +- Apache Commons Logging (from http://commons.apache.org/logging/, http://commons.apache.org/proper/commons-logging/, https://commons.apache.org/proper/commons-logging/) - Apache Commons Validator (from http://commons.apache.org/proper/commons-validator/, http://jakarta.apache.org/commons/${pom.artifactId.substring(8)}/, https://repo1.maven.org/maven2/commons-validator/commons-validator) - Apache Geronimo JMS Spec 2.0 (from http://geronimo.apache.org/maven/${siteId}/${version}) - Apache Groovy (from http://groovy-lang.org, http://groovy.codehaus.org/, https://groovy-lang.org) @@ -135,8 +134,8 @@ The following software have components provided under the terms of this license: - Jackson-dataformat-XML (from http://wiki.fasterxml.com/JacksonExtensionXmlDataBinding, https://github.com/FasterXML/jackson-dataformat-xml) - 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 Bean Validation API (from https://beanvalidation.org) - Jakarta Servlet (from https://projects.eclipse.org/projects/ee4j.servlet) +- Jakarta Validation API (from https://beanvalidation.org) - 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) - Java Architecture for XML Binding (from http://jaxb.java.net/, https://repo1.maven.org/maven2/javax/xml/bind/jaxb-api) - Java Native Access (from https://github.com/java-native-access/jna, https://github.com/twall/jna) @@ -313,9 +312,7 @@ The following software have components provided under the terms of this license: - swagger-core (from https://repo1.maven.org/maven2/io/swagger/core/v3/swagger-core, https://repo1.maven.org/maven2/io/swagger/swagger-core) - swagger-jaxrs (from https://repo1.maven.org/maven2/io/swagger/swagger-jaxrs) - swagger-models (from https://repo1.maven.org/maven2/io/swagger/core/v3/swagger-models, https://repo1.maven.org/maven2/io/swagger/swagger-models) -- tomcat-embed-core (from http://tomcat.apache.org/) - tomcat-embed-el (from http://tomcat.apache.org/, https://tomcat.apache.org/) -- tomcat-embed-websocket (from http://tomcat.apache.org/, https://tomcat.apache.org/) - wildfly-common (from <https://repo1.maven.org/maven2/org/wildfly/common/wildfly-common>, https://repo1.maven.org/maven2/org/wildfly/common/wildfly-common) ======================================================================== @@ -441,7 +438,6 @@ The following software have components provided under the terms of this license: - JavaBeans Activation Framework (from <http://java.sun.com/javase/technologies/desktop/javabeans/jaf/index.jsp>, http://java.sun.com/javase/technologies/desktop/javabeans/jaf/index.jsp, https://repo1.maven.org/maven2/com/sun/activation/javax.activation) - JavaMail API (from https://repo1.maven.org/maven2/com/sun/mail/javax.mail) - javax.annotation API (from http://jcp.org/en/jsr/detail?id=250) -- tomcat-embed-core (from http://tomcat.apache.org/) ======================================================================== CPL-1.0 @@ -471,7 +467,7 @@ The following software have components provided under the terms of this license: - JUnit Platform Engine API (from http://junit.org/junit5/, https://junit.org/junit5/) - JUnit Vintage Engine (from http://junit.org/junit5/, https://junit.org/junit5/) - Jakarta Annotations API (from https://projects.eclipse.org/projects/ee4j.ca) -- Jakarta Bean Validation API (from https://beanvalidation.org) +- Jakarta Validation API (from https://beanvalidation.org) - 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) - Java Servlet 4.0 API @@ -503,8 +499,8 @@ The following software have components provided under the terms of this license: - JUnit Vintage Engine (from http://junit.org/junit5/, https://junit.org/junit5/) - 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 Bean Validation API (from https://beanvalidation.org) - Jakarta Servlet (from https://projects.eclipse.org/projects/ee4j.servlet) +- Jakarta Validation API (from https://beanvalidation.org) - 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) - Java Servlet 4.0 API @@ -519,7 +515,6 @@ The following software have components provided under the terms of this license: - JBoss Jakarta Annotations API (from <https://github.com/jboss/jboss-jakarta-annotations-api_spec>, https://github.com/jboss/jboss-jakarta-annotations-api_spec) - Jakarta Annotations API (from https://projects.eclipse.org/projects/ee4j.ca) - 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) -- tomcat-embed-core (from http://tomcat.apache.org/) ======================================================================== GPL-2.0-with-classpath-exception @@ -530,8 +525,8 @@ The following software have components provided under the terms of this license: - JBoss Jakarta Annotations API (from <https://github.com/jboss/jboss-jakarta-annotations-api_spec>, https://github.com/jboss/jboss-jakarta-annotations-api_spec) - 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 Bean Validation API (from https://beanvalidation.org) - Jakarta Servlet (from https://projects.eclipse.org/projects/ee4j.servlet) +- Jakarta Validation API (from https://beanvalidation.org) - 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) - Java Architecture for XML Binding (from http://jaxb.java.net/, https://repo1.maven.org/maven2/javax/xml/bind/jaxb-api) @@ -540,7 +535,6 @@ The following software have components provided under the terms of this license: - Old JAXB Core (from <https://eclipse-ee4j.github.io/jaxb-ri/>, https://eclipse-ee4j.github.io/jaxb-ri/) - Old JAXB Runtime (from https://eclipse-ee4j.github.io/jaxb-ri/, https://repo1.maven.org/maven2/com/sun/xml/bind/jaxb-impl) - javax.annotation API (from http://jcp.org/en/jsr/detail?id=250) -- tomcat-embed-core (from http://tomcat.apache.org/) ======================================================================== GPL-3.0-only diff --git a/devops/aws/chart/.helmignore b/devops/aws/chart/.helmignore index 6e238cb1cbd9e264bf7790a760830304695e22a1..95d3192efeb0e0430672e76cf7c08c17530f974f 100644 --- a/devops/aws/chart/.helmignore +++ b/devops/aws/chart/.helmignore @@ -1,3 +1,17 @@ +# Copyright © 2020 Amazon Web Services +# +# 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. + # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. diff --git a/devops/aws/chart/Chart.yaml b/devops/aws/chart/Chart.yaml index 273bfa9d4db374cfb594a6ccf20dfce369698799..9c59aeb498cfaa890b81ab63fb28f65389d22c4d 100644 --- a/devops/aws/chart/Chart.yaml +++ b/devops/aws/chart/Chart.yaml @@ -1,3 +1,17 @@ +# Copyright © 2020 Amazon Web Services +# +# 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. + apiVersion: v2 name: "os-notification" version: __CHART_VERSION__ diff --git a/devops/aws/chart/templates/NOTES.txt b/devops/aws/chart/templates/NOTES.txt index f15afa919efb6cf0dc53f0d70283f9ae0dbbcbbb..d23eb4196e1d11c4a0d5d3880ef345592b60f786 100644 --- a/devops/aws/chart/templates/NOTES.txt +++ b/devops/aws/chart/templates/NOTES.txt @@ -1,3 +1,16 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# 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. + {{ .Chart.Name }} deployed to {{ .Release.Namespace }} namespace {{- if (.Values.service).apiPath }} Application URL available at path {{ .Values.service.apiPath }} diff --git a/devops/aws/chart/templates/authorizationpolicy.yaml b/devops/aws/chart/templates/authorizationpolicy.yaml index c62503152d9f5dc3f958259cf07244619068e9a7..eb6163c85b9facdceb92f9de86dff53f7c71946e 100644 --- a/devops/aws/chart/templates/authorizationpolicy.yaml +++ b/devops/aws/chart/templates/authorizationpolicy.yaml @@ -1,4 +1,17 @@ -{{- template "common.authzpolicy" (list . "os-notification.authzpolicy") -}} +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# 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. + +{{ template "common.authzpolicy" (list . "os-notification.authzpolicy") -}} {{- define "os-notification.authzpolicy" -}} ## Define overrides for the service authorization policy resource here {{- end -}} diff --git a/devops/aws/chart/templates/deployment.yaml b/devops/aws/chart/templates/deployment.yaml index fe5b6d58860fdf701bd7b57f8b9f19f1b070d737..6508e11b8d0a84429eba55fc0068d04c6dabe974 100644 --- a/devops/aws/chart/templates/deployment.yaml +++ b/devops/aws/chart/templates/deployment.yaml @@ -1,4 +1,17 @@ -{{- template "common.deployment" (list . "os-notification.deployment") -}} +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# 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. + +{{ template "common.deployment" (list . "os-notification.deployment") -}} {{- define "os-notification.deployment" -}} ## Define overrides for the service deployment resource here {{- end -}} \ No newline at end of file diff --git a/devops/aws/chart/templates/destinationrule.yaml b/devops/aws/chart/templates/destinationrule.yaml index 8b177c74c326ed11d038e6f3202bf59ecd078746..9569802e9d9b9b3baf34b91431c11189f98479b2 100644 --- a/devops/aws/chart/templates/destinationrule.yaml +++ b/devops/aws/chart/templates/destinationrule.yaml @@ -1,4 +1,17 @@ -{{- template "common.destinationrule" (list . "os-notification.destinationrule") -}} +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# 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. + +{{ template "common.destinationrule" (list . "os-notification.destinationrule") -}} {{- define "os-notification.destinationrule" -}} ## Define overrides for the service destination rule resource here {{- end -}} \ No newline at end of file diff --git a/devops/aws/chart/templates/scaledobject.yaml b/devops/aws/chart/templates/scaledobject.yaml index 223a84f81b02c2956d41f67cb33199886b259b81..af1cdb19c478202b760e7bfc72ce16fabcf56b7e 100644 --- a/devops/aws/chart/templates/scaledobject.yaml +++ b/devops/aws/chart/templates/scaledobject.yaml @@ -1,4 +1,17 @@ -{{- template "common.scaledobject" (list . "os-notification.scaledobject") -}} +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# 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. + +{{ template "common.scaledobject" (list . "os-notification.scaledobject") -}} {{- define "os-notification.scaledobject" -}} ## Define overrides for the service's scaled object resource here {{- end -}} \ No newline at end of file diff --git a/devops/aws/chart/templates/service.yaml b/devops/aws/chart/templates/service.yaml index f428befd679a58ebd22cce606769210ab7396afc..dda584f2916280a24c3f0f184b349d684e6c8fe7 100644 --- a/devops/aws/chart/templates/service.yaml +++ b/devops/aws/chart/templates/service.yaml @@ -1,4 +1,17 @@ -{{- template "common.service" (list . "os-notification.service") -}} +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# 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. + +{{ template "common.service" (list . "os-notification.service") -}} {{- define "os-notification.service" -}} ## Define overrides for the service resource here {{- end -}} \ No newline at end of file diff --git a/devops/aws/chart/templates/serviceaccount.yaml b/devops/aws/chart/templates/serviceaccount.yaml index e9f7578f311c0adf072cec36c41f968fed60362b..3631c010d0f66a6d057e064849f3895f90faf5f7 100644 --- a/devops/aws/chart/templates/serviceaccount.yaml +++ b/devops/aws/chart/templates/serviceaccount.yaml @@ -1,4 +1,17 @@ -{{- template "common.serviceaccount" (list . "os-notification.serviceaccount") -}} +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# 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. + +{{ template "common.serviceaccount" (list . "os-notification.serviceaccount") -}} {{- define "os-notification.serviceaccount" -}} ## Define overrides for the service's service account resource here {{- end -}} \ No newline at end of file diff --git a/devops/aws/chart/templates/serviceparameters.yaml b/devops/aws/chart/templates/serviceparameters.yaml index db735ba41f9d8b2fdb2456248785c4ae9e1fb12c..265fbbc41d9d9bf813b67dd5a89e3813a5b3113f 100644 --- a/devops/aws/chart/templates/serviceparameters.yaml +++ b/devops/aws/chart/templates/serviceparameters.yaml @@ -1,4 +1,17 @@ -{{- template "common.serviceparameters" (list . "os-notification.serviceparameters") -}} +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# 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. + +{{ template "common.serviceparameters" (list . "os-notification.serviceparameters") -}} {{- define "os-notification.serviceparameters" -}} ## Define overrides for the service parameters here {{- end -}} \ No newline at end of file diff --git a/devops/aws/chart/templates/virtualservice.yaml b/devops/aws/chart/templates/virtualservice.yaml index 00eeff92cec2661aee8451b61fd7849620474729..ccdff57782eeb07144bb9f6194e538f441a4e7d3 100644 --- a/devops/aws/chart/templates/virtualservice.yaml +++ b/devops/aws/chart/templates/virtualservice.yaml @@ -1,4 +1,17 @@ -{{- template "common.virtualservice" (list . "os-notification.virtualservice") -}} +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# 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. + +{{ template "common.virtualservice" (list . "os-notification.virtualservice") -}} {{- define "os-notification.virtualservice" -}} ## Define overrides for the service's virtual service resource here {{- end -}} \ No newline at end of file diff --git a/devops/aws/chart/values.yaml b/devops/aws/chart/values.yaml index 2db1c01d3456e94cc8d10f19eb763ad0edca6dfd..d9d65c941df3afaf09793a068ed66bbf7ab083e7 100644 --- a/devops/aws/chart/values.yaml +++ b/devops/aws/chart/values.yaml @@ -1 +1,15 @@ +# Copyright © 2020 Amazon Web Services +# +# 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. + image: __CONTAINER__ \ No newline at end of file diff --git a/devops/aws/pipeline/override-stages.yml b/devops/aws/pipeline/override-stages.yml index 16fb9baf7e4788cbf4a6ad3f0d0cad54986633b0..bcdc513f7215810a1ea6971a20f7c36cfc8afb74 100644 --- a/devops/aws/pipeline/override-stages.yml +++ b/devops/aws/pipeline/override-stages.yml @@ -1,3 +1,17 @@ +# Copyright © 2020 Amazon Web Services +# +# 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. + include: - project: "osdu/platform/ci-cd-pipelines" file: "cloud-providers/aws-global.yml" @@ -11,10 +25,13 @@ include: aws-test-java: script: - export KUBECONFIG=/tmp/kubeconfig-${RANDOM}.yaml - - echo "ROLE $EKS_CLUSTER_MGMT_ROLE" - - echo "CLUSTER $EKS_CLUSTER_NAME" - aws eks update-kubeconfig --region $AWS_REGION --name $EKS_CLUSTER_NAME --role-arn $EKS_CLUSTER_MGMT_ROLE - chmod 600 $KUBECONFIG - + - pip3 install boto3 + - export PUSH_ENDPOINT_PATH=testing/notification-test-aws/build-aws/push-endpoint + - echo "PUSH_ENDPOINT_PATH ${PUSH_ENDPOINT_PATH}" + - python3 $PUSH_ENDPOINT_PATH/setup_teardown_endpoint.py --create --environment_file $PUSH_ENDPOINT_PATH/environment_file.sh --kube_file $PUSH_ENDPOINT_PATH/push-endpoint-manifest.yaml + - trap "python3 $PUSH_ENDPOINT_PATH/setup_teardown_endpoint.py --delete --environment_file $PUSH_ENDPOINT_PATH/environment_file.sh --kube_file $PUSH_ENDPOINT_PATH/push-endpoint-manifest.yaml" EXIT + - source $PUSH_ENDPOINT_PATH/environment_file.sh - $MAVEN_BUILD $INTEGRATION_TEST_DIR maven-aws-integration-test-output.log ${AWS_MAVEN_TEST_COMMAND_OVERRIDE:-test} --update-snapshots -DdisableXmlReport=true diff --git a/provider/notification-aws/build-aws/buildspec.yaml b/provider/notification-aws/build-aws/buildspec.yaml index f9e607cf66c9fe966f36ad6fb495d8c5d84880ed..cce51eb61d9030e516f22fb253740a823899c368 100644 --- a/provider/notification-aws/build-aws/buildspec.yaml +++ b/provider/notification-aws/build-aws/buildspec.yaml @@ -47,18 +47,19 @@ phases: pre_build: commands: - echo "Logging in to Amazon ECR..." - - aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin ${ECR_REGISTRY} + - aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${ECR_REGISTRY} # authenticate with ECR via the AWS CLI - echo "Logging into Docker Hub..." - docker login -u ${DOCKER_USERNAME} -p ${DOCKER_PASSWORD} - build: commands: - export REPO_NAME=${PWD##*/} - export OUTPUT_DIR="dist" - export BRANCH_NAME=`echo ${CODEBUILD_SOURCE_VERSION} | awk '{gsub("refs/heads/","");gsub("\\.","-");gsub("[[:space:]]","-")}1' | sed 's/\//-/g' | awk '{print tolower($0)}'` - export ECR_TAG=`echo build.${BRANCH_NAME}.${CODEBUILD_BUILD_NUMBER}.${CODEBUILD_RESOLVED_SOURCE_VERSION} | cut -c 1-120` + - export PUSH_ENDPOINT_ECR_TAG=`echo push_endpoint.${BRANCH_NAME}.${CODEBUILD_BUILD_NUMBER}.${CODEBUILD_RESOLVED_SOURCE_VERSION} | cut -c 1-120` - export ECR_IMAGE=${ECR_REGISTRY}:${ECR_TAG} - export ECR_IMAGE_BRANCH_LATEST=${ECR_REGISTRY}:${BRANCH_NAME} + - export PUSH_ENDPOINT_IMAGE=${ECR_REGISTRY}:${PUSH_ENDPOINT_ECR_TAG} - export INTEGRATION_TEST_OUTPUT=${OUTPUT_DIR}/testing/integration - export INTEGRATION_TEST_OUTPUT_BIN=${INTEGRATION_TEST_OUTPUT}/bin - mkdir -p ${OUTPUT_DIR}/bin diff --git a/provider/notification-aws/build-aws/entrypoint.sh b/provider/notification-aws/build-aws/entrypoint.sh index c372dfb636e1ff38b9f0c0bf7d89d8ccce695437..efc2ca4222b817f90261e18ce7b4fe40eb150d68 100755 --- a/provider/notification-aws/build-aws/entrypoint.sh +++ b/provider/notification-aws/build-aws/entrypoint.sh @@ -1 +1,15 @@ +# Copyright © 2020 Amazon Web Services +# +# 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. + java $JAVA_OPTS --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED -jar /app.jar diff --git a/provider/notification-aws/pom.xml b/provider/notification-aws/pom.xml index 8e3a0b0cc1cc8d6815d2fa3ad4708f6c30297e8d..bd5067fe44a7fc133ce9085ea198c95616015dd1 100644 --- a/provider/notification-aws/pom.xml +++ b/provider/notification-aws/pom.xml @@ -76,7 +76,7 @@ <dependency> <groupId>org.opengroup.osdu.core.aws</groupId> <artifactId>os-core-lib-aws</artifactId> - <version>0.24.0</version> + <version>0.25.1-SNAPSHOT</version> </dependency> <dependency> <groupId>commons-io</groupId> diff --git a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/NotificationQueueService.java b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/NotificationQueueService.java index 40f21f3eaee9707649605828ba405e78e28e6799..0b4d818faed050cecf7fbd0852fa0158d899d991 100644 --- a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/NotificationQueueService.java +++ b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/NotificationQueueService.java @@ -1,16 +1,17 @@ -// Copyright © Amazon Web Services -// -// 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. +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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.provider.aws.queue; diff --git a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/NotificationRetryQueueService.java b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/NotificationRetryQueueService.java index bc7d33c14f9379406615a57f33c5836cbc0193f2..55f89b91fccec2be10d54f87f44e0c5435662f2e 100644 --- a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/NotificationRetryQueueService.java +++ b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/NotificationRetryQueueService.java @@ -1,16 +1,18 @@ -// Copyright © Amazon Web Services -// -// 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. +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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.provider.aws.queue; import com.amazonaws.services.sqs.model.Message; diff --git a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/NotificationRetrySQSHandler.java b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/NotificationRetrySQSHandler.java index 00f68fcf110d56813cacfd48207638d655d80c68..6aaf28899a29493cd26b26a3f33b00085509d437 100644 --- a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/NotificationRetrySQSHandler.java +++ b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/NotificationRetrySQSHandler.java @@ -1,16 +1,18 @@ -// Copyright © Amazon Web Services -// -// 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. +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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.provider.aws.queue; import com.amazonaws.services.sqs.AmazonSQS; diff --git a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/NotificationSQSHandler.java b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/NotificationSQSHandler.java index 7a1078e858fc4e96f4fb4136991b625f857a39b6..d4e7fe89e8588fcfa709a7990d3d430f6ce5c6d3 100644 --- a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/NotificationSQSHandler.java +++ b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/NotificationSQSHandler.java @@ -1,16 +1,18 @@ -// Copyright © Amazon Web Services -// -// 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. +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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.provider.aws.queue; import com.amazonaws.services.sqs.AmazonSQS; diff --git a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/impl/NotificationQueueServiceImpl.java b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/impl/NotificationQueueServiceImpl.java index da20bf30a1f4e627a14fb438d4bed1067d8683d7..2c0d79d776b79015a73057f2b9dcd63879bb4e44 100644 --- a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/impl/NotificationQueueServiceImpl.java +++ b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/impl/NotificationQueueServiceImpl.java @@ -1,16 +1,18 @@ -// Copyright © Amazon Web Services -// -// 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. +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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.provider.aws.queue.impl; import com.amazonaws.services.dynamodbv2.datamodeling.PaginatedQueryList; @@ -115,6 +117,7 @@ public class NotificationQueueServiceImpl implements NotificationQueueService { } public void processMessagesBySubscription(Subscription subscription, List<Message> messages, String dataPartitionId) { + logger.info("Processing {} messages for subscription {}", messages.size(), subscription.getId()); List<Message> messagesToRetry = new ArrayList<>(); DynamoDBQueryHelperV2 dynamoDBQueryHelper = dynamoDBQueryHelperFactory.getQueryHelperUsingSSM(failedNotificationTablePath); try { @@ -122,13 +125,15 @@ public class NotificationQueueServiceImpl implements NotificationQueueService { gsiQuery.setPartitionIdSubscriptionId(String.join("-", dataPartitionId, subscription.getId())); PaginatedQueryList<FailedNotificationDoc> results = dynamoDBQueryHelper.queryByGSI(FailedNotificationDoc.class, gsiQuery); + logger.info("Failed notifications result: {}", results); if (results != null && !results.isEmpty()) { - logger.debug("Subscription {} has previous failed messages", subscription.getId()); + logger.info("Subscription {} has previous failed messages", subscription.getId()); messagesToRetry.addAll(messages); } else { + logger.info("Processing messages for subscription that has not yet failed: {}", subscription.getPushEndpoint()); boolean hasPreviousFailed = false; for (Message message : messages) { - logger.debug("Processing Notification for messageId: {}, Subscription Endpoint: {}", message.getMessageId(), subscription.getPushEndpoint()); + logger.info("Processing Notification for messageId: {}, Subscription Endpoint: {}", message.getMessageId(), subscription.getPushEndpoint()); if (hasPreviousFailed) { messagesToRetry.add(message); continue; @@ -145,12 +150,13 @@ public class NotificationQueueServiceImpl implements NotificationQueueService { logger.error("Exception in processMessagesBySubscription for {} :", subscription.getPushEndpoint(), e); messagesToRetry.addAll(messages); } - logger.info("Messages retry size :: {}", messagesToRetry.size()); + logger.info("Messages retry size :: {} Subscription ID: {}", messagesToRetry.size(), subscription.getId()); messagesToRetry.forEach(message -> insertFailedNotification(message, subscription, dataPartitionId, dynamoDBQueryHelper)); } private boolean notifySubscriber(Subscription subscription, String messageBody, Map<String, String> headerAttributes) { // Only process this subscription if the topics match. + logger.debug("Subscription: {}, Message Body: {}, Message Headers: {}", subscription, messageBody, headerAttributes); if (!subscription.getTopic().equals(headerAttributes.get(PublishRequestBuilder.OSDU_TOPIC_ATTRIBUTE_NAME))) return true; HttpResponse response; diff --git a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/impl/NotificationRetryQueueServiceImpl.java b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/impl/NotificationRetryQueueServiceImpl.java index b51df1790df1da3b6f1b66ea27c5895bc4fcd323..de55ca71ce6487d40469fbe3ebae69116d53ff0b 100644 --- a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/impl/NotificationRetryQueueServiceImpl.java +++ b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/queue/impl/NotificationRetryQueueServiceImpl.java @@ -1,16 +1,18 @@ -// Copyright © Amazon Web Services -// -// 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. +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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.provider.aws.queue.impl; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBDeleteExpression; @@ -101,12 +103,13 @@ public class NotificationRetryQueueServiceImpl implements NotificationRetryQueue DynamoDBQueryHelperV2 dynamoDBQueryHelper = dynamoDBQueryHelperFactory.getQueryHelperUsingSSM(failedNotificationTablePath); boolean hasPreviousFailed = false; List<RetryProcessResult> notificationResults = new ArrayList<>(); + logger.info("Retrying {} messages from the Retry Queue", messages.size()); for (Message message : messages) { RetryProcessResult processResult = new RetryProcessResult(); processResult.setMessage(message); - logger.debug("Processing Notification for messageId: {}, Subscription Endpoint: {}", message.getMessageId(), subscription.getPushEndpoint()); + logger.info("Processing Notification for messageId: {}, Subscription Endpoint: {}", message.getMessageId(), subscription.getPushEndpoint()); if (hasPreviousFailed) { processResult.setResult(NotificationResult.NACK); notificationResults.add(processResult); @@ -119,6 +122,7 @@ public class NotificationRetryQueueServiceImpl implements NotificationRetryQueue if (!response.isSuccessCode()) { processResult.setResult(NotificationResult.NACK); hasPreviousFailed = true; + logger.error("Failed to process messageId {} for subscriber {}. Error message: {}", message.getMessageId(), subscription.getId(), response.getBody()); } else { processResult.setResult(NotificationResult.ACK); FailedNotificationDoc doc = dynamoDBQueryHelper.loadByPrimaryKey(FailedNotificationDoc.class, diff --git a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/security/AwsSecurityConfig.java b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/security/AwsSecurityConfig.java deleted file mode 100644 index e7567d10ee6a2c222b85e689b8b5f171cff8106b..0000000000000000000000000000000000000000 --- a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/security/AwsSecurityConfig.java +++ /dev/null @@ -1,36 +0,0 @@ - /* - Copyright © 2020 Amazon Web Services - 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.provider.aws.security; - - -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; - - -@SuppressWarnings("deprecation") -@EnableWebSecurity -@EnableGlobalMethodSecurity(prePostEnabled = true) -public class AwsSecurityConfig extends WebSecurityConfigurerAdapter { - @Override - protected void configure(HttpSecurity http) throws Exception { - http.httpBasic().disable() - .csrf().disable(); //disable default authN. AuthN handled by endpoints proxy - } -} - - diff --git a/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsAppPropertiesTest.java b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsAppPropertiesTest.java index b5533616fabb8df7814522ab43fcf70f6b5f7f2b..22bfcdb95ed59a4527b5ffe354009da87d7abefd 100644 --- a/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsAppPropertiesTest.java +++ b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsAppPropertiesTest.java @@ -1,3 +1,17 @@ +// Copyright © Amazon Web Services +// +// 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.provider.aws; import static org.junit.Assert.assertEquals; diff --git a/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsGoogleServiceAccountImplTest.java b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsGoogleServiceAccountImplTest.java index f7e17b0bf99d5cbb287fc5713bcda16d2cf281f1..bcd4ee0fa74c2fa5b89c9380f5c8bab71f937d68 100644 --- a/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsGoogleServiceAccountImplTest.java +++ b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsGoogleServiceAccountImplTest.java @@ -1,3 +1,17 @@ +// Copyright © Amazon Web Services +// +// 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.provider.aws; import org.junit.Test; diff --git a/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsPubSubHandshakeHandlerTest.java b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsPubSubHandshakeHandlerTest.java index d48cbef2d0f95f9bf8a1a9ee240522c7c0d9fc01..a930aea77d0ce6e00602a0694390e0b79d3601c7 100644 --- a/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsPubSubHandshakeHandlerTest.java +++ b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsPubSubHandshakeHandlerTest.java @@ -1,3 +1,17 @@ +// Copyright © Amazon Web Services +// +// 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.provider.aws; import static org.junit.Assert.assertNull; diff --git a/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsServiceAccountValidatorTest.java b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsServiceAccountValidatorTest.java index 5649ab02c19c53adb92df25f6f61afc52e7bb138..ace2602ebaa1e2d70287c97ca48a817bcd336bc4 100644 --- a/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsServiceAccountValidatorTest.java +++ b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsServiceAccountValidatorTest.java @@ -1,3 +1,17 @@ +// Copyright © Amazon Web Services +// +// 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.provider.aws; import static org.junit.Assert.assertFalse; diff --git a/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/security/KmsHelperTest.java b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/security/KmsHelperTest.java index 0eb25f1de6e315b0e4d0fce4fc8d13373de8d951..b16562b8dabb090be1184e56d5fd7ee1f2ac142f 100644 --- a/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/security/KmsHelperTest.java +++ b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/security/KmsHelperTest.java @@ -1,3 +1,17 @@ +// Copyright © Amazon Web Services +// +// 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.provider.aws.security; import static org.mockito.ArgumentMatchers.any; diff --git a/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/utils/AwsCognitoClientTest.java b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/utils/AwsCognitoClientTest.java index 2a1ac4996ce68d931bbc1c0963fd6794095fe808..f6adf45fb2046e25daca5a15d9ff67c78fb4cb4d 100644 --- a/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/utils/AwsCognitoClientTest.java +++ b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/utils/AwsCognitoClientTest.java @@ -1,3 +1,17 @@ +// Copyright © Amazon Web Services +// +// 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.provider.aws.utils; import static org.junit.Assert.assertEquals; diff --git a/testing/notification-test-aws/build-aws/prepare-dist.sh b/testing/notification-test-aws/build-aws/prepare-dist.sh index 3aaf33a954f52dae47001d8f4da7c9449860e7c4..a82740f3e97968bf7cdfcda58863587ef120288e 100755 --- a/testing/notification-test-aws/build-aws/prepare-dist.sh +++ b/testing/notification-test-aws/build-aws/prepare-dist.sh @@ -35,6 +35,10 @@ echo $OUTPUT_DIR echo $INTEGRATION_TEST_OUTPUT_DIR echo $INTEGRATION_TEST_OUTPUT_BIN_DIR +# Build the Push Endpoint image +(cd $INTEGRATION_TEST_SOURCE_DIR_AWS/build-aws/push-endpoint && mvn -B -ntp -s ./maven/settings.xml package && docker build -t $PUSH_ENDPOINT_IMAGE -f Dockerfile --no-cache . && docker push $PUSH_ENDPOINT_IMAGE) +# Finished building the Push Endpoint image + rm -rf "$INTEGRATION_TEST_OUTPUT_DIR" mkdir -p "$INTEGRATION_TEST_OUTPUT_DIR" && mkdir -p "$INTEGRATION_TEST_OUTPUT_BIN_DIR" echo "Building integration testing assemblies and gathering artifacts..." diff --git a/testing/notification-test-aws/build-aws/push-endpoint/Dockerfile b/testing/notification-test-aws/build-aws/push-endpoint/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..48b47e5a79f66b6f2d47b430cc26175c5aa64dab --- /dev/null +++ b/testing/notification-test-aws/build-aws/push-endpoint/Dockerfile @@ -0,0 +1,28 @@ +# Copyright © 2020 Amazon Web Services +# +# 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. + +# https://docs.spring.io/spring-boot/docs/current/reference/html/deployment.html +FROM amazoncorretto:17 + +ARG JAR_FILE=target/*spring-boot.jar +# Harcoding this value since Notification-core requires this variable. AWS does not use it. Might change in future +ENV ENVIRONMENT=DEV + + +WORKDIR / +COPY ${JAR_FILE} app.jar +COPY /entrypoint.sh /entrypoint.sh +EXPOSE 8080 + +ENTRYPOINT ["/bin/sh", "-c", ". /entrypoint.sh"] diff --git a/testing/notification-test-aws/build-aws/push-endpoint/entrypoint.sh b/testing/notification-test-aws/build-aws/push-endpoint/entrypoint.sh new file mode 100644 index 0000000000000000000000000000000000000000..ad36924a8a44f39172321142486daf67eeb75c09 --- /dev/null +++ b/testing/notification-test-aws/build-aws/push-endpoint/entrypoint.sh @@ -0,0 +1,16 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# 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. + + +java $JAVA_OPTS -jar /app.jar diff --git a/testing/notification-test-aws/build-aws/push-endpoint/maven/settings.xml b/testing/notification-test-aws/build-aws/push-endpoint/maven/settings.xml new file mode 100644 index 0000000000000000000000000000000000000000..274a34febd0abf7379555dc4ee10e1d9c64ee67f --- /dev/null +++ b/testing/notification-test-aws/build-aws/push-endpoint/maven/settings.xml @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.​ +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. + +--> + +<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> + + <profiles> + <profile> + <id>aws-osdu-dev-maven</id> + <activation> + <activeByDefault>true</activeByDefault> + </activation> + <repositories> + <repository> + <id>aws-osdu-dev-maven</id> + <url>${env.AWS_OSDU_DEV_MAVEN_URL}</url> + </repository> + <repository> + <id>gitlab-os-core-common-maven</id> + <url>https://community.opengroup.org/api/v4/projects/67/packages/maven</url> + </repository> + <repository> + <id>gitlab-os-core-lib-aws-maven</id> + <url>https://community.opengroup.org/api/v4/projects/68/packages/maven</url> + </repository> + </repositories> + </profile> + <profile> + <id>credentialsConfiguration</id> + <activation> + <activeByDefault>true</activeByDefault> + </activation> + <properties> + <deployment.environment>dev</deployment.environment> + <aws.accessKeyId>no-default</aws.accessKeyId> + <aws.secretKey>no-default</aws.secretKey> + <azure.devops.username>Another-Access-Token-2021</azure.devops.username> + <azure.devops.token>no-default</azure.devops.token> + </properties> + </profile> + <profile> + <id>sonar</id> + <activation> + <activeByDefault>true</activeByDefault> + </activation> + <properties> + <sonar.host.url> + ${env.SONAR_URL} + </sonar.host.url> + </properties> + </profile> + </profiles> + + <servers> + <server> + <id>aws-osdu-dev-maven</id> + <username>aws</username> + <password>${env.AWS_OSDU_DEV_MAVEN_AUTH_TOKEN}</password> + </server> + </servers> + + <mirrors> + <mirror> + <id>aws-osdu-dev-maven</id> + <name>aws-osdu-dev-maven</name> + <url>${env.AWS_OSDU_DEV_MAVEN_URL}</url> + <mirrorOf>!gitlab-os-core-common-maven,!gitlab-os-core-lib-aws-maven</mirrorOf> + </mirror> + </mirrors> + + <activeProfiles> + <activeProfile>credentialsConfiguration</activeProfile> + </activeProfiles> + +</settings> diff --git a/testing/notification-test-aws/build-aws/push-endpoint/pom.xml b/testing/notification-test-aws/build-aws/push-endpoint/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..8b8855dad3f6823435b42ef23e157fcea8b7d43a --- /dev/null +++ b/testing/notification-test-aws/build-aws/push-endpoint/pom.xml @@ -0,0 +1,166 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.​ +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.example</groupId> + <artifactId>notification-push-endpoint</artifactId> + <packaging>jar</packaging> + <version>1.0-SNAPSHOT</version> + + <parent> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-parent</artifactId> + <version>3.1.4</version> + <relativePath/> + </parent> + + <properties> + <maven.compiler.source>17</maven.compiler.source> + <maven.compiler.target>17</maven.compiler.target> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <os-core-common.version>0.25.0-rc2</os-core-common.version> + <spring-boot-maven-plugin.version>2.7.6</spring-boot-maven-plugin.version> + <aws-java-sdk.version>1.11.1018</aws-java-sdk.version> + <aws-encryption-sdk-java.version>2.4.0</aws-encryption-sdk-java.version> + </properties> + + <dependencies> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-security</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + </dependency> + <dependency> + <groupId>org.opengroup.osdu</groupId> + <artifactId>os-core-common</artifactId> + <version>${os-core-common.version}</version> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-encryption-sdk-java</artifactId> + <version>${aws-encryption-sdk-java.version}</version> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-java-sdk-sqs</artifactId> + <version>${aws-java-sdk.version}</version> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-java-sdk-sts</artifactId> + <version>${aws-java-sdk.version}</version> + </dependency> + </dependencies> + + <profiles> + <profile> + <id>aws-dev</id> + <activation> + <property> + <name>deployment.environment</name> + <value>dev</value> + </property> + </activation> + <properties> + <aws.version>1.11.1018</aws.version> + <repo.releases.id>community-maven-repo</repo.releases.id> + <publish.snapshots.id>community-maven-via-job-token</publish.snapshots.id> + <publish.releases.id>community-maven-via-job-token</publish.releases.id> + <repo.releases.url>https://community.opengroup.org/api/v4/groups/17/-/packages/maven</repo.releases.url> + <publish.snapshots.url>https://community.opengroup.org/api/v4/projects/143/packages/maven</publish.snapshots.url> + <publish.releases.url>https://community.opengroup.org/api/v4/projects/143/packages/maven</publish.releases.url> + </properties> + </profile> + </profiles> + + <repositories> + <repository> + <id>${repo.releases.id}</id> + <url>${repo.releases.url}</url> + </repository> + </repositories> + + <distributionManagement> + <repository> + <id>${publish.releases.id}</id> + <url>${publish.releases.url}</url> + </repository> + <snapshotRepository> + <id>${publish.snapshots.id}</id> + <url>${publish.snapshots.url}</url> + </snapshotRepository> + </distributionManagement> + + <build> + <plugins> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + <version>${spring-boot-maven-plugin.version}</version> + <executions> + <execution> + <goals> + <goal>repackage</goal> + </goals> + <configuration> + <classifier>spring-boot</classifier> + <mainClass> + org.example.Application + </mainClass> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + <version>3.5.1</version> + <configuration> + <createDependencyReducedPom>false</createDependencyReducedPom> + </configuration> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>shade</goal> + </goals> + <configuration> + <filters> + <filter> + <artifact>*:*</artifact> + <excludes> + <exclude>META-INF/*.SF</exclude> + <exclude>META-INF/*.DSA</exclude> + <exclude>META-INF/*.RSA</exclude> + </excludes> + </filter> + </filters> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + +</project> \ No newline at end of file diff --git a/testing/notification-test-aws/build-aws/push-endpoint/setup_teardown_endpoint.py b/testing/notification-test-aws/build-aws/push-endpoint/setup_teardown_endpoint.py new file mode 100644 index 0000000000000000000000000000000000000000..922e9d2b328c909a2218e973456960b3058f8755 --- /dev/null +++ b/testing/notification-test-aws/build-aws/push-endpoint/setup_teardown_endpoint.py @@ -0,0 +1,576 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# 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. + +import asyncio +import json +import subprocess as sp +import argparse as ap +import os +import time + +import boto3 +import typing + +NOTIFICATION_SUFFIX = "push-endpoint" + + +SERVICE_ROLE_ASSUME_POLICY_TEMPLATE = """{{ + "Version": "2012-10-17", + "Statement": [ + {{ + "Effect": "Allow", + "Principal": {{ + "Federated": "arn:aws:iam::{0}:oidc-provider/{1}" + }}, + "Action": "sts:AssumeRoleWithWebIdentity", + "Condition": {{ + "StringEquals": {{ + "{1}:sub": "system:serviceaccount:{2}:{3}" + }} + }} + }} + ] +}}""" + + +SERVICE_ROLE_PERMISSIONS_POLICY_TEMPLATE = """{{ + "Version": "2012-10-17", + "Statement": [ + {{ + "Effect": "Allow", + "Action": [ + "sqs:SendMessage" + ], + "Resource": ["{0}"] + }} + ] +}}""" + + +QUEUE_URL_TEMPLATE = """ + - name: QUEUE_NUM_{0} + value: {1}""" + +ALLOWED_ORIGINS_TEMPLATE = """ + - prefix: {0}""" + +SERVICE_ACCOUNT_NAME = "push-endpoint-sa" +PUSH_ENDPOINT_POD_NAME = "push-endpoint" +PUSH_ENDPOINT_PATH = "/api/push-endpoint" +PUSH_ENDPOINT_K8S_TEMPLATE = """ +apiVersion: v1 +kind: Namespace +metadata: + labels: + istio-injection: enabled + name: {push_namespace} +spec: +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + annotations: + eks.amazonaws.com/role-arn: {role_arn} + name: {name} + namespace: {push_namespace} +--- +apiVersion: v1 +kind: Service +metadata: + labels: + service: {name} + name: {name} + namespace: {push_namespace} +spec: + ports: + - name: http + port: 8080 + protocol: TCP + targetPort: 8080 + selector: + app.kubernetes.io/instance: {name} + app.kubernetes.io/name: {name} + type: ClusterIP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/instance: {name} + app.kubernetes.io/name: {name} + name: {name} + namespace: {push_namespace} +spec: + selector: + matchLabels: + app.kubernetes.io/instance: {name} + app.kubernetes.io/name: {name} + template: + metadata: + annotations: null + labels: + app.kubernetes.io/instance: {name} + app.kubernetes.io/name: {name} + spec: + automountServiceAccountToken: true + containers: + - env: + - name: HMAC_SECRET + value: "{hmac_secret}" + - name: AWS_REGION + value: "{aws_region}" + - name: MAX_QUEUE_NUM + value: "{num_queues}" +{queue_urls} + image: "{image}" + imagePullPolicy: Always + name: {name} + ports: + - containerPort: 8080 + name: http + protocol: TCP + resources: + limits: + memory: 900M + requests: + cpu: 1000m + memory: 900M + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 10001 + volumeMounts: + - mountPath: /tmp + name: tmp-volume + securityContext: + fsGroup: 1337 + seccompProfile: + type: RuntimeDefault + serviceAccountName: {name} + volumes: + - emptyDir: + sizeLimit: 2Gi + name: tmp-volume +--- +apiVersion: security.istio.io/v1beta1 +kind: AuthorizationPolicy +metadata: + name: {name}-allow-services + namespace: {push_namespace} +spec: + action: ALLOW + rules: + - from: + - source: + principals: + - cluster.local/ns/{ingress_namespace}/sa/{ingress_gateway_name} + - cluster.local/ns/{core_namespace}/sa/os-notification + - cluster.local/ns/{core_namespace}/sa/os-register + selector: + matchLabels: + app.kubernetes.io/name: {name} +--- +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: {name} + namespace: {push_namespace} +spec: + host: {name} + trafficPolicy: + portLevelSettings: + - connectionPool: + http: + http1MaxPendingRequests: 10000 + http2MaxRequests: 100 + tcp: + maxConnections: 0 + port: + number: 8080 + tls: + mode: ISTIO_MUTUAL +--- +apiVersion: networking.istio.io/v1alpha3 +kind: VirtualService +metadata: + name: {name} + namespace: {push_namespace} +spec: + gateways: + - {ingress_namespace}/{osdu_gateway_name} + hosts: + - '*' + http: + - corsPolicy: + allowCredentials: true + allowHeaders: + - Authorization + - Data-Partition-Id + - Correlation-Id + - Content-Type + allowMethods: + - POST + - GET + - PATCH + - PUT + - DELETE + allowOrigins: +{allowed_origins} + maxAge: 60m + headers: + response: + remove: + - access-control-allow-origin + - access-control-allow-credentials + set: + access-control-allow-headers: Authorization, Data-Partition-Id, Correlation-Id, + Content-Type + access-control-allow-methods: POST, GET, PATCH, PUT, DELETE + match: + - uri: + prefix: {api_path} + route: + - destination: + host: {name} + port: + number: 8080 +""" + +class CommonParameters: + def __init__(self, osdu_instance: str, eks_cluster: str, region: str, + num_queues: int, env_file: str, base_url: str, domain_name: str, + endpoint_suffix: str, kube_file: typing.Optional[str], api_path: str): + self.account_id = boto3.client('sts').get_caller_identity().get('Account') + self.osdu_instance = osdu_instance + self.eks_cluster = eks_cluster + self.region = region + self.domain_name = domain_name + self.endpoint_suffix = endpoint_suffix + self.kube_file = kube_file + self.namespace_prefix: str = "" + self.ingress_namespace: str = "" + self.ingress_gateway: str = "" + self.osdu_gateway: str = "" + self.amp_workspace: str = "" + self.num_queues = num_queues + self.env_file = env_file + self.base_url = base_url + self.sa_role_policy_name = "int-test-notification-policy" + self._set_parameters() + self.api_path = api_path + self.wildcard_path = f"{self.api_path}/*" + self.sqs_client = boto3.client('sqs', region_name=region) + self.iam_client = boto3.client('iam', region_name=region) + + if kube_file is None: + self.kube_file = f"{self.push_namespace}.yaml" + + def _set_parameters(self): + sns_client = boto3.client('ssm', region_name=self.region) + parameters = { + f"/osdu/eks/{self.eks_cluster}/amp/workspace/id": "amp_workspace", + f"/osdu/eks/{self.eks_cluster}/instances/{self.osdu_instance}/ingress/osdu-gateway/name": "osdu_gateway", + f"/osdu/eks/{self.eks_cluster}/instances/{self.osdu_instance}/ingress/ingress-gateway/name": "ingress_gateway", + f"/osdu/eks/{self.eks_cluster}/instances/{self.osdu_instance}/ingress/namespace": "ingress_namespace", + f"/osdu/instances/{self.osdu_instance}/config/k8s/namespace-prefix": "namespace_prefix", + } + params = sns_client.get_parameters(Names=[key for key in parameters]) + for parameter in params["Parameters"]: + parameter_path = parameter["Name"] + short_name = parameters[parameter_path] + setattr(self, short_name, parameter["Value"]) + + self.core_namespace = self.get_namespace("core") + self.push_namespace = self.get_namespace(self.endpoint_suffix) + print("Push Endpoint namespace:", self.push_namespace) + + def get_namespace(self, suffix: str) -> str: + return f"{self.namespace_prefix}-{suffix}" + + def get_service_role(self) -> str: + return f"{self.region}-{self.push_namespace}" + + def get_sqs_queue_name(self, queue_num: int) -> str: + return f"{self.push_namespace}-{queue_num}" + + def get_oidc_id(self) -> str: + eks_client = boto3.client('eks', region_name=self.region) + cluster_info = eks_client.describe_cluster(name=self.eks_cluster) + return cluster_info["cluster"]["identity"]["oidc"]["issuer"] \ + [len("https://"):] + + def create_policy_document(self, queue_arns: typing.List[str]) -> str: + service_role_name = self.get_service_role() + oidc_id = self.get_oidc_id() + assume_account_policy = SERVICE_ROLE_ASSUME_POLICY_TEMPLATE \ + .format(self.account_id, oidc_id, self.push_namespace, + PUSH_ENDPOINT_POD_NAME) + permissions_policy = SERVICE_ROLE_PERMISSIONS_POLICY_TEMPLATE \ + .format('", "'.join(queue_arns)) + role_arn: str + try: + role = self.iam_client.create_role(RoleName=service_role_name, + AssumeRolePolicyDocument=assume_account_policy) + self.iam_client.put_role_policy(RoleName=service_role_name, + PolicyName=self.sa_role_policy_name, + PolicyDocument=permissions_policy) + role_arn = role["Role"]["Arn"] + except self.iam_client.exceptions.EntityAlreadyExistsException: + role = self.iam_client.get_role(RoleName=service_role_name) + role_arn = role["Role"]["Arn"] + return role_arn + + def create_k8s_file(self, queue_urls: typing.List[str], + env_file: typing.TextIO, role_arn: str): + queue_url_templates = [] + for i, url in enumerate(queue_urls): + queue_url_templates.append(QUEUE_URL_TEMPLATE.format(i, url)) + env_file.write(f"export PUSH_ENDPOINT_QUEUE_{i}={url}\n") + env_file.write(f"export PUSH_ENDPOINT_URL_{i}={self.base_url}{self.api_path}/{i}\n") + env_file.write(f"export PUSH_ENDPOINT_NUM_QUEUES={self.num_queues}\n") + queue_url_template = "".join(queue_url_templates)[1:] + + hmac_secret = sp.check_output(["openssl", "rand", "-hex", "15"]).decode("utf-8").strip() + + notification_command = f'kubectl get deployment -n {self.core_namespace} os-notification --output json | jq -r ".spec.template.spec.containers[0].image"' + notification_result = sp.run(notification_command, shell=True, capture_output=True, encoding="utf-8") + if notification_result.stderr: + print("Notification command had standard error:", notification_result.stderr) + + notification_image = notification_result.stdout.strip() + image_parts = notification_image.split(":") + print(image_parts, notification_image) + if len(image_parts) != 2: + raise RuntimeError("Unexpected result from Kubectl command.") + + # Depending on build env, images names could have two formats: + # - `build.dev.1101.COMMIT_HASH` on CodePipeline + # - `COMMIT_HASH` on Gitlab + # Using -1 as an index here after the split avoid an IndexError with the second case + endpoint_image_tag = f"push_endpoint.{image_parts[1].split('.', 1)[-1]}" + endpoint_image = f"{image_parts[0]}:{endpoint_image_tag[:120]}" + env_file.write(f"export HMAC_SECRET={hmac_secret}\n") + + allowed_origins = [ + ALLOWED_ORIGINS_TEMPLATE.format("http://localhost"), + ALLOWED_ORIGINS_TEMPLATE.format(f"https://{self.domain_name}") + ] + print(allowed_origins, endpoint_image) + + values_contents = PUSH_ENDPOINT_K8S_TEMPLATE \ + .format(core_namespace=self.core_namespace, + ingress_namespace=self.ingress_namespace, + push_namespace=self.push_namespace, + ingress_gateway_name=self.ingress_gateway, + osdu_gateway_name=self.osdu_gateway, + name=PUSH_ENDPOINT_POD_NAME, + hmac_secret=hmac_secret, + aws_region=self.region, + num_queues=self.num_queues, + image=endpoint_image, + queue_urls=queue_url_template, + api_path=self.api_path, + allowed_origins="".join(allowed_origins)[1:], + role_arn=role_arn) + + with open(self.kube_file, "w") as file: + file.write(values_contents) + + async def ensure_queue_created(self, queue_num: int, + received_queues: asyncio.Queue): + queue_name = self.get_sqs_queue_name(queue_num) + try: + queue = self.sqs_client.create_queue(QueueName=queue_name) + except self.sqs_client.exceptions.QueueDeletedRecently: + time.sleep(62) + await self.ensure_queue_created(queue_num, received_queues) + return + except self.sqs_client.exceptions.QueueNameExists: + queue = self.sqs_client.get_queue_url(QueueName=queue_name) + await received_queues.put(queue["QueueUrl"]) + + def get_sqs_queue_arn(self, queue_url: str): + QUEUE_ARN_ATTR = "QueueArn" + response = self.sqs_client.get_queue_attributes( + QueueUrl=queue_url, + AttributeNames=[QUEUE_ARN_ATTR] + ) + return response["Attributes"][QUEUE_ARN_ATTR] + + def disable_jwt_auth_on_path(self): + output = sp.check_output(["kubectl", "get", "authorizationpolicy", "-n", + self.ingress_namespace, "ingress-jwt-required", + "-o", "json"]) + current_auth_policy = json.loads(output) + for rule in current_auth_policy["spec"]["rules"]: + for outer_op in rule["to"]: + not_paths = outer_op["operation"]["notPaths"] + if self.wildcard_path not in not_paths: + not_paths.append(self.wildcard_path) + new_auth_policy = json.dumps(current_auth_policy) + sp.check_output(["kubectl", "apply", "-f", "-"], input=new_auth_policy, + encoding='utf-8') + + async def create_resources(self): + received_queues = asyncio.Queue() + tasks = [] + for i in range(self.num_queues): + task = asyncio.create_task( + self.ensure_queue_created(i, received_queues) + ) + tasks.append(task) + + await asyncio.gather(*tasks) + print("Should have created the queues.") + + queue_arns = [] + queue_urls = [] + while not received_queues.empty(): + queue_url = await received_queues.get() + queue_arns.append(self.get_sqs_queue_arn(queue_url)) + queue_urls.append(queue_url) + + role_arn = self.create_policy_document(queue_arns) + print("Should have created the IAM Role and policy. ARN:", role_arn) + + with open(self.env_file, "w") as file: + self.create_k8s_file(queue_urls, file, role_arn) + + print("Now creating the Kubernetes resources") + sp.check_output(["kubectl", "apply", "-f", self.kube_file]) + + print("Now changing the JWT Authorization Policy") + self.disable_jwt_auth_on_path() + + async def ensure_queue_deleted(self, queue_num: int): + queue_name = self.get_sqs_queue_name(queue_num) + try: + queue_url = self.sqs_client.get_queue_url(QueueName=queue_name) + self.sqs_client.delete_queue(QueueUrl=queue_url["QueueUrl"]) + except self.sqs_client.exceptions.QueueDoesNotExist: + print("Queue", queue_name, "not found, so could not delete!") + + def re_enable_jwt_auth_on_path(self): + output = sp.check_output(["kubectl", "get", "authorizationpolicy", "-n", + self.ingress_namespace, "ingress-jwt-required", + "-o", "json"]) + current_auth_policy = json.loads(output) + for rule in current_auth_policy["spec"]["rules"]: + for outer_op in rule["to"]: + not_paths = outer_op["operation"]["notPaths"] + try: + not_paths.remove(self.wildcard_path) + except ValueError: + print(f"Path {self.wildcard_path} was already not exempted from the disable JWT authentication.") + + new_auth_policy = json.dumps(current_auth_policy) + sp.check_output(["kubectl", "apply", "-f", "-"], input=new_auth_policy, + encoding='utf-8') + + async def delete_resources(self): + print("Now changing the JWT Authorization Policy") + self.re_enable_jwt_auth_on_path() + + print("Deleting the kubernetes resources.") + try: + sp.check_output(["kubectl", "delete", "-f", self.kube_file]) + except Exception as e: + print("Failed to delete the kubernetes resources:", e) + + print("Deleting the role policy.") + try: + self.iam_client.delete_role_policy(RoleName=self.get_service_role(), + PolicyName=self.sa_role_policy_name) + self.iam_client.delete_role(RoleName=self.get_service_role()) + except self.iam_client.exceptions.NoSuchEntityException: + print("Could not delete role", self.get_service_role(), + "because it does not exist!") + + print("Deleting the SQS queues.") + tasks = [] + for i in range(self.num_queues): + task = asyncio.create_task(self.ensure_queue_deleted(i)) + tasks.append(task) + + await asyncio.gather(*tasks) + + +async def main(): + argparser = ap.ArgumentParser(description="Handles creation/deletion of the" + " AWS resources required for the integration te" + "sts and creates an environment variable file f" + "or the integration tests to use.") + argparser.add_argument('--region', type=str, + default=os.getenv('AWS_REGION'), + help="The AWS region to deploy the cloud resources to.") + argparser.add_argument('--num_queues', type=int, default=2, + help="The number of queues to create.") + argparser.add_argument('--osdu_instance_name', type=str, + default=os.getenv("OSDU_INSTANCE_NAME"), + help="The OSDU instance name.") + argparser.add_argument('--eks_cluster_name', type=str, + default=os.getenv("EKS_CLUSTER_NAME")) + argparser.add_argument('--base_url', type=str, + default=os.getenv("AWS_BASE_URL")) + argparser.add_argument('--domain_name', type=str, + default=os.getenv("DOMAIN")) + argparser.add_argument('--endpoint_suffix', type=str, + default=NOTIFICATION_SUFFIX) + argparser.add_argument('--kube_file', type=str, default=None) + argparser.add_argument('--api_path', type=str, + default=PUSH_ENDPOINT_PATH, + help="The push endpoint path relative from the ingress gateway.") + argparser.add_argument('--environment_file', type=str, + default="./environment_file.sh", + help="The file to create the environment variables in.") + argparser.add_argument('--create', action='store_true', help="Creates the " + "resources required for the integration tests.") + argparser.add_argument('--delete', action='store_true', help="Deletes the " + "resources created for the integration tests.") + + args = argparser.parse_args() + if args.create and args.delete: + raise ValueError("Cannot create and delete at the same time.") + + if not args.create and not args.delete: + raise ValueError("Must specify either create or delete.") + + osdu_instance = args.osdu_instance_name + eks_cluster = args.eks_cluster_name + num_queues = args.num_queues + region = args.region + env_file = args.environment_file + base_url = args.base_url + domain_name = args.domain_name + endpoint_suffix = args.endpoint_suffix + kube_file = args.kube_file + api_path = args.api_path + common_params = CommonParameters(osdu_instance, eks_cluster, region, + num_queues, env_file, base_url, domain_name, + endpoint_suffix, kube_file, api_path) + + if args.create: + await common_params.create_resources() + + if args.delete: + await common_params.delete_resources() + + +if __name__ == '__main__': + asyncio.run(main()) + diff --git a/testing/notification-test-aws/build-aws/push-endpoint/src/main/java/org/example/Application.java b/testing/notification-test-aws/build-aws/push-endpoint/src/main/java/org/example/Application.java new file mode 100644 index 0000000000000000000000000000000000000000..af98f486137d175490ae38c39bd7d73fdb0615c8 --- /dev/null +++ b/testing/notification-test-aws/build-aws/push-endpoint/src/main/java/org/example/Application.java @@ -0,0 +1,30 @@ +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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.example; + +import jakarta.servlet.http.HttpServlet; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.annotation.Bean; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/testing/notification-test-aws/build-aws/push-endpoint/src/main/java/org/example/HmacVerification.java b/testing/notification-test-aws/build-aws/push-endpoint/src/main/java/org/example/HmacVerification.java new file mode 100644 index 0000000000000000000000000000000000000000..3a730f523414cbf48d6c3d364db53bdef6693c57 --- /dev/null +++ b/testing/notification-test-aws/build-aws/push-endpoint/src/main/java/org/example/HmacVerification.java @@ -0,0 +1,71 @@ +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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.example; + +import org.opengroup.osdu.core.common.cryptographic.SignatureService; +import org.opengroup.osdu.core.common.cryptographic.SignatureServiceException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; + +import jakarta.servlet.http.HttpServletRequest; + +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Map; + +@Component("hmacVerification") +@RequestScope +public class HmacVerification { + @Autowired + private HttpServletRequest request; + + private final SignatureService service = new SignatureService(); + + private static final Logger LOGGER = LoggerFactory.getLogger(HmacVerification.class); + + public boolean verifyHmac() { + boolean foundError = false; + LOGGER.info("Inside verifyHmac"); + LOGGER.error("Request: {}", request); + try { + Map<String, String> params = QueryStringUtils.parseQueryString(request.getQueryString()); + LOGGER.info(request.getQueryString()); + String tokenToVerify = params.get("hmac"); + if (tokenToVerify == null) throw new SignatureServiceException("Hmac verification not attached to request!"); + tokenToVerify = URLDecoder.decode(tokenToVerify, StandardCharsets.UTF_8); + service.verifyHmacSignature(tokenToVerify, OSDUSecretString.getSecret()); + } catch (SignatureServiceException except) { + LOGGER.error("Failed to verify request.", except); + foundError = true; + } + return !foundError; + } + + private static final String URL = "https://my.url/com"; + private static final String NONCE = "FEDCBA9876543210"; + public static void main(String[] args) throws SignatureServiceException { + SignatureService service = new SignatureService(); + String expireTime = Long.toString(System.currentTimeMillis() + 3600000); + String data = String.format("{\"expireMillisecond\": \"%s\",\"hashMechanism\": \"hmacSHA256\",\"endpointUrl\": \"%s\",\"nonce\": \"%s\"}", expireTime, URL, NONCE); + String encodedData = Base64.getEncoder().encodeToString(data.getBytes(StandardCharsets.UTF_8)); + String signature = encodedData + "." + service.getSignedSignature(URL, OSDUSecretString.getSecret(), expireTime, NONCE); + System.out.println(signature); + } +} diff --git a/testing/notification-test-aws/build-aws/push-endpoint/src/main/java/org/example/OSDUSecretString.java b/testing/notification-test-aws/build-aws/push-endpoint/src/main/java/org/example/OSDUSecretString.java new file mode 100644 index 0000000000000000000000000000000000000000..cef67c18a5e6160c7bd5204e4151b0f212a80daf --- /dev/null +++ b/testing/notification-test-aws/build-aws/push-endpoint/src/main/java/org/example/OSDUSecretString.java @@ -0,0 +1,32 @@ +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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.example; + +public class OSDUSecretString { + private static String secretValue = null; + //private static String secretValue = "0123456789abcdef"; + private static final String SECRET_ENV_NAME = "HMAC_SECRET"; + + public static String getSecret() { + if (secretValue == null) { + secretValue = System.getenv(SECRET_ENV_NAME); + if (secretValue == null) throw new NullPointerException("Must specify the HMAC Secret via the environment variable: " + SECRET_ENV_NAME); + } + System.out.println("Got secret..."); + return secretValue; + } + +} diff --git a/testing/notification-test-aws/build-aws/push-endpoint/src/main/java/org/example/PushEndpointController.java b/testing/notification-test-aws/build-aws/push-endpoint/src/main/java/org/example/PushEndpointController.java new file mode 100644 index 0000000000000000000000000000000000000000..12020776d0e873b60282ea946a514f19d8615ad2 --- /dev/null +++ b/testing/notification-test-aws/build-aws/push-endpoint/src/main/java/org/example/PushEndpointController.java @@ -0,0 +1,126 @@ +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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.example; + +import com.amazonaws.services.sqs.AmazonSQS; +import com.amazonaws.services.sqs.AmazonSQSClientBuilder; +import com.amazonaws.services.sqs.model.SendMessageResult; +import com.google.common.hash.Hashing; +import org.apache.http.HttpStatus; +import org.opengroup.osdu.core.common.model.http.AppException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.context.annotation.RequestScope; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.servlet.HandlerMapping; + +import jakarta.servlet.http.HttpServletRequest; +import javax.validation.constraints.NotBlank; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Map; +import java.util.Scanner; + +@RestController +@RequestMapping("/") +@RequestScope +@Validated +public class PushEndpointController { + private final AmazonSQS sqsClient; + private final int maxQueueNum; + private static final Logger LOGGER = LoggerFactory.getLogger(PushEndpointController.class); + + public PushEndpointController() { + sqsClient = AmazonSQSClientBuilder.defaultClient(); + maxQueueNum = Integer.parseInt(System.getenv("MAX_QUEUE_NUM")); + } + + private static String verifySubscriptionForChallenge(String crc) { + String response = OSDUSecretString.getSecret() + crc; + response = Hashing.sha256() + .hashString(response, StandardCharsets.UTF_8) + .toString(); + response = Base64.getEncoder().encodeToString(response.getBytes()); + return response; + } + + @GetMapping("/{count}") + @PreAuthorize("@hmacVerification.verifyHmac()") + public ResponseEntity<VerifySubscriptionResponse> verifySubscription(@RequestParam("crc") @NotBlank String crc, HttpServletRequest request) { + getQueueNumberFromRequest(request); + String response = verifySubscriptionForChallenge(crc); + VerifySubscriptionResponse returnValue = new VerifySubscriptionResponse(response); + LOGGER.info(returnValue.toString()); + return ResponseEntity.ok(returnValue); + } + + private String readMessage(HttpServletRequest request) throws IOException { + Scanner scan = new Scanner(request.getInputStream()); + StringBuilder builder = new StringBuilder(); + while (scan.hasNextLine()) { + builder.append(scan.nextLine()); + } + return builder.toString(); + } + + private void throwAppException(String message) { + throw new AppException(HttpStatus.SC_BAD_REQUEST, "Bad Request", message); + } + + private int getQueueNumberFromRequest(HttpServletRequest request) { + Object uriTemplateObject = request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); + if (uriTemplateObject == null || !(uriTemplateObject instanceof Map)) { + throwAppException("Invalid request path!"); + } + Map<String, String> uriTempalteVariables = (Map<String, String>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); + String queueNumber = uriTempalteVariables.get("count"); + int returnValue = Integer.parseInt(queueNumber); + if (returnValue >= maxQueueNum) { + throwAppException("Invalid queue number!"); + } + return returnValue; + } + + private String getQueueURL(HttpServletRequest request) { + String queueURL = System.getenv("QUEUE_NUM_" + getQueueNumberFromRequest(request)); + if (queueURL == null) { + throwAppException("Queue not found!"); + } + return queueURL; + } + + @PostMapping("/{count}") + @PreAuthorize("@hmacVerification.verifyHmac()") + public ResponseEntity<SendMessageResult> pushNotificationToQueue(HttpServletRequest request) throws IOException { + String queueURL = getQueueURL(request); + String message = readMessage(request); + SendMessageResult returnValue = sqsClient.sendMessage(queueURL, message); + LOGGER.info(returnValue.toString()); + return ResponseEntity.ok(returnValue); + } +} + +record VerifySubscriptionResponse(String responseHash) { + +} diff --git a/testing/notification-test-aws/build-aws/push-endpoint/src/main/java/org/example/QueryStringUtils.java b/testing/notification-test-aws/build-aws/push-endpoint/src/main/java/org/example/QueryStringUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..d79e70e4f921177a080f68999d61345db83731c7 --- /dev/null +++ b/testing/notification-test-aws/build-aws/push-endpoint/src/main/java/org/example/QueryStringUtils.java @@ -0,0 +1,32 @@ +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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.example; + +import java.util.HashMap; +import java.util.Map; + +public class QueryStringUtils { + + public static Map<String, String> parseQueryString(String queryString) { + HashMap<String, String> retValue = new HashMap<>(); + for (String pair : queryString.split("&")) { + String[] keyValue = pair.split("=", 2); + if (keyValue.length == 2) retValue.put(keyValue[0], keyValue[1]); + } + return retValue; + } + +} diff --git a/testing/notification-test-aws/build-aws/push-endpoint/src/main/java/org/example/SecurityConfig.java b/testing/notification-test-aws/build-aws/push-endpoint/src/main/java/org/example/SecurityConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..093ffd18ab8b6fa3fa6dde7f4dc0da626fba8c50 --- /dev/null +++ b/testing/notification-test-aws/build-aws/push-endpoint/src/main/java/org/example/SecurityConfig.java @@ -0,0 +1,34 @@ +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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.example; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.web.SecurityFilterChain; + +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) +@Configuration +public class SecurityConfig { + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + return http.httpBasic().disable().csrf().disable().build(); + } +} diff --git a/testing/notification-test-aws/build-aws/push-endpoint/src/main/resources/application.properties b/testing/notification-test-aws/build-aws/push-endpoint/src/main/resources/application.properties new file mode 100644 index 0000000000000000000000000000000000000000..30b07cc6788082a9b99213bc91fd967433dc1335 --- /dev/null +++ b/testing/notification-test-aws/build-aws/push-endpoint/src/main/resources/application.properties @@ -0,0 +1,9 @@ +LOG_PREFIX=push_endpoint +logging.level.org.springframework.web=${LOG_LEVEL:INFO} +server.servlet.contextPath=/api/push-endpoint +server.port=${APPLICATION_PORT:8080} + +spring.application.name=push-endpoint +management.endpoint.health.probes.enabled=true +management.health.livenessState.enabled=true +management.health.readinessState.enabled=true diff --git a/testing/notification-test-aws/build-aws/run-tests.sh b/testing/notification-test-aws/build-aws/run-tests.sh index afd1e9e3a44432dacecbd08cd37d703cac09c99c..5a181f150a5ccac46b6de6286638f4d7ecee6e93 100755 --- a/testing/notification-test-aws/build-aws/run-tests.sh +++ b/testing/notification-test-aws/build-aws/run-tests.sh @@ -30,6 +30,11 @@ echo "$SCRIPT_SOURCE_DIR" # The following variables are automatically populated from the environment during integration testing # see os-deploy-aws/build-aws/integration-test-env-variables.py for an updated list +PUSH_ENDPOINT_PATH=$SCRIPT_SOURCE_DIR/push-endpoint +python3 $PUSH_ENDPOINT_PATH/setup_teardown_endpoint.py --create --environment_file $PUSH_ENDPOINT_PATH/environment_file.sh --kube_file $PUSH_ENDPOINT_PATH/push-endpoint-manifest.yaml + +trap "python3 $PUSH_ENDPOINT_PATH/setup_teardown_endpoint.py --delete --environment_file $PUSH_ENDPOINT_PATH/environment_file.sh --kube_file $PUSH_ENDPOINT_PATH/push-endpoint-manifest.yaml" EXIT +source $PUSH_ENDPOINT_PATH/environment_file.sh export AWS_COGNITO_AUTH_FLOW=USER_PASSWORD_AUTH export AWS_COGNITO_AUTH_PARAMS_PASSWORD=$ADMIN_PASSWORD @@ -37,13 +42,16 @@ export AWS_COGNITO_AUTH_PARAMS_USER=$ADMIN_USER export AWS_COGNITO_AUTH_PARAMS_USER_NO_ACCESS=$USER_NO_ACCESS export ENVIRONMENT=DEV export NOTIFICATION_REGISTER_BASE_URL=$NOTIFICATION_REGISTER_BASE_URL -export HMAC_SECRET=02030405060708090A0B0C0D0E0F -export REGISTER_CUSTOM_PUSH_PATH=/api/register/v1/awstest/aws/challenge/1 +export REGISTER_CUSTOM_PUSH_PATH=/api/push-endpoint/0 +export STORAGE_HOST=$STORAGE_URL +export FILE_URL=$FILE_URL export REGISTER_CUSTOM_PUSH_URL_HMAC=$NOTIFICATION_REGISTER_BASE_URL$REGISTER_CUSTOM_PUSH_PATH export NOTIFICATION_BASE_URL=$NOTIFICATION_BASE_URL - +export OSDU_TENANT=int-test-notification +export TENANT_NAME=int-test-notification #### RUN INTEGRATION TEST ######################################################################### +JAVA_HOME=$JAVA17_HOME mvn test -f "$SCRIPT_SOURCE_DIR"/../pom.xml TEST_EXIT_CODE=$? diff --git a/testing/notification-test-aws/pom.xml b/testing/notification-test-aws/pom.xml index 15f79aaacb288d9a119108d8ece41b37da167702..56fa1b277a2ddbac69d53610801572d9fd34fbb2 100644 --- a/testing/notification-test-aws/pom.xml +++ b/testing/notification-test-aws/pom.xml @@ -51,6 +51,16 @@ <artifactId>aws-java-sdk-cognitoidp</artifactId> <version>1.11.676</version> </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-java-sdk-ssm</artifactId> + <version>1.11.339</version> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-java-sdk-sqs</artifactId> + <version>1.11.339</version> + </dependency> <dependency> <groupId>org.opengroup.osdu.notification</groupId> <artifactId>notification-test-core</artifactId> diff --git a/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/api/PubsubEndpointHMACDescriptor.java b/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/api/PubsubEndpointHMACDescriptor.java index 9f439169743714ddba75eebe46620b3b6ad052cd..1417d968e90ff4c0577eb2f65dafa1a14171db42 100644 --- a/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/api/PubsubEndpointHMACDescriptor.java +++ b/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/api/PubsubEndpointHMACDescriptor.java @@ -1,15 +1,17 @@ -// Copyright © 2020 Amazon Web Services -// 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. +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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; diff --git a/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/api/TestPubsubEndpointHMAC.java b/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/api/TestPubsubEndpointHMAC.java index 5627cbc10ce458d23c6a11096f1dc39318835dae..2624baffad719e8275ec1957bd7c9d8776903a17 100644 --- a/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/api/TestPubsubEndpointHMAC.java +++ b/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/api/TestPubsubEndpointHMAC.java @@ -1,16 +1,18 @@ -// Copyright © 2020 Amazon Web Services -// -// 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. +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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.Assert.assertEquals; diff --git a/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/FileTestUtils.java b/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/FileTestUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..228735972a92a98066445151e488299e5e8ad5a5 --- /dev/null +++ b/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/FileTestUtils.java @@ -0,0 +1,321 @@ +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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.subscriptions; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import com.amazonaws.services.sqs.model.Message; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; +import org.apache.commons.lang3.tuple.Pair; +import org.opengroup.osdu.core.common.model.entitlements.Acl; +import org.opengroup.osdu.core.common.model.file.LocationResponse; +import org.opengroup.osdu.core.common.model.http.DpsHeaders; +import org.opengroup.osdu.core.common.model.legal.Legal; +import org.opengroup.osdu.notification.util.AwsTestUtils; + +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 java.net.MalformedURLException; +import java.net.URL; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.time.Instant; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class FileTestUtils { + + private final DpsHeaders dpsHeaders; + private final Client restClient; + private final String baseUrl; + private final static String DATASET_KIND = "osdu:wks:dataset--File.Generic:1.0.0"; + private final ObjectMapper objectMapper = new ObjectMapper(); + + private static class NullTrustManager implements X509TrustManager { + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + @Override + public void checkClientTrusted(X509Certificate[] certs, String authType) { + } + + @Override + public void checkServerTrusted(X509Certificate[] certs, String authType) { + } + } + + private record FileMetadataResponse(String id) { + } + + public FileTestUtils(DpsHeaders headers) { + TrustManager[] trustAllCerts = new TrustManager[]{new NullTrustManager()}; + + try { + SSLContext sc = SSLContext.getInstance("TLS"); + sc.init(null, trustAllCerts, new SecureRandom()); + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + } catch (Exception e) { + } + restClient = Client.create(); + dpsHeaders = headers; + baseUrl = System.getProperty("FILE_URL", System.getenv("FILE_URL")); + assertNotEquals(null, baseUrl, "Must set the FILE_URL environment variable!"); + } + + /** + * Returns the expected message values for the given the legal tag name to use. + * @param legalTagName The legal tag name. + * @return The expected message values. Used to compare with the actual message values. + */ + public String uploadFile(String legalTagName) throws JsonProcessingException { + LocationResponse locationResponse = getFileLocation(); + String signedUrl = locationResponse.getLocation().get("SignedURL"); + assertNotEquals(null, signedUrl); + String fileSource = locationResponse.getLocation().get("FileSource"); + uploadTestFile(signedUrl); + return setFileMetadata(fileSource, legalTagName); + } + + private String getFileMetadataURL() { + try { + URL mergedURL = new URL(baseUrl + "/files/metadata"); + return mergedURL.toString(); + } catch (MalformedURLException e) { + fail("Failed to get file metadata URL"); + } + return null; + } + + private String getFileUploadURL() { + try { + URL mergedURL = new URL(baseUrl + "/files/uploadURL"); + return mergedURL.toString(); + } catch (MalformedURLException e) { + fail("Failed to get file upload URL"); + } + return null; + } + + private ClientResponse sendRequest(String url, String method, boolean addHeaders, Object body, MediaType contentType) { + WebResource resource = restClient.resource(url); + WebResource.Builder resourceBuilder = resource.getRequestBuilder(); + if (contentType != null) { + resourceBuilder.accept(contentType); + resourceBuilder.type(contentType); + } + if (addHeaders) { + dpsHeaders.getHeaders().forEach(resourceBuilder::header); + } + return (body == null) ? resourceBuilder.method(method, ClientResponse.class) : resourceBuilder.method(method, ClientResponse.class, body); + } + + private LocationResponse getFileLocation() throws JsonProcessingException { + ClientResponse response = sendRequest(getFileUploadURL(), "GET", true, null, null); + assertEquals(200, response.getStatus()); + String responseData = response.getEntity(String.class); + return objectMapper.readValue(responseData, LocationResponse.class); + } + + private void uploadTestFile(String url) { + ClientResponse response = sendRequest(url, "PUT", false, "Test file upload.", MediaType.MULTIPART_FORM_DATA_TYPE); + assertEquals(200, response.getStatus()); + } + + private JsonObject getFileMetadataData(String fileSource) { + JsonObject dataObject = new JsonObject(); + dataObject.addProperty("Endian", "BIG"); + dataObject.addProperty("Description", "Test file"); + dataObject.addProperty("TotalSize", "1048576"); + JsonObject fileSourceInfo = new JsonObject(); + fileSourceInfo.addProperty("FileSource", fileSource); + fileSourceInfo.addProperty("Name", "1234"); + fileSourceInfo.addProperty("PreloadFilePath", "gs://osdu-cicd-epam-persistent-area/c3af38c1-654d-47a0-a3e6-9e94c32add84/b62b104f843142f49ee6d747e6bdd49d"); + fileSourceInfo.addProperty("PreloadFileCreateUser", "user1"); + fileSourceInfo.addProperty("PreloadFileModifyDate", "mar 11"); + fileSourceInfo.addProperty("PreloadFileModifyUser", "mar 11"); + JsonObject datasetProperties = new JsonObject(); + datasetProperties.add("FileSourceInfo", fileSourceInfo); + dataObject.add("DatasetProperties", datasetProperties); + return dataObject; + } + + private JsonArray getJsonArrayFromStringArray(Iterable<String> input) { + JsonArray jsonArray = new JsonArray(); + for (String str : input) { + jsonArray.add(str); + } + return jsonArray; + } + + private JsonObject getFileMetadataBase(String legalTagName) { + Pair<Acl, Legal> aclLegalPair = RecordUtils.getAclAndLegal(RecordUtils.getDefaultAcls(true), legalTagName, "US"); + JsonObject jsonAcl = new JsonObject(); + Acl acl = aclLegalPair.getLeft(); + jsonAcl.add("viewers", getJsonArrayFromStringArray(Arrays.asList(acl.viewers))); + jsonAcl.add("owners", getJsonArrayFromStringArray(Arrays.asList(acl.owners))); + + Legal legal = aclLegalPair.getRight(); + JsonObject jsonLegal = new JsonObject(); + jsonLegal.add("legaltags", getJsonArrayFromStringArray(legal.getLegaltags())); + jsonLegal.add("otherRelevantDataCountries", getJsonArrayFromStringArray(legal.getOtherRelevantDataCountries())); + jsonLegal.addProperty("status", "compliant"); + + JsonObject fileMetadata = new JsonObject(); + fileMetadata.add("acl", jsonAcl); + fileMetadata.add("legal", jsonLegal); + return fileMetadata; + } + + private JsonObject getFileMetadata(String fileSource, String legalTagName) { + JsonObject fileMetadata = getFileMetadataBase(legalTagName); + fileMetadata.addProperty("createUser", "osdu-community-sa-airflow@nice-etching-277309.iam.gserviceaccount.com"); + fileMetadata.addProperty("createTime", "2021-02-22T18:50:47.498Z"); + fileMetadata.addProperty("modifyUser", "osdu-community-sa-airflow@nice-etching-277309.iam.gserviceaccount.com"); + fileMetadata.addProperty("modifyTime", "2021-02-22T21:13:10.587Z"); + fileMetadata.addProperty("kind", DATASET_KIND); + + JsonObject dataObject = getFileMetadataData(fileSource); + fileMetadata.add("data", dataObject); + + return fileMetadata; + } + + private String setFileMetadata(String fileSource, String legalTagName) throws JsonProcessingException { + JsonObject fileMetadata = getFileMetadata(fileSource, legalTagName); + + ClientResponse response = sendRequest(getFileMetadataURL(), "POST", true, fileMetadata.toString(), null); + assertEquals(201, response.getStatus()); + String responseData = response.getEntity(String.class); + return objectMapper.readValue(responseData, FileMetadataResponse.class).id(); + } + + private void compareVersionIdWithExpected(String fileId, Object versionId, Instant started, Instant ended) { + assertNotEquals(null, versionId); + assertTrue(versionId instanceof String); + String versionString = versionId.toString(); + assertTrue(versionString.startsWith(fileId)); + String versionIdString = versionString.substring(fileId.length() + 1); + long versionIdMicros = Long.parseLong(versionIdString); + final long MICROS_PER_SECOND = 1000000; + final long NANOS_PER_MICRO = 1000; + long versionIdNanos = (versionIdMicros % MICROS_PER_SECOND) * NANOS_PER_MICRO; + long versionIdSeconds = versionIdMicros / MICROS_PER_SECOND; + Instant versionIdInstant = Instant.ofEpochSecond(versionIdSeconds, versionIdNanos); + assertTrue(versionIdInstant.isAfter(started)); + assertTrue(versionIdInstant.isBefore(ended)); + } + + private void compareTimestamp(Object timestampObj, Instant started, Instant ended) { + assertNotEquals(null, timestampObj); + assertTrue(timestampObj instanceof Number); + Instant instantTs = Instant.ofEpochMilli(((Number) timestampObj).longValue()); + assertTrue(instantTs.isAfter(started)); + assertTrue(instantTs.isBefore(ended)); + } + + private void checkDatasetDetails(Map<String, Object> properties, String fileId, Instant started, Instant ended) { + assertEquals(fileId, properties.get("datasetId")); + compareVersionIdWithExpected(fileId, properties.get("datasetVersionId"), started, ended); + assertEquals("FILE", properties.get("datasetType").toString()); + Object recordCount = properties.get("recordCount"); + assertTrue(recordCount instanceof Number); + assertEquals(1, recordCount); + compareTimestamp(properties.get("timestamp"), started, ended); + } + + private void checkInProgressStatus(Map<String, Object> properties, Instant started, Instant ended) { + Object errorCode = properties.get("errorCode"); + assertNotEquals(null, errorCode); + assertTrue(errorCode instanceof Number); + assertEquals(0, errorCode); + assertEquals(dpsHeaders.getUserId(), properties.get("userEmail")); + compareTimestamp(properties.get("timestamp"), started, ended); + Object message = properties.get("message"); + assertNotEquals(null, message); + assertTrue(message instanceof String); + } + + private void checkSuccessStatus(Map<String, Object> properties, String fileId, Instant started, Instant ended) { + checkInProgressStatus(properties, started, ended); + assertEquals(fileId, properties.get("recordId")); + compareVersionIdWithExpected(fileId, properties.get("recordIdVersion"), started, ended); + } + + public void compareMessagesWithExpected(String fileId, List<Message> receivedMessages, Instant started) throws Exception { + Instant ended = Instant.now(); + assertEquals("Expect exactly 3 messages: dataset sync start, dataset sync end, and dataset details", 3, receivedMessages.size()); + String correlationId = null; + boolean syncStartFound = false; + boolean syncEndFound = false; + boolean datasetDetailsFound = false; + for (Message message : receivedMessages) { + FileMessage fileMessage = AwsTestUtils.unwrapFirstMessage(message, FileMessage[].class); + Map<String, Object> properties = fileMessage.properties(); + if (correlationId == null) { + correlationId = properties.get("correlationId").toString(); + } else { + assertEquals(correlationId, properties.get("correlationId").toString()); + } + + + if (fileMessage.kind().equals("datasetDetails")) { + assertFalse(datasetDetailsFound); + datasetDetailsFound = true; + checkDatasetDetails(properties, fileId, started, ended); + } else if (fileMessage.kind().equals("status")) { + Object status = properties.get("status"); + Object stage = properties.get("stage"); + assertNotEquals(null, status); + assertNotEquals(null, stage); + assertTrue(status instanceof String); + assertTrue(stage instanceof String); + assertEquals("DATASET_SYNC", stage); + if (status.equals("IN_PROGRESS")) { + assertFalse(syncStartFound); + syncStartFound = true; + checkInProgressStatus(properties, started, ended); + } else if (status.equals("SUCCESS")) { + assertFalse(syncEndFound); + syncEndFound = true; + checkSuccessStatus(properties, fileId, started, ended); + } else { + fail("Unexpected status: " + status); + } + } else { + fail("Unexpected kind: " + fileMessage.kind()); + } + } + } +} + +record FileMessage (String kind, Map<String, Object> properties) { +} diff --git a/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/LegalTagUtils.java b/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/LegalTagUtils.java index 43fc4e536ecb1349b78dad6af60039221b2417a2..a0d2c2584a0e9d024407f269f73cc5a7c7a67749 100644 --- a/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/LegalTagUtils.java +++ b/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/LegalTagUtils.java @@ -1,62 +1,101 @@ +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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.subscriptions; import static org.junit.Assert.assertEquals; -import org.apache.http.HttpStatus; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.sun.jersey.api.client.ClientResponse; +import org.opengroup.osdu.core.common.http.json.HttpResponseBodyMapper; +import org.opengroup.osdu.core.common.legal.ILegalProvider; +import org.opengroup.osdu.core.common.legal.LegalAPIConfig; +import org.opengroup.osdu.core.common.legal.LegalFactory; +import org.opengroup.osdu.core.common.model.http.DpsHeaders; +import org.opengroup.osdu.core.common.model.legal.LegalException; +import org.opengroup.osdu.core.common.model.legal.LegalTag; +import org.opengroup.osdu.core.common.model.legal.Properties; +import com.amazonaws.services.sqs.model.Message; +import org.opengroup.osdu.notification.util.AwsTestUtils; +import org.opengroup.osdu.notification.util.Config; import org.opengroup.osdu.notification.util.TestUtils; -import java.util.UUID; +import java.sql.Date; +import java.util.Collections; +import java.util.List; public class LegalTagUtils { - public static ClientResponse create(String legalTagName, String token, boolean isTestPartition) throws Exception { - return create("US", legalTagName, "2099-01-25", "Public Domain Data", token, isTestPartition); - } + private final ILegalProvider legalService; - protected static ClientResponse create(String countryOfOrigin, String name, String expDate, String dataType, String token, boolean isTestPartition) - throws Exception { - String body = getBody(countryOfOrigin, name, expDate, dataType); - ClientResponse response = StorageTestUtils.send(getLegalUrl(), "legaltags", "POST", StorageTestUtils.getHeaders(TenantUtils.getTenantName(isTestPartition), token, UUID.randomUUID().toString(), isTestPartition), body, - ""); + public LegalTagUtils(DpsHeaders dpsHeaders, HttpResponseBodyMapper responseBodyMapper) { + LegalAPIConfig legalConfig = LegalAPIConfig.builder().rootUrl(Config.Instance().LegalServicePath).build(); + LegalFactory legalFactory = new LegalFactory(legalConfig, responseBodyMapper); + legalService = legalFactory.create(dpsHeaders); + } - assertEquals(HttpStatus.SC_CREATED, response.getStatus()); - Thread.sleep(100); - return response; + public void addLegalTag(String name, String expDate) throws LegalException { + LegalTag legalTag = createLegalTag(name, expDate); + legalService.create(legalTag); } - public static ClientResponse delete(String legalTagName, String token, boolean isTestPartition) throws Exception { - return StorageTestUtils.send(getLegalUrl(), "legaltags/" + legalTagName, "DELETE", StorageTestUtils.getHeaders(TenantUtils.getTenantName(isTestPartition), token, UUID.randomUUID().toString(), isTestPartition), "", ""); + public void addLegalTag(String name) throws LegalException { + addLegalTag(name, "2099-01-25"); } - protected static String getLegalUrl() { - String legalUrl = System.getProperty("LEGAL_URL", System.getenv("LEGAL_URL")); - return legalUrl; + public LegalMessage deleteLegalTag(String name) throws LegalException { + legalService.delete(name); + LegalMessageElement element = new LegalMessageElement(TestUtils.getOsduTenant(), name, "incompliant"); + return new LegalMessage(Collections.singletonList(element)); } - protected static String getBody(String countryOfOrigin, String name, String expDate, String dataType) { + public void ensureDeleted(String name) { + try { + deleteLegalTag(name); + } catch (LegalException e) { + System.err.println(e.toString()); + } + } - JsonArray coo = new JsonArray(); - coo.add(countryOfOrigin); + public void assertFirstMessagesSimilar(LegalMessage expected, List<Message> receivedMessages) throws Exception { + LegalMessage legalMessage = AwsTestUtils.unwrapSingleFirst(receivedMessages, LegalMessage.class); + assertEquals(1, legalMessage.statusChangedTags().size()); + LegalMessageElement expectedElement = expected.statusChangedTags().get(0); + LegalMessageElement actualElement = legalMessage.statusChangedTags().get(0); + assertEquals(expectedElement.dataPartitionId(), actualElement.dataPartitionId()); + assertEquals(expectedElement.changedTagName(), actualElement.changedTagName()); + assertEquals(expectedElement.changedTagStatus(), actualElement.changedTagStatus()); + } - JsonObject properties = new JsonObject(); - properties.add("countryOfOrigin", coo); - properties.addProperty("contractId", "A1234"); - properties.addProperty("expirationDate", expDate); - properties.addProperty("dataType", dataType); - properties.addProperty("originator", "MyCompany"); - properties.addProperty("securityClassification", "Public"); - properties.addProperty("exportClassification", "EAR99"); - properties.addProperty("personalData", "No Personal Data"); + private LegalTag createLegalTag(String name, String expDate) { + LegalTag legalTag = new LegalTag(); + legalTag.setName(name); + legalTag.setDescription(String.format("test for %s", name)); + Properties legalProps = new Properties(); + legalProps.setCountryOfOrigin(Collections.singletonList("US")); + legalProps.setContractId("A1234"); + legalProps.setDataType("Public Domain Data"); + legalProps.setExpirationDate(Date.valueOf(expDate)); + legalProps.setOriginator("MyCompany"); + legalProps.setSecurityClassification("Public"); + legalProps.setExportClassification("EAR99"); + legalProps.setPersonalData("No Personal Data"); + legalTag.setProperties(legalProps); + return legalTag; + } +} - JsonObject tag = new JsonObject(); - tag.addProperty("name", name); - tag.addProperty("description", "test for " + name); - tag.add("properties", properties); +record LegalMessage(List<LegalMessageElement> statusChangedTags) { +} - return tag.toString(); - } +record LegalMessageElement(String dataPartitionId, String changedTagName, String changedTagStatus) { } diff --git a/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/RecordUtils.java b/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/RecordUtils.java index 4c7516521b60be54f03de9e533b9912c397c3a84..d988ff977b11fb47cd41ade392dd54e23e3b61e0 100644 --- a/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/RecordUtils.java +++ b/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/RecordUtils.java @@ -1,79 +1,109 @@ +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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.subscriptions; import com.google.gson.JsonArray; -import com.google.gson.JsonObject; +import org.apache.commons.lang3.tuple.Pair; import org.opengroup.osdu.core.common.Constants; +import org.opengroup.osdu.core.common.model.entitlements.Acl; +import org.opengroup.osdu.core.common.model.legal.Legal; +import org.opengroup.osdu.core.common.model.storage.Record; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; public class RecordUtils { private static final String domain = System.getProperty("DOMAIN", System.getenv("DOMAIN")); - public static String createJsonRecordWithReference(int recordsCount, String id, String kind, String legalTag, String fromCrs, String conversionType, boolean isTestPartition) { + public static Record[] createRecordsWithReference(int recordsCount, String id, String kind, String legalTag, String fromCrs, String conversionType, boolean isTestPartition) { - JsonArray records = new JsonArray(); + Record[] records = new Record[recordsCount]; for (int i = 0; i < recordsCount; i++) { - JsonObject data = new JsonObject(); - data.addProperty("X", 16.00); - data.addProperty("Y", 10.00); - data.addProperty("Z", 0.0); + Map<String, Object> data = new HashMap<>(); + data.put("X", 16.00); + data.put("Y", 10.00); + data.put("Z", 0.0); JsonArray propertyNames = new JsonArray(); propertyNames.add("X"); propertyNames.add("Y"); propertyNames.add("Z"); - JsonObject meta = new JsonObject(); - meta.addProperty(Constants.KIND, conversionType); - meta.addProperty(Constants.PERSISTABLE_REFERENCE, fromCrs); - meta.add(Constants.PROPERTY_NAMES, propertyNames); + Map<String, Object> meta = new HashMap<>(); + meta.put(Constants.KIND, conversionType); + meta.put(Constants.PERSISTABLE_REFERENCE, fromCrs); + meta.put(Constants.PROPERTY_NAMES, propertyNames); - JsonArray metaBlocks = new JsonArray(); - metaBlocks.add(meta); + Map<String, Object>[] metaBlocks = new Map[1]; + metaBlocks[0] = meta; - JsonObject record = getRecordWithInputData(id + i, kind, legalTag, data, isTestPartition); - record.add(Constants.META, metaBlocks); + Record record = getRecordWithInputData(id + i, kind, legalTag, data, isTestPartition); + record.setMeta(metaBlocks); - records.add(record); + records[i] = record; } - return records.toString(); + return records; } - private static JsonObject getRecordWithInputData(String id, String kind, String legalTag, JsonObject data, boolean isTestPartition) { - JsonObject record = getDefaultRecord(id, kind, legalTag, isTestPartition); - record.add("data", data); + private static Record getRecordWithInputData(String id, String kind, String legalTag, Map<String, Object> data, boolean isTestPartition) { + Record record = getDefaultRecord(id, kind, legalTag, isTestPartition); + record.setData(data); return record; } - private static JsonObject getDefaultRecord(String id, String kind, String legalTag, boolean isTestPartition) { - JsonArray acls = new JsonArray(); - acls.add(String.format("data.test1@%s", getAclSuffix(isTestPartition))); - return getDefaultRecordFromAcl(id, kind, legalTag, acls); + public static String[] getDefaultAcls(boolean isTestPartition) { + return new String[]{String.format("data.test1@%s", getAclSuffix(isTestPartition))}; } - private static JsonObject getDefaultRecordFromAcl(String id, String kind, String legalTag, JsonArray acls) { - JsonObject acl = new JsonObject(); - acl.add("viewers", acls); - acl.add("owners", acls); + private static Record getDefaultRecord(String id, String kind, String legalTag, boolean isTestPartition) { + return getDefaultRecordFromAcl(id, kind, legalTag, getDefaultAcls(isTestPartition)); + } - JsonArray tags = new JsonArray(); - tags.add(legalTag); + private static Record getDefaultRecordFromAcl(String id, String kind, String legalTag, String[] acls) { + Pair<Acl, Legal> pair = getAclAndLegal(acls, legalTag, "BR"); - JsonArray ordcJson = new JsonArray(); - ordcJson.add("BR"); + Record record = new Record(); + record.setAcl(pair.getLeft()); + record.setLegal(pair.getRight()); + record.setId(id); + record.setKind(kind); + return record; + } - JsonObject legal = new JsonObject(); - legal.add("legaltags", tags); - legal.add("otherRelevantDataCountries", ordcJson); + public static Pair<Acl, Legal> getAclAndLegal(String[] acls, String legalTags, String... countries) { + Acl acl = new Acl(); + acl.setOwners(acls); + acl.setViewers(acls); - JsonObject record = new JsonObject(); - record.addProperty("id", id); - record.addProperty("kind", kind); - record.add("acl", acl); - record.add("legal", legal); - return record; + Set<String> ordc = new HashSet<>(); + Collections.addAll(ordc, countries); + Set<String> tags = new HashSet<>(); + tags.add(legalTags); + + Legal legal = new Legal(); + legal.setLegaltags(tags); + legal.setOtherRelevantDataCountries(ordc); + + return Pair.of(acl, legal); } public static String getAclSuffix(boolean isTestPartition) { diff --git a/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/StorageTestUtils.java b/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/StorageTestUtils.java index fd7a216d0a7b19ea6265eab24b2610e9b8b5895c..ca652f413c256efc0a6747ce68534eced2101346 100644 --- a/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/StorageTestUtils.java +++ b/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/StorageTestUtils.java @@ -1,121 +1,70 @@ +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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.subscriptions; -import com.sun.jersey.api.client.Client; -import com.sun.jersey.api.client.ClientResponse; -import com.sun.jersey.api.client.WebResource; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import com.amazonaws.services.sqs.model.Message; +import org.opengroup.osdu.core.common.http.json.HttpResponseBodyMapper; import org.opengroup.osdu.core.common.model.http.DpsHeaders; +import org.opengroup.osdu.core.common.model.storage.Record; +import org.opengroup.osdu.core.common.model.storage.StorageException; +import org.opengroup.osdu.core.common.storage.IStorageService; +import org.opengroup.osdu.core.common.storage.StorageAPIConfig; +import org.opengroup.osdu.core.common.storage.StorageFactory; +import org.opengroup.osdu.notification.util.AwsTestUtils; +import org.opengroup.osdu.notification.util.Config; -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 java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.net.HttpURLConnection; -import java.net.URL; -import java.security.SecureRandom; -import java.security.cert.X509Certificate; -import java.util.*; +import java.util.HashSet; +import java.util.List; public class StorageTestUtils { - public static ClientResponse send(String path, String httpMethod, Map<String, String> headers, String requestBody, - String query) throws Exception { - - log(httpMethod, StorageTestUtils.getApiPath(path + query), headers, requestBody); - Client client = StorageTestUtils.getClient(); - - WebResource webResource = client.resource(StorageTestUtils.getApiPath(path + query)); - - WebResource.Builder builder = webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON); - headers.forEach(builder::header); - - return builder.method(httpMethod, ClientResponse.class, requestBody); - } - - public static ClientResponse send(String url, String path, String httpMethod, Map<String, String> headers, - String requestBody, String query) throws Exception { - - log(httpMethod, url + path, headers, requestBody); - Client client = StorageTestUtils.getClient(); - - WebResource webResource = client.resource(url + path); - WebResource.Builder builder = webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON); - headers.forEach(builder::header); - - 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); - } + private final IStorageService storageService; + private final HashSet<String> allowedOps = new HashSet<>(); - public static String getApiPath(String api) throws Exception { - String baseUrl = System.getProperty("STORAGE_URL", System.getenv("STORAGE_URL")); - URL mergedURL = new URL(baseUrl + api); - System.out.println(mergedURL.toString()); - return mergedURL.toString(); + public StorageTestUtils(DpsHeaders headers, HttpResponseBodyMapper mapper) { + StorageAPIConfig config = StorageAPIConfig.builder().rootUrl(Config.Instance().StorageServicePath).build(); + StorageFactory subscriptionFactory = new StorageFactory(config, mapper); + storageService = subscriptionFactory.create(headers); + allowedOps.add("create"); + allowedOps.add("delete"); } - 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) { - } - allowMethods("PATCH"); - return Client.create(); + protected static final String PERSISTABLE_REFERENCE = "%7B%22LB_CRS%22%3A%22%257B%2522WKT%2522%253A%2522PROJCS%255B%255C%2522British_National_Grid%255C%2522%252CGEOGCS%255B%255C%2522GCS_OSGB_1936%255C%2522%252CDATUM%255B%255C%2522D_OSGB_1936%255C%2522%252CSPHEROID%255B%255C%2522Airy_1830%255C%2522%252C6377563.396%252C299.3249646%255D%255D%252CPRIMEM%255B%255C%2522Greenwich%255C%2522%252C0.0%255D%252CUNIT%255B%255C%2522Degree%255C%2522%252C0.0174532925199433%255D%255D%252CPROJECTION%255B%255C%2522Transverse_Mercator%255C%2522%255D%252CPARAMETER%255B%255C%2522False_Easting%255C%2522%252C400000.0%255D%252CPARAMETER%255B%255C%2522False_Northing%255C%2522%252C-100000.0%255D%252CPARAMETER%255B%255C%2522Central_Meridian%255C%2522%252C-2.0%255D%252CPARAMETER%255B%255C%2522Scale_Factor%255C%2522%252C0.9996012717%255D%252CPARAMETER%255B%255C%2522Latitude_Of_Origin%255C%2522%252C49.0%255D%252CUNIT%255B%255C%2522Meter%255C%2522%252C1.0%255D%252CAUTHORITY%255B%255C%2522EPSG%255C%2522%252C27700%255D%255D%2522%252C%2522Type%2522%253A%2522LBCRS%2522%252C%2522EngineVersion%2522%253A%2522PE_10_3_1%2522%252C%2522AuthorityCode%2522%253A%257B%2522Authority%2522%253A%2522EPSG%2522%252C%2522Code%2522%253A%252227700%2522%257D%252C%2522Name%2522%253A%2522British_National_Grid%2522%257D%22%2C%22TRF%22%3A%22%257B%2522WKT%2522%253A%2522GEOGTRAN%255B%255C%2522OSGB_1936_To_WGS_1984_Petroleum%255C%2522%252CGEOGCS%255B%255C%2522GCS_OSGB_1936%255C%2522%252CDATUM%255B%255C%2522D_OSGB_1936%255C%2522%252CSPHEROID%255B%255C%2522Airy_1830%255C%2522%252C6377563.396%252C299.3249646%255D%255D%252CPRIMEM%255B%255C%2522Greenwich%255C%2522%252C0.0%255D%252CUNIT%255B%255C%2522Degree%255C%2522%252C0.0174532925199433%255D%255D%252CGEOGCS%255B%255C%2522GCS_WGS_1984%255C%2522%252CDATUM%255B%255C%2522D_WGS_1984%255C%2522%252CSPHEROID%255B%255C%2522WGS_1984%255C%2522%252C6378137.0%252C298.257223563%255D%255D%252CPRIMEM%255B%255C%2522Greenwich%255C%2522%252C0.0%255D%252CUNIT%255B%255C%2522Degree%255C%2522%252C0.0174532925199433%255D%255D%252CMETHOD%255B%255C%2522Position_Vector%255C%2522%255D%252CPARAMETER%255B%255C%2522X_Axis_Translation%255C%2522%252C446.448%255D%252CPARAMETER%255B%255C%2522Y_Axis_Translation%255C%2522%252C-125.157%255D%252CPARAMETER%255B%255C%2522Z_Axis_Translation%255C%2522%252C542.06%255D%252CPARAMETER%255B%255C%2522X_Axis_Rotation%255C%2522%252C0.15%255D%252CPARAMETER%255B%255C%2522Y_Axis_Rotation%255C%2522%252C0.247%255D%252CPARAMETER%255B%255C%2522Z_Axis_Rotation%255C%2522%252C0.842%255D%252CPARAMETER%255B%255C%2522Scale_Difference%255C%2522%252C-20.489%255D%252CAUTHORITY%255B%255C%2522EPSG%255C%2522%252C1314%255D%255D%2522%252C%2522Type%2522%253A%2522STRF%2522%252C%2522EngineVersion%2522%253A%2522PE_10_3_1%2522%252C%2522AuthorityCode%2522%253A%257B%2522Authority%2522%253A%2522EPSG%2522%252C%2522Code%2522%253A%25221314%2522%257D%252C%2522Name%2522%253A%2522OSGB_1936_To_WGS_1984_Petroleum%2522%257D%22%2C%22Type%22%3A%22EBCRS%22%2C%22EngineVersion%22%3A%22PE_10_3_1%22%2C%22Name%22%3A%22OSGB+1936+*+UKOOA-Pet+%2F+British+National+Grid+%5B27700%2C1314%5D%22%2C%22AuthorityCode%22%3A%7B%22Authority%22%3A%22MyCompany%22%2C%22Code%22%3A%2227700006%22%7D%7D"; + private static final String RECORD_ID_PREFIX_TEST = TenantUtils.getTenantName(true) + ":query:"; + private static final long NOW = System.currentTimeMillis(); + private static final String KIND_TEST = TenantUtils.getTenantName(true) + ":ds:query:1.0." + NOW; + public StorageMessage createAndPutRecord(String correlationId, String legalTag) throws StorageException { + String recordId = RECORD_ID_PREFIX_TEST + correlationId; + Record[] records = RecordUtils.createRecordsWithReference(1, recordId, KIND_TEST, legalTag, PERSISTABLE_REFERENCE, "CRS", true); + storageService.upsertRecord(records); + // We append the index in RecordUtils to ensure the IDs are unique. Maybe we don't need to do that. + return new StorageMessage(records[0].getId(), KIND_TEST, "create"); } - private static void allowMethods(String... methods) { - try { - Field methodsField = HttpURLConnection.class.getDeclaredField("methods"); - - Field modifiersField = Field.class.getDeclaredField("modifiers"); - modifiersField.setAccessible(true); - modifiersField.setInt(methodsField, methodsField.getModifiers() & ~Modifier.FINAL); - - methodsField.setAccessible(true); - - String[] oldMethods = (String[]) methodsField.get(null); - Set<String> methodsSet = new LinkedHashSet<>(Arrays.asList(oldMethods)); - methodsSet.addAll(Arrays.asList(methods)); - String[] newMethods = methodsSet.toArray(new String[0]); - - methodsField.set(null/*static field*/, newMethods); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new IllegalStateException(e); - } + public void assertFirstMessagesSimilar(StorageMessage expected, List<Message> receivedMessages) throws Exception { + System.out.printf("Total received messages: %d\n", receivedMessages.size()); + StorageMessage actual = AwsTestUtils.unwrapFirst(receivedMessages, StorageMessage[].class); + assertTrue("Expect the op to be in the \"created\" or \"deleted\" set.", allowedOps.contains(actual.op())); + assertEquals(expected.kind(), actual.kind()); + assertEquals(expected.id(), actual.id()); } +} - public static Map<String, String> getHeaders(String tenantName, String token, String correlationId, boolean isTestPartition) { - Map<String, String> headers = new HashMap<>(); - if(tenantName == null || tenantName.isEmpty()) { - tenantName = TenantUtils.getTenantName(false); - } - headers.put("data-partition-id", TenantUtils.getTenantName(isTestPartition)); - headers.put("Authorization", token); +record StorageMessage(String id, String kind, String op) { - System.out.printf("Using correlation-id for the request: %s \n", correlationId); - headers.put("correlation-id", correlationId); - return headers; - } } diff --git a/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/TenantUtils.java b/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/TenantUtils.java index 182461b8691c0f47a215b2ac9f38376e3bafaeb9..d0427ae8c9c30e85ad63456b7ca66a464967c2dc 100644 --- a/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/TenantUtils.java +++ b/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/TenantUtils.java @@ -1,3 +1,17 @@ +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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.subscriptions; public class TenantUtils { diff --git a/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/TestNotificationsEndpoint.java b/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/TestNotificationsEndpoint.java index e5b9b32ce21bdb80172070c230776c5f2a645fb6..858d7c1c6c3dc2163bcb7b975eb9d34e6e91b2ad 100644 --- a/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/TestNotificationsEndpoint.java +++ b/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/TestNotificationsEndpoint.java @@ -1,12 +1,37 @@ +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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.subscriptions; -import com.sun.jersey.api.client.ClientResponse; +import com.amazonaws.services.simplesystemsmanagement.AWSSimpleSystemsManagement; +import com.amazonaws.services.simplesystemsmanagement.AWSSimpleSystemsManagementClientBuilder; +import com.amazonaws.services.simplesystemsmanagement.model.GetParametersRequest; +import com.amazonaws.services.simplesystemsmanagement.model.GetParametersResult; +import com.amazonaws.services.sqs.AmazonSQS; +import com.amazonaws.services.sqs.AmazonSQSClientBuilder; +import com.amazonaws.services.sqs.model.Message; +import com.amazonaws.services.sqs.model.PurgeQueueRequest; +import com.amazonaws.services.sqs.model.ReceiveMessageRequest; +import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.After; -import org.junit.Before; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; +import org.opengroup.osdu.core.common.http.json.HttpResponseBodyMapper; 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.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; @@ -14,125 +39,394 @@ import org.opengroup.osdu.core.common.notification.SubscriptionException; import org.opengroup.osdu.core.common.notification.SubscriptionFactory; import org.opengroup.osdu.notification.util.*; +import java.time.Instant; +import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; import java.util.HashMap; +import java.util.HashSet; +import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; -public class TestNotificationsEndpoint extends TestBase { +public class TestNotificationsEndpoint { - private String subscriptionId_TestPartition; - private ISubscriptionService awssubscriptionService; - private TestUtils testUtils; - private static SubscriptionFactory awsfactory; + private static ISubscriptionService subscriptionService; + private static StorageTestUtils storageUtils; + private static LegalTagUtils legalUtils; + private static FileTestUtils fileUtils; - private static final long NOW = System.currentTimeMillis(); - private static final String RECORD_ID_PREFIX_TEST = TenantUtils.getTenantName(true) + ":query:"; - private static final String KIND_TEST = TenantUtils.getTenantName(true) + ":ds:query:1.0." + NOW; - private static final String LEGAL_TAG = TenantUtils.getTenantName(false) + "-storage-" + System.currentTimeMillis(); - private static final String LEGAL_TAG_TEST = TenantUtils.getTenantName(true) + "-storage-" + System.currentTimeMillis(); + private static final int FILE_QUEUE_NUM = 0; + private static final int INDEXER_STORAGE_INDEXER_QUEUE_NUM = 0; + private static final int INDEXER_STORAGE_STORAGE_QUEUE_NUM = 1; + private static final int LEGAL_STORAGE_STORAGE_QUEUE_NUM = 0; + private static final int LEGAL_STORAGE_LEGAL_QUEUE_NUM = 1; + private static final int REQUIRED_QUEUES = 2; - protected static final String PARTITION_TEST = "opendes"; + protected static final String PARTITION_TEST = "int-test-notification"; + private static final String FILE_SERVICE_NAME = "file"; + private static final String INDEXER_SERVICE_NAME = "indexer"; + private static final String LEGAL_SERVICE_NAME = "legal"; + private static final String STORAGE_SERVICE_NAME = "storage"; + private final Object mutex = new Object(); + private static final String FILE_LEGAL_TAG_NAME = String.format("%s-file-testing-%d", TenantUtils.getTenantName(true), System.currentTimeMillis()); + private static final String INDEXER_LEGAL_TAG_NAME = String.format("%s-indexer-testing-%d", TenantUtils.getTenantName(true), System.currentTimeMillis()); + private static final String STORAGE_LEGAL_TAG_NAME = String.format("%s-legal-storage-%d", TenantUtils.getTenantName(true), System.currentTimeMillis()); + + private static AmazonSQS sqsClient; + + private static final Map<String, String> serviceTopicLookup = new HashMap<>(); + + private final static ObjectMapper objectMapper = new ObjectMapper(); + + private static final int MAX_RETRIES = 5; + private static final int MAX_POLL_TIME = 120; + + + private static class PushQueue { + private final String queueUrl; + private final String endpointUrl; + private final int queueNum; + private final Set<String> subscriptions = new HashSet<>(); + + private final List<Message> messages = new ArrayList<>(); + + public PushQueue(String queueUrl, String endpointUrl, int queueNum) { + this.queueUrl = queueUrl; + this.endpointUrl = endpointUrl; + this.queueNum = queueNum; + } + + public void register(String serviceName) throws SubscriptionException, InterruptedException { + String osduTopic = serviceTopicLookup.get(serviceName); + assertNotEquals(null, osduTopic); + + Subscription subscription = new Subscription(); + subscription.setPushEndpoint(endpointUrl); + subscription.setSecret(subscriptionSecret); + subscription.setId(String.format("%s-%d", osduTopic, queueNum)); + subscription.setName(String.format("%s on queue %d", osduTopic, queueNum)); + subscription.setDescription(String.format("Testing service %s osduTopic by using push endpoint to queue %d.", serviceName, queueNum)); + subscription.setTopic(osduTopic); + String subscriptionId = null; + int i = 0; + boolean errored = true; + while (errored) { + try { + subscriptionId = subscriptionService.create(subscription).getId(); + i = 0; + errored = false; + } catch (SubscriptionException e) { + if (i >= MAX_RETRIES || e.getHttpResponse().getResponseCode() != 400) + throw e; + Thread.sleep((int) (200 * (2 << i))); + } + ++i; + } + subscriptions.add(subscriptionId); + } + + public void pollMessages(int numMessages, int timeout) { + messages.clear(); + ReceiveMessageRequest request = new ReceiveMessageRequest(); + request.setQueueUrl(queueUrl); + request.setMaxNumberOfMessages(numMessages); + final int MAX_TIMEOUT = 20; + request.setWaitTimeSeconds(MAX_TIMEOUT); + while (messages.size() < numMessages && timeout > MAX_TIMEOUT) { + messages.addAll(sqsClient.receiveMessage(request).getMessages()); + timeout -= MAX_TIMEOUT; + } + if (messages.size() < numMessages) + messages.addAll(sqsClient.receiveMessage(request.withWaitTimeSeconds(timeout)).getMessages()); + } + + public void pollMessages(int numMessages) { + pollMessages(numMessages, MAX_POLL_TIME); + } + + public List<Message> getMessages() { + return new ArrayList<>(messages); + } + + public void clearLocalMessages() { + messages.forEach(message -> sqsClient.deleteMessage(queueUrl, message.getReceiptHandle())); + messages.clear(); + } + + public void removeAllKnownSubscriptions() { + clearLocalMessages(); + subscriptions.forEach(TestNotificationsEndpoint::ensureSubscriptionDeleted); + subscriptions.clear(); + } + + public void purge() { + removeAllKnownSubscriptions(); + PurgeQueueRequest purgeQueueRequest = new PurgeQueueRequest(); + purgeQueueRequest.setQueueUrl(queueUrl); + sqsClient.purgeQueue(purgeQueueRequest); + } + + public void removeAllPotentialSubscriptions(Map<String, String> allTopics) { + allTopics.forEach((key, value) -> { + String id = Base64.getEncoder().encodeToString((value + PARTITION_TEST + endpointUrl).getBytes()); + ensureSubscriptionDeleted(id); + }); + } + } + + private record IndexerProgress(int statusCode, String[] trace, String lastUpdateTime) { + } + + private record IndexerMessage(String id, String kind, String operationType, String status, IndexerProgress indexProgress) { + } + + + private static String getEnv(String envVariableName) { + String envVar = System.getenv(envVariableName); + if (envVar == null) { + throw new IllegalArgumentException(String.format("Must have environment variable '%s' set!", envVariableName)); + } + + return envVar; + } + + private static List<PushQueue> queues; + + private static Secret subscriptionSecret; - protected static final String PERSISTABLE_REFERENCE = "%7B%22LB_CRS%22%3A%22%257B%2522WKT%2522%253A%2522PROJCS%255B%255C%2522British_National_Grid%255C%2522%252CGEOGCS%255B%255C%2522GCS_OSGB_1936%255C%2522%252CDATUM%255B%255C%2522D_OSGB_1936%255C%2522%252CSPHEROID%255B%255C%2522Airy_1830%255C%2522%252C6377563.396%252C299.3249646%255D%255D%252CPRIMEM%255B%255C%2522Greenwich%255C%2522%252C0.0%255D%252CUNIT%255B%255C%2522Degree%255C%2522%252C0.0174532925199433%255D%255D%252CPROJECTION%255B%255C%2522Transverse_Mercator%255C%2522%255D%252CPARAMETER%255B%255C%2522False_Easting%255C%2522%252C400000.0%255D%252CPARAMETER%255B%255C%2522False_Northing%255C%2522%252C-100000.0%255D%252CPARAMETER%255B%255C%2522Central_Meridian%255C%2522%252C-2.0%255D%252CPARAMETER%255B%255C%2522Scale_Factor%255C%2522%252C0.9996012717%255D%252CPARAMETER%255B%255C%2522Latitude_Of_Origin%255C%2522%252C49.0%255D%252CUNIT%255B%255C%2522Meter%255C%2522%252C1.0%255D%252CAUTHORITY%255B%255C%2522EPSG%255C%2522%252C27700%255D%255D%2522%252C%2522Type%2522%253A%2522LBCRS%2522%252C%2522EngineVersion%2522%253A%2522PE_10_3_1%2522%252C%2522AuthorityCode%2522%253A%257B%2522Authority%2522%253A%2522EPSG%2522%252C%2522Code%2522%253A%252227700%2522%257D%252C%2522Name%2522%253A%2522British_National_Grid%2522%257D%22%2C%22TRF%22%3A%22%257B%2522WKT%2522%253A%2522GEOGTRAN%255B%255C%2522OSGB_1936_To_WGS_1984_Petroleum%255C%2522%252CGEOGCS%255B%255C%2522GCS_OSGB_1936%255C%2522%252CDATUM%255B%255C%2522D_OSGB_1936%255C%2522%252CSPHEROID%255B%255C%2522Airy_1830%255C%2522%252C6377563.396%252C299.3249646%255D%255D%252CPRIMEM%255B%255C%2522Greenwich%255C%2522%252C0.0%255D%252CUNIT%255B%255C%2522Degree%255C%2522%252C0.0174532925199433%255D%255D%252CGEOGCS%255B%255C%2522GCS_WGS_1984%255C%2522%252CDATUM%255B%255C%2522D_WGS_1984%255C%2522%252CSPHEROID%255B%255C%2522WGS_1984%255C%2522%252C6378137.0%252C298.257223563%255D%255D%252CPRIMEM%255B%255C%2522Greenwich%255C%2522%252C0.0%255D%252CUNIT%255B%255C%2522Degree%255C%2522%252C0.0174532925199433%255D%255D%252CMETHOD%255B%255C%2522Position_Vector%255C%2522%255D%252CPARAMETER%255B%255C%2522X_Axis_Translation%255C%2522%252C446.448%255D%252CPARAMETER%255B%255C%2522Y_Axis_Translation%255C%2522%252C-125.157%255D%252CPARAMETER%255B%255C%2522Z_Axis_Translation%255C%2522%252C542.06%255D%252CPARAMETER%255B%255C%2522X_Axis_Rotation%255C%2522%252C0.15%255D%252CPARAMETER%255B%255C%2522Y_Axis_Rotation%255C%2522%252C0.247%255D%252CPARAMETER%255B%255C%2522Z_Axis_Rotation%255C%2522%252C0.842%255D%252CPARAMETER%255B%255C%2522Scale_Difference%255C%2522%252C-20.489%255D%252CAUTHORITY%255B%255C%2522EPSG%255C%2522%252C1314%255D%255D%2522%252C%2522Type%2522%253A%2522STRF%2522%252C%2522EngineVersion%2522%253A%2522PE_10_3_1%2522%252C%2522AuthorityCode%2522%253A%257B%2522Authority%2522%253A%2522EPSG%2522%252C%2522Code%2522%253A%25221314%2522%257D%252C%2522Name%2522%253A%2522OSGB_1936_To_WGS_1984_Petroleum%2522%257D%22%2C%22Type%22%3A%22EBCRS%22%2C%22EngineVersion%22%3A%22PE_10_3_1%22%2C%22Name%22%3A%22OSGB+1936+*+UKOOA-Pet+%2F+British+National+Grid+%5B27700%2C1314%5D%22%2C%22AuthorityCode%22%3A%7B%22Authority%22%3A%22MyCompany%22%2C%22Code%22%3A%2227700006%22%7D%7D"; @BeforeClass - public static void classSetup() { + public static void classSetup() throws Exception { SubscriptionAPIConfig config = SubscriptionAPIConfig.builder().rootUrl(Config.Instance().RegisterServicePath).build(); - awsfactory = new SubscriptionFactory(config); + SubscriptionFactory subscriptionFactory = new SubscriptionFactory(config); + HttpResponseBodyMapper responseBodyMapper = new HttpResponseBodyMapper(objectMapper); + + + sqsClient = AmazonSQSClientBuilder.defaultClient(); + + getSubscriptionSecret(); + + // Set up the subscription service used by this test + AwsTestUtils testUtils = new AwsTestUtils(); + + DpsHeaders dpsHeaders = testUtils.getDpsHeaders(); + // Set up the legal service used by this test suite + storageUtils = new StorageTestUtils(dpsHeaders, responseBodyMapper); + legalUtils = new LegalTagUtils(dpsHeaders, responseBodyMapper); + subscriptionService = subscriptionFactory.create(dpsHeaders); + fileUtils = new FileTestUtils(dpsHeaders); + + getTopicNames(); + createQueues(); + purgeQueues(); + assertTrue(String.format("Must have at least %d Push Endpoint Queues to run this test!", REQUIRED_QUEUES), queues.size() >= REQUIRED_QUEUES); } - @Before - public void setup() throws Exception { - this.testUtils = new AwsTestUtils(); - Map<String, String> headers = new HashMap<>(); - headers.put(DpsHeaders.DATA_PARTITION_ID, TestUtils.getOsduTenant()); - headers.put(DpsHeaders.AUTHORIZATION, testUtils.getOpsToken()); - //hardcoding user here for 200 response tests. This is just initializing the subscription creation - headers.put("x-user-id", AwsConfig.getAWSCognitoUser()); + private static void getSubscriptionSecret() { + // Get the Push Endpoint Secret. Only one secret is used and shared across because otherwise, we would need to have a separate authorization for each queue, and warming up the + // lambda functions would need to + String pushEndpointSecret = getEnv("HMAC_SECRET"); + HmacSecret hmacSecret = new HmacSecret(); + hmacSecret.setValue(pushEndpointSecret); + subscriptionSecret = hmacSecret; + System.out.printf("TestNotificationsEndpoint.classSetup has HMAC Secret: %s\n", subscriptionSecret); + } - DpsHeaders dpsHeaders = DpsHeaders.createFromMap(headers); - awssubscriptionService = awsfactory.create(dpsHeaders); + private static void purgeQueues() throws InterruptedException { + queues.forEach(PushQueue::purge); + // Wait for the queues to be purged before continuing the tests. + Thread.sleep(60000); + } - try { - // Ensure that there is no previous subscription already registered - // Sometimes this can happen if previous tests didn't exit properly + private static void createQueues() { + // Create the Push Endpoint Queues to ensure the right notifications are sent to the right queues. + String numQueuesAsString = getEnv("PUSH_ENDPOINT_NUM_QUEUES"); + int numQueues = Integer.parseInt(numQueuesAsString); + queues = new ArrayList<>(numQueues); + for (int i = 0; i < numQueues; ++i) { + String endpointUrl = getEnv(String.format("PUSH_ENDPOINT_URL_%d", i)); + String queueUrl = getEnv(String.format("PUSH_ENDPOINT_QUEUE_%d", i)); + PushQueue queue = new PushQueue(queueUrl, endpointUrl, i); + queue.removeAllPotentialSubscriptions(serviceTopicLookup); + queues.add(queue); + } + } - // Sadly there is no method to delete a subscription from just name, so have - // to manually build the ID like this. - String subscriptionId = String.format("%s%s%s", - Config.Instance().Topic, - PARTITION_TEST, - Config.Instance().HMACPushUrl); - String encodedSubscriptionId = Base64.getEncoder().encodeToString(subscriptionId.getBytes()); + private static void getTopicNames() { + // Get the OSDU topics for each of the services that emit notifications. + String instanceName = getEnv("OSDU_INSTANCE_NAME"); + String[] services = new String[] {FILE_SERVICE_NAME, INDEXER_SERVICE_NAME, LEGAL_SERVICE_NAME, STORAGE_SERVICE_NAME}; + List<String> ssmNames = new ArrayList<>(services.length); + Map<String, String> parameterReverseLookup = new HashMap<>(services.length); + Arrays.stream(services).forEach(serviceName -> { + String ssmParam = String.format("/osdu/instances/%s/core/%s/osdu-topic-name", instanceName, serviceName); + ssmNames.add(ssmParam); + parameterReverseLookup.put(ssmParam, serviceName); + }); + AWSSimpleSystemsManagement ssm = AWSSimpleSystemsManagementClientBuilder.defaultClient(); + GetParametersRequest getParametersRequest = new GetParametersRequest().withNames(ssmNames); + GetParametersResult getParametersResult = ssm.getParameters(getParametersRequest); + getParametersResult.getParameters().forEach(parameter -> { + String serviceName = parameterReverseLookup.get(parameter.getName()); + serviceTopicLookup.put(serviceName, parameter.getValue()); + }); + } - awssubscriptionService.delete(encodedSubscriptionId); + private static void ensureSubscriptionDeleted(String subscriptionId) { + try { + subscriptionService.delete(subscriptionId); + } + catch (Exception e) { + // Don't care, because the subscription may or may not exist. + // If it doesn't exist, then this will erroneously error out if we don't catch it first. } - catch (Exception e) {} } @After - @Override public void tearDown() throws Exception { - LegalTagUtils.delete(LEGAL_TAG_TEST, testUtils.getOpsToken(), true); - LegalTagUtils.delete(LEGAL_TAG, testUtils.getOpsToken(), false); - this.testUtils = null; - } - - private void createResourceForTestParition() throws Exception { - //Create a new subscription to pub/sub - Subscription subscription = new Subscription(); - subscription.setName("Subscription-test-for-notification"); - subscription.setDescription("Subscription with test Partition for fetching notifications"); - subscription.setTopic(Config.Instance().Topic); - subscription.setPushEndpoint(Config.Instance().HMACPushUrl); - HmacSecret secret = new HmacSecret(); - secret.setValue(Config.Instance().hmacSecretValue); - - subscription.setSecret(secret); - try { - Subscription subscriptionCreated = awssubscriptionService.create(subscription); - System.out.println("Subscription created successfully"); - String notificationId = subscriptionCreated.getNotificationId(); - subscriptionId_TestPartition = subscriptionCreated.getId(); - Config.Instance().NotificationId = notificationId; - }catch (SubscriptionException e){ - System.out.println("Subscription exception inner response : " + e.getHttpResponse()); - throw e; + queues.forEach(PushQueue::removeAllKnownSubscriptions); + legalUtils.ensureDeleted(STORAGE_LEGAL_TAG_NAME); + legalUtils.ensureDeleted(INDEXER_LEGAL_TAG_NAME); + legalUtils.ensureDeleted(FILE_LEGAL_TAG_NAME); + Thread.sleep(10000); // Give time for the legal notifications to be sent... + queues.forEach(queue -> queue.removeAllPotentialSubscriptions(serviceTopicLookup)); + purgeQueues(); + } + + private List<List<Message>> pollForMessages(int timeout, int numMessages, PushQueue... queues) throws InterruptedException { + List<Thread> threads = new ArrayList<>(queues.length); + for (PushQueue queue : queues) { + Runnable pollMessagesRunnable = () -> queue.pollMessages(numMessages); + if (timeout >= 0) { + pollMessagesRunnable = () -> queue.pollMessages(numMessages, timeout); + } + Thread thread = new Thread(pollMessagesRunnable); + thread.start(); + threads.add(thread); + } + for (Thread thread : threads) { + thread.join(); } + List<List<Message>> messages = new ArrayList<>(queues.length); + for (PushQueue queue : queues) { + messages.add(queue.getMessages()); + } + return messages; } - private ClientResponse createStorageRecordForTestPartition(final String correlationId) throws Exception { - String recordId = RECORD_ID_PREFIX_TEST + UUID.randomUUID().toString(); - String jsonInput = RecordUtils.createJsonRecordWithReference(1, recordId, KIND_TEST, LEGAL_TAG_TEST, PERSISTABLE_REFERENCE, "CRS", true); - return StorageTestUtils.send("records", "PUT", StorageTestUtils.getHeaders(TenantUtils.getTenantName(true), testUtils.getAdminToken(), correlationId, true), jsonInput, ""); + private List<List<Message>> pollForMessages(PushQueue... queues) throws InterruptedException { + return pollForMessages(-1, 1, queues); } @Test - public void testVerifyNotificationReceived() throws Exception { - try { - LegalTagUtils.create(LEGAL_TAG_TEST, testUtils.getOpsToken(), true); - createResourceForTestParition(); - final String correlationId = UUID.randomUUID().toString(); - ClientResponse response = createStorageRecordForTestPartition(correlationId); - assertEquals(201, response.getStatus()); - //Executing notifications response to endpoints takes an upper bound of 120s. - Thread.sleep(120000); - - //Run Bash File to fetch logs from register endpoint and verify that notification was received - String bashFileToExecute = "src/test/java/org/opengroup/osdu/notification/subscriptions/verify_register-logs.sh " + correlationId; - - Process process = Runtime.getRuntime().exec(bashFileToExecute); - process.waitFor(); - - int exitValue = process.exitValue(); - assertEquals(exitValue, 0); - } catch (Exception e) { - throw e; - } finally { - awssubscriptionService.delete(subscriptionId_TestPartition); + public void test_File_Notifications_Received() throws Exception { + synchronized (mutex) { + PushQueue fileQueue = queues.get(FILE_QUEUE_NUM); + try { + fileQueue.register(FILE_SERVICE_NAME); + legalUtils.addLegalTag(FILE_LEGAL_TAG_NAME); + Instant start = Instant.now(); + String fileId = fileUtils.uploadFile(FILE_LEGAL_TAG_NAME); + + // Get Queue Messages + List<List<Message>> messagesLists = pollForMessages(-1, 3, fileQueue); + assertEquals(1, messagesLists.size()); + List<Message> fileSQSMessages = messagesLists.get(0); + + fileUtils.compareMessagesWithExpected(fileId, fileSQSMessages, start); + } catch (Exception e) { + System.err.println(e.toString()); + e.printStackTrace(); + throw e; + } finally { + legalUtils.ensureDeleted(FILE_LEGAL_TAG_NAME); + } + } + } + + @Test + @Ignore("On the pipeline, this integration test can take way more than 10 minutes, which is determined to be unrealistic.") + public void test_Indexer_Notifications_Received() throws Exception { + synchronized (mutex) { + PushQueue storageQueue = queues.get(INDEXER_STORAGE_STORAGE_QUEUE_NUM); + PushQueue indexerQueue = queues.get(INDEXER_STORAGE_INDEXER_QUEUE_NUM); + try { + indexerQueue.register(INDEXER_SERVICE_NAME); + storageQueue.register(STORAGE_SERVICE_NAME); + Instant start = Instant.now(); + + legalUtils.addLegalTag(INDEXER_LEGAL_TAG_NAME); + StorageMessage expectedStorageMessage = storageUtils.createAndPutRecord(UUID.randomUUID().toString(), INDEXER_LEGAL_TAG_NAME); + + // Get Queue Messages + List<List<Message>> messagesLists = pollForMessages(600, 1, storageQueue, indexerQueue); + assertEquals(2, messagesLists.size()); + List<Message> storageSQSMessages = messagesLists.get(0); + List<Message> indexerSQSMessages = messagesLists.get(1); + + Instant end = Instant.now(); + + storageUtils.assertFirstMessagesSimilar(expectedStorageMessage, storageSQSMessages); + IndexerMessage indexerMessage = AwsTestUtils.unwrapFirst(indexerSQSMessages, IndexerMessage[].class); + assertEquals(expectedStorageMessage.kind(), indexerMessage.kind()); + assertEquals(expectedStorageMessage.id(), indexerMessage.id()); + assertEquals("create", indexerMessage.operationType()); + assertEquals("WARN", indexerMessage.status()); + assertNotEquals(null, indexerMessage.indexProgress()); + assertEquals(200, indexerMessage.indexProgress().statusCode()); + Instant lastChanged = Instant.parse(indexerMessage.indexProgress().lastUpdateTime()); + assertTrue(lastChanged.isAfter(start) && lastChanged.isBefore(end)); + } catch (Exception e) { + System.err.println(e.toString()); + e.printStackTrace(); + throw e; + } finally { + legalUtils.ensureDeleted(INDEXER_LEGAL_TAG_NAME); + } + } + } + + @Test + public void test_LegalAndStorage_Notifications_Received() throws Exception { + synchronized (mutex) { + PushQueue legalQueue = queues.get(LEGAL_STORAGE_LEGAL_QUEUE_NUM); + PushQueue storageQueue = queues.get(LEGAL_STORAGE_STORAGE_QUEUE_NUM); + try { + legalQueue.register(LEGAL_SERVICE_NAME); + storageQueue.register(STORAGE_SERVICE_NAME); + + legalUtils.addLegalTag(STORAGE_LEGAL_TAG_NAME); + + final String correlationId = UUID.randomUUID().toString(); + StorageMessage expectedStorageMessage = storageUtils.createAndPutRecord(correlationId, STORAGE_LEGAL_TAG_NAME); + List<List<Message>> messagesLists = pollForMessages(storageQueue); + assertEquals(1, messagesLists.size()); + List<Message> storageSQSMessages = messagesLists.get(0); + storageUtils.assertFirstMessagesSimilar(expectedStorageMessage, storageSQSMessages); + storageQueue.clearLocalMessages(); + + LegalMessage expectedLegalMessage = legalUtils.deleteLegalTag(STORAGE_LEGAL_TAG_NAME); + + // Get Queue Messages + messagesLists = pollForMessages(storageQueue, legalQueue); + assertEquals(2, messagesLists.size()); + storageSQSMessages = messagesLists.get(0); + List<Message> legalSQSMessages = messagesLists.get(1); + + storageUtils.assertFirstMessagesSimilar(expectedStorageMessage, storageSQSMessages); + legalUtils.assertFirstMessagesSimilar(expectedLegalMessage, legalSQSMessages); + } catch (Exception e) { + System.err.println(e.toString()); + e.printStackTrace(); + throw e; + } finally { + legalUtils.ensureDeleted(STORAGE_LEGAL_TAG_NAME); + } } } } diff --git a/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/verify_register-logs.sh b/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/verify_register-logs.sh deleted file mode 100755 index bacda8d64af7d7f2aa14789f7e97b372158ad0b0..0000000000000000000000000000000000000000 --- a/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/subscriptions/verify_register-logs.sh +++ /dev/null @@ -1,9 +0,0 @@ -CORE_K8S_NAMESPACE="$AWS_SERVICE_NAMESPACE-core" -register_pod=$(kubectl get pods -n $CORE_K8S_NAMESPACE | grep "Running" | grep "os-register" | awk '{ print $1 }') -register_logs=$(kubectl logs $register_pod -n $CORE_K8S_NAMESPACE --since=2m) - -if echo $register_logs | grep $1; then - exit 0 -else - exit 1 -fi diff --git a/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/util/AwsTestUtils.java b/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/util/AwsTestUtils.java index d2c64bab0ba45d473ed115c4ca445b2d8a7b2a83..5a2df46ba141375f8fc35b5c7c06fdc567cb24e3 100644 --- a/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/util/AwsTestUtils.java +++ b/testing/notification-test-aws/src/test/java/org/opengroup/osdu/notification/util/AwsTestUtils.java @@ -15,13 +15,20 @@ package org.opengroup.osdu.notification.util; -import org.apache.commons.lang3.StringUtils; - -public class AwsTestUtils extends TestUtils{ +import static org.junit.Assert.assertTrue; +import com.amazonaws.services.sqs.model.Message; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.lang3.StringUtils; +import org.opengroup.osdu.core.common.model.http.DpsHeaders; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +public class AwsTestUtils extends TestUtils { AwsCognitoClient client = new AwsCognitoClient(); + private static final ObjectMapper objectMapper = new ObjectMapper(); @Override public String getOpsToken() throws Exception { @@ -31,6 +38,35 @@ public class AwsTestUtils extends TestUtils{ return opsToken; } + public DpsHeaders getDpsHeaders() throws Exception { + Map<String, String> headers = new HashMap<>(); + headers.put(DpsHeaders.DATA_PARTITION_ID, TestUtils.getOsduTenant()); + headers.put(DpsHeaders.AUTHORIZATION, this.getOpsToken()); + //hardcoding user here for 200 response tests. This is just initializing the subscription creation + headers.put(DpsHeaders.USER_ID, AwsConfig.getAWSCognitoUser()); + + return DpsHeaders.createFromMap(headers); + } + + public static <T> T unwrapFirstMessage(Message message, Class<T[]> classType) throws Exception { + T[] submessages = objectMapper.readValue(message.getBody(), classType); + assertTrue("Must have at least 1 sub-message!", 1 <= submessages.length); + return submessages[0]; + } + + public static <T> T unwrapFirst(List<Message> messages, Class<T[]> classType) throws Exception { + assertTrue("Must have at least 1 message!", 1 <= messages.size()); + + Message firstMessage = messages.get(0); + return unwrapFirstMessage(firstMessage, classType); + } + + public static <T> T unwrapSingleFirst(List<Message> messages, Class<T> classType) throws Exception { + assertTrue("Must have at least 1 message!", 1 <= messages.size()); + + Message firstMessage = messages.get(0); + return objectMapper.readValue(firstMessage.getBody(), classType); + } //These users don't have access to the API, so getting the token for NoAccessUser @Override @@ -40,6 +76,7 @@ public class AwsTestUtils extends TestUtils{ } return adminToken; } + //These users don't have access to the API, so getting the token for NoAccessUser @Override public String getEditorToken() throws Exception { @@ -48,6 +85,7 @@ public class AwsTestUtils extends TestUtils{ } return editorToken; } + //These users don't have access to the API, so getting the token for NoAccessUser @Override public String getNoAccessToken() throws Exception {