diff --git a/NOTICE b/NOTICE index 80d9fa87f9f865657a366a6997044a114a51a0cd..c45d185e0bc6e26ef4de23c2456fe1ef2569cb44 100644 --- a/NOTICE +++ b/NOTICE @@ -52,7 +52,6 @@ The following software have components provided under the terms of this license: - Animal Sniffer Annotations (from https://repo1.maven.org/maven2/org/codehaus/mojo/animal-sniffer-annotations) - Apache Commons BeanUtils (from http://commons.apache.org/proper/commons-beanutils/, https://commons.apache.org/proper/commons-beanutils/, https://repo1.maven.org/maven2/commons-beanutils/commons-beanutils) - Apache Commons Codec (from http://commons.apache.org/proper/commons-codec/, https://commons.apache.org/proper/commons-codec/) -- Apache Commons Collections (from https://commons.apache.org/proper/commons-collections/) - 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/) @@ -143,7 +142,6 @@ The following software have components provided under the terms of this license: - Java Native Access (from https://github.com/java-native-access/jna, https://github.com/twall/jna) - Java Native Access Platform (from https://github.com/java-native-access/jna) - Java Servlet 4.0 API -- Java UUID Generator (from http://wiki.fasterxml.com/JugHome) - 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) - Javassist (from http://www.javassist.org/) - JetBrains Java Annotations (from https://github.com/JetBrains/java-annotations) @@ -271,7 +269,6 @@ The following software have components provided under the terms of this license: - Zipkin Reporter: Core (from https://repo1.maven.org/maven2/io/zipkin/reporter2/zipkin-reporter) - Zipkin v2 (from https://repo1.maven.org/maven2/io/zipkin/zipkin2/zipkin) - aalto-xml (from https://github.com/FasterXML/aalto-xml, https://repo1.maven.org/maven2/com/fasterxml/aalto-xml) -- documentdb-bulkexecutor (from http://azure.microsoft.com/en-us/services/documentdb/) - error-prone annotations (from https://repo1.maven.org/maven2/com/google/errorprone/error_prone_annotations) - io.grpc:grpc-alts (from https://github.com/grpc/grpc-java) - io.grpc:grpc-api (from https://github.com/grpc/grpc-java) @@ -658,8 +655,6 @@ The following software have components provided under the terms of this license: - Spring Data for Azure Cosmos DB SQL API (from https://github.com/Azure/azure-sdk-for-java/tree/master/sdk/cosmos/azure-spring-data-cosmos) - ThreeTen backport (from https://github.com/ThreeTen/threetenbp, https://www.threeten.org/threetenbp) - adal4j (from https://github.com/AzureAD/azure-activedirectory-library-for-java) -- azure-documentdb (from http://azure.microsoft.com/en-us/services/documentdb/, https://azure.microsoft.com/en-us/services/cosmos-db/) -- documentdb-bulkexecutor (from http://azure.microsoft.com/en-us/services/documentdb/) - micrometer-core (from https://github.com/micrometer-metrics/micrometer) - mockito-inline (from http://mockito.org, https://github.com/mockito/mockito) - mockito-junit-jupiter (from https://github.com/mockito/mockito) diff --git a/devops/gc/deploy/templates/deployment.yaml b/devops/gc/deploy/templates/deployment.yaml index b363dca8f899ee765e7812ab7a18b74164d154f8..998f9ea80897cadbba3a78d6cc7f7e97591207b8 100644 --- a/devops/gc/deploy/templates/deployment.yaml +++ b/devops/gc/deploy/templates/deployment.yaml @@ -9,7 +9,7 @@ spec: selector: matchLabels: app: {{ .Values.conf.appName | quote}} - replicas: 1 + replicas: {{ .Values.conf.replicas }} template: metadata: labels: diff --git a/devops/gc/deploy/values.yaml b/devops/gc/deploy/values.yaml index f87091d7cb84c91de42d0bfdd80345b0730a6243..e78d466f563fba2c17aa6222c17e667d860e8c98 100644 --- a/devops/gc/deploy/values.yaml +++ b/devops/gc/deploy/values.yaml @@ -30,6 +30,7 @@ conf: openidSecretName: "notification-keycloak-secret" notificationRedisSecretName: "notification-redis-secret" redisSSL: false + replicas: 1 istio: proxyCPU: "5m" diff --git a/pom.xml b/pom.xml index 395b309d168cc7f1b6be81002eeacc7151644c0a..1b645f99a5a4c9d4e424a392886f687f0e324c96 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ <java.version>17</java.version> <maven.compiler.target>${java.version}</maven.compiler.target> <maven.compiler.source>${java.version}</maven.compiler.source> - <os-core-common.version>0.19.0-rc6</os-core-common.version> + <os-core-common.version>0.24.0-rc6</os-core-common.version> <log4j2.version>2.17.1</log4j2.version> <json-smart.version>2.4.7</json-smart.version> <openapi.version>1.6.14</openapi.version> diff --git a/provider/notification-aws/lombok.config b/provider/notification-aws/lombok.config new file mode 100644 index 0000000000000000000000000000000000000000..0c2484f841602f9ef9b8613e98c78a4c2fbdc7b5 --- /dev/null +++ b/provider/notification-aws/lombok.config @@ -0,0 +1,2 @@ + config.stopBubbling = true + lombok.addLombokGeneratedAnnotation = true diff --git a/provider/notification-aws/pom.xml b/provider/notification-aws/pom.xml index d3fcd1489b5524216b55a2f60d2d676df9f5f8f2..2be707a21b30d81a1032ce95ae0808523eaeadf8 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.23.0</version> + <version>0.24.0-SNAPSHOT</version> </dependency> <dependency> <groupId>commons-io</groupId> @@ -203,10 +203,6 @@ <goals> <goal>prepare-agent</goal> </goals> - <configuration> - <!-- Sets the VM argument line used when unit tests are run. --> - <propertyName>jacocoArgLine</propertyName> - </configuration> </execution> <execution> <id>report</id> diff --git a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/impl/AwsGoogleServiceAccountImpl.java b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/impl/AwsGoogleServiceAccountImpl.java index 09c56e5df2b827e68dac7b0061ec71493c22a154..87b6502878aa097845b21088de76341f1f617e04 100644 --- a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/impl/AwsGoogleServiceAccountImpl.java +++ b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/impl/AwsGoogleServiceAccountImpl.java @@ -15,13 +15,14 @@ package org.opengroup.osdu.notification.provider.aws.impl; import org.opengroup.osdu.notification.provider.interfaces.IGoogleServiceAccount; import org.springframework.stereotype.Component; + @Component public class AwsGoogleServiceAccountImpl implements IGoogleServiceAccount { @Override + // To do: Check if it is to be supported public String getIdToken(String keyString, String audience) { - // TODO : Check if it is to be supported - - throw new UnsupportedOperationException(); + + throw new UnsupportedOperationException(); } } diff --git a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/impl/AwsPubsubRequestBodyExtractor.java b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/impl/AwsPubsubRequestBodyExtractor.java index d4c30be61a0cbdd14cf41ae5b43f98e1021b2152..240b7b40a4d52484e2197e5d3f926c308a16cac7 100644 --- a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/impl/AwsPubsubRequestBodyExtractor.java +++ b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/impl/AwsPubsubRequestBodyExtractor.java @@ -59,6 +59,7 @@ public class AwsPubsubRequestBodyExtractor implements IPubsubRequestBodyExtracto if (this.messageContent == null) { this.messageContent = this.extractPubsubMessageFromRequestBody(); } + return this.messageContent.getAttributes(); } @@ -70,10 +71,14 @@ public class AwsPubsubRequestBodyExtractor implements IPubsubRequestBodyExtracto } public String extractNotificationIdFromRequestBody() { + JsonElement subscription = null; if (this.root == null) { this.root = this.extractRootJsonElementFromRequestBody(); } - JsonElement subscription = this.root.get("subscription"); + + if(root.has("subscription")) + subscription = this.root.get("subscription"); + if (subscription == null) { throw new AppException(HttpStatus.BAD_REQUEST.value(), INVALID_PUBSUB_MESSAGE, "Subscription object not found"); } @@ -92,14 +97,16 @@ public class AwsPubsubRequestBodyExtractor implements IPubsubRequestBodyExtracto this.root = this.extractRootJsonElementFromRequestBody(); } JsonElement message = this.root.get("message"); + if (message == null) { throw new AppException(HttpStatus.BAD_REQUEST.value(), INVALID_PUBSUB_MESSAGE, "Message object not found"); } + MessageContent content = GSON.fromJson(message.toString(), MessageContent.class); Map<String, String> attributes = content.getAttributes(); + if (attributes == null || attributes.isEmpty()) { - log.error("Incorrect Message: " + message ); throw new AppException(HttpStatus.BAD_REQUEST.value(), INVALID_PUBSUB_MESSAGE, "Attribute map not found"); } String data = content.getData(); @@ -112,8 +119,8 @@ public class AwsPubsubRequestBodyExtractor implements IPubsubRequestBodyExtracto throw new AppException(HttpStatus.BAD_REQUEST.value(), INVALID_PUBSUB_MESSAGE, "No tenant information from pubsub message."); } - String x_user_id= request.getHeader("x-user-id"); - lowerCase.put("x-user-id",x_user_id); + String xUserId= request.getHeader("x-user-id"); + lowerCase.put("x-user-id", xUserId); content.setAttributes(lowerCase); String decoded = new String(Base64.getDecoder().decode(data)); @@ -122,9 +129,10 @@ public class AwsPubsubRequestBodyExtractor implements IPubsubRequestBodyExtracto return content; } - private JsonObject extractRootJsonElementFromRequestBody() { + @SuppressWarnings("deprecation") + private JsonObject extractRootJsonElementFromRequestBody() { try { - JsonParser jsonParser = new JsonParser(); + JsonParser jsonParser = new JsonParser(); BufferedReader reader = request.getReader(); Stream<String> lines = reader.lines(); String requestBody = lines.collect(Collectors.joining("\n")); diff --git a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/model/FailedNotificationDoc.java b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/model/FailedNotificationDoc.java index 59cb608b17d5b6e5d03c9fe3ce1a2aac9615c1a1..f656a194ece08a2cd9671f6679fab9e9622cd929 100644 --- a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/model/FailedNotificationDoc.java +++ b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/model/FailedNotificationDoc.java @@ -19,11 +19,11 @@ import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBIndexHashKey; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBIndexRangeKey; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTypeConvertedEnum; + import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import org.apache.commons.lang3.StringUtils; @Data @NoArgsConstructor 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 387c40eeb946bd486ab0394d1aed7ecbde0a3179..da20bf30a1f4e627a14fb438d4bed1067d8683d7 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 @@ -13,7 +13,6 @@ // limitations under the License. package org.opengroup.osdu.notification.provider.aws.queue.impl; -import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBDeleteExpression; import com.amazonaws.services.dynamodbv2.datamodeling.PaginatedQueryList; import com.amazonaws.services.sqs.AmazonSQS; import com.amazonaws.services.sqs.model.Message; @@ -24,6 +23,7 @@ import org.opengroup.osdu.core.aws.dynamodb.DynamoDBQueryHelperV2; import org.opengroup.osdu.core.aws.sqs.AmazonSQSConfig; import org.opengroup.osdu.core.aws.ssm.K8sLocalParameterProvider; import org.opengroup.osdu.core.aws.ssm.K8sParameterNotFoundException; +import org.opengroup.osdu.core.aws.sns.PublishRequestBuilder; import org.opengroup.osdu.core.common.http.HttpResponse; import org.opengroup.osdu.core.common.model.notification.Subscription; import org.opengroup.osdu.notification.provider.aws.model.FailedNotificationDoc; @@ -150,6 +150,9 @@ public class NotificationQueueServiceImpl implements NotificationQueueService { } private boolean notifySubscriber(Subscription subscription, String messageBody, Map<String, String> headerAttributes) { + // Only process this subscription if the topics match. + if (!subscription.getTopic().equals(headerAttributes.get(PublishRequestBuilder.OSDU_TOPIC_ATTRIBUTE_NAME))) return true; + HttpResponse response; try { response = notificationHandler.notifySubscriber(subscription, messageBody, headerAttributes); 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 0652b440531b1f5c8be0b28c8fffd1608244d63e..b51df1790df1da3b6f1b66ea27c5895bc4fcd323 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 @@ -165,8 +165,6 @@ public class NotificationRetryQueueServiceImpl implements NotificationRetryQueue private void deleteDbRecords(List<Message> messages) { DynamoDBQueryHelperV2 dynamoDBQueryHelper = dynamoDBQueryHelperFactory.getQueryHelperUsingSSM(failedNotificationTablePath); messages.parallelStream().forEach(message -> { - FailedNotificationDoc doc = dynamoDBQueryHelper.loadByPrimaryKey(FailedNotificationDoc.class, - message.getMessageAttributes().get(FAILED_NOTIFICATION_RECORD_ID).getStringValue()); try { FailedNotificationDoc objectToDelete = new FailedNotificationDoc(); objectToDelete.setId(message.getMessageAttributes().get(FAILED_NOTIFICATION_RECORD_ID).getStringValue()); diff --git a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/repository/SubscriptionRepository.java b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/repository/SubscriptionRepository.java index 4cecb6736dcc124aa93b31527689c055465699b3..c687640a291f8209304d3b6eab523ec8d79b88cc 100644 --- a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/repository/SubscriptionRepository.java +++ b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/repository/SubscriptionRepository.java @@ -26,7 +26,6 @@ import org.opengroup.osdu.notification.provider.aws.security.KmsHelper; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Repository; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; 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 index d683b65ca3e02ac7d0eefeadca1650923226c45e..e7567d10ee6a2c222b85e689b8b5f171cff8106b 100644 --- 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 @@ -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 © 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; @@ -20,6 +22,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +@SuppressWarnings("deprecation") @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class AwsSecurityConfig extends WebSecurityConfigurerAdapter { diff --git a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/security/KmsHelper.java b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/security/KmsHelper.java index 73ad6a41679a9b39103b5e21cd6a83398a97f2d1..141c29d9092fe20ce232bb1259a16a87b4c0a9b1 100644 --- a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/security/KmsHelper.java +++ b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/security/KmsHelper.java @@ -67,34 +67,23 @@ public class KmsHelper { throw new AppException(HttpStatus.SC_INTERNAL_SERVER_ERROR, "SSM InternalServerErrorException", e.getErrorMessage()); } - } - - public ByteBuffer encrypt(String plainTextString) { - - EncryptRequest encReq = new EncryptRequest(); encReq.setKeyId(kmsKeyId); encReq.setPlaintext(ByteBuffer.wrap(plainTextString.getBytes())); encReq.setEncryptionContext(Collections.singletonMap("dataPartitionId", dpsHeaders.getPartitionId())); - ByteBuffer ciphertext = kmsClient.encrypt(encReq).getCiphertextBlob(); - return ciphertext; - - - + return kmsClient.encrypt(encReq).getCiphertextBlob(); } + public String decrypt(ByteBuffer ciphertext, String dataPartitionId) { - DecryptRequest decReq = new DecryptRequest(); decReq.setCiphertextBlob(ciphertext); decReq.setEncryptionContext(Collections.singletonMap("dataPartitionId", dataPartitionId)); ByteBuffer decrypted = kmsClient.decrypt(decReq).getPlaintext(); - String decryptedStr = new String(decrypted.array()); - return decryptedStr; + return new String(decrypted.array()); } - } diff --git a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/security/ThreadSignatureService.java b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/security/ThreadSignatureService.java index bd54591c5550a593a1c8877a3c4420621055f63c..e68d8917eb4379ae4366206f84e43d102077a624 100644 --- a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/security/ThreadSignatureService.java +++ b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/security/ThreadSignatureService.java @@ -14,8 +14,14 @@ package org.opengroup.osdu.notification.provider.aws.security; -import com.google.common.base.Strings; -import com.google.gson.Gson; +import java.nio.charset.StandardCharsets; +import java.security.SecureRandom; +import java.util.Base64; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import javax.xml.bind.DatatypeConverter; + import org.apache.commons.lang3.StringUtils; import org.opengroup.osdu.core.common.cryptographic.HmacData; import org.opengroup.osdu.core.common.cryptographic.ISignatureService; @@ -23,129 +29,138 @@ import org.opengroup.osdu.core.common.cryptographic.SignatureServiceException; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; -import javax.xml.bind.DatatypeConverter; -import java.nio.charset.StandardCharsets; -import java.security.SecureRandom; -import java.util.Base64; +import com.google.common.base.Strings; +import com.google.gson.Gson; @Component @Primary public class ThreadSignatureService implements ISignatureService { - private static final String HMAC_SHA_256 = "HmacSHA256"; - private static final String DATA_FORMAT = "{\"expireMillisecond\": \"%s\",\"hashMechanism\": \"hmacSHA256\",\"endpointUrl\": \"%s\",\"nonce\": \"%s\"}"; - private static final String NOTIFICATION_SERVICE = "de-notification-service"; - private static final long EXPIRE_DURATION = 30000L; - - private static final String INVALID_SIGNATURE = "Invalid signature"; - private static final String ERROR_GENERATING_SIGNATURE = "Error generating the signature"; - private static final String SIGNATURE_EXPIRED = "Signature is expired"; - private static final String MISSING_HMAC_SIGNATURE = "HMAC signature should not be null or empty"; - private static final String MISSING_SECRET_VALUE = "Secret should not be null or empty"; - private static final String MISSING_ATTRIBUTES_IN_SIGNATURE = "Missing url or nonce or expire time in the signature"; - - - @Override - public String getSignedSignature(String url, String secret) throws SignatureServiceException { - if (Strings.isNullOrEmpty(url) || Strings.isNullOrEmpty(secret)) { - throw new SignatureServiceException(ERROR_GENERATING_SIGNATURE); - } - final long currentTime = System.currentTimeMillis(); - final String expireTime = String.valueOf(currentTime + EXPIRE_DURATION); - final String timeStamp = String.valueOf(currentTime); - try { - String nonce = DatatypeConverter.printHexBinary(generateRandomBytes(16)).toLowerCase(); - String data = String.format(DATA_FORMAT, expireTime, url, nonce); - final byte[] signature = getSignature(secret, nonce, timeStamp, data); - byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8); - String dataBytesEncoded = Base64.getEncoder().encodeToString(dataBytes); - StringBuilder output = new StringBuilder(); - output.append(dataBytesEncoded) - .append(".") - .append(DatatypeConverter.printHexBinary(signature).toLowerCase()); - - return output.toString(); - } catch (Exception ex) { - throw new SignatureServiceException(ERROR_GENERATING_SIGNATURE, ex); - } - } - - @Override - public String getSignedSignature(String url, String secret, String expireTime, String nonce) throws SignatureServiceException { - if (Strings.isNullOrEmpty(url) || Strings.isNullOrEmpty(secret) || !StringUtils.isNumeric(expireTime)) { - throw new SignatureServiceException(ERROR_GENERATING_SIGNATURE); - } - final long expiry = Long.parseLong(expireTime); - if (System.currentTimeMillis() > expiry) { - throw new SignatureServiceException(SIGNATURE_EXPIRED); - } - String timeStamp = String.valueOf(expiry - EXPIRE_DURATION); - String data = String.format(DATA_FORMAT, expireTime, url, nonce); - try { - final byte[] signature = getSignature(secret, nonce, timeStamp, data); - return DatatypeConverter.printHexBinary(signature).toLowerCase(); - } catch (Exception ex) { - throw new SignatureServiceException(ERROR_GENERATING_SIGNATURE, ex); - } - } - - - @Override - public void verifyHmacSignature(String hmac, String secret) throws SignatureServiceException { - if (Strings.isNullOrEmpty(hmac)) { - throw new SignatureServiceException(MISSING_HMAC_SIGNATURE); - } - if (Strings.isNullOrEmpty(secret)) { - throw new SignatureServiceException(MISSING_SECRET_VALUE); - } - String[] tokens = hmac.split("\\."); - if (tokens.length != 2) { - throw new SignatureServiceException(INVALID_SIGNATURE); - } - byte[] dataBytes = Base64.getDecoder().decode(tokens[0]); - String requestSignature = tokens[1]; - - String data = new String(dataBytes, StandardCharsets.UTF_8); - HmacData hmacData = new Gson().fromJson(data, HmacData.class); - String url = hmacData.getEndpointUrl(); - String nonce = hmacData.getNonce(); - String expireTime = hmacData.getExpireMillisecond(); - if (Strings.isNullOrEmpty(url) || Strings.isNullOrEmpty(nonce) || Strings.isNullOrEmpty(expireTime)) { - throw new SignatureServiceException(MISSING_ATTRIBUTES_IN_SIGNATURE); - } - String newSignature = getSignedSignature(url, secret, expireTime, nonce); - if (!requestSignature.equalsIgnoreCase(newSignature)) { - throw new SignatureServiceException(INVALID_SIGNATURE); - } - } - - private byte[] getSignature(String secret, String nonce, String timeStamp, String data) throws Exception { - final byte[] secretBytes = DatatypeConverter.parseHexBinary(secret); - final byte[] nonceBytes = DatatypeConverter.parseHexBinary(nonce); - final byte[] encryptedNonce = computeHmacSha256(nonceBytes, secretBytes); - final byte[] encryptedTimestamp = computeHmacSha256(timeStamp, encryptedNonce); - final byte[] signedKey = computeHmacSha256(NOTIFICATION_SERVICE, encryptedTimestamp); - return computeHmacSha256(data, signedKey); - } - - private byte[] computeHmacSha256(final String data, final byte[] key) throws Exception { - final Mac mac = Mac.getInstance(HMAC_SHA_256); - mac.init(new SecretKeySpec(key, HMAC_SHA_256)); - return mac.doFinal(data.getBytes(StandardCharsets.UTF_8)); - } - - private byte[] computeHmacSha256(final byte[] data, final byte[] key) throws Exception { - final Mac mac = Mac.getInstance(HMAC_SHA_256); - mac.init(new SecretKeySpec(key, HMAC_SHA_256)); - return mac.doFinal(data); - } - - private byte[] generateRandomBytes(final int size) { - final byte[] key = new byte[size]; - SecureRandom secureRandom = new SecureRandom(); - secureRandom.nextBytes(key); - return key; - } + private static final String HMAC_SHA_256 = "HmacSHA256"; + private static final String DATA_FORMAT = "{\"expireMillisecond\": \"%s\",\"hashMechanism\": \"hmacSHA256\",\"endpointUrl\": \"%s\",\"nonce\": \"%s\"}"; + private static final String NOTIFICATION_SERVICE = "de-notification-service"; + private static final long EXPIRE_DURATION = 30000L; + + private static final String INVALID_SIGNATURE = "Invalid signature"; + private static final String ERROR_GENERATING_SIGNATURE = "Error generating the signature"; + private static final String SIGNATURE_EXPIRED = "Signature is expired"; + private static final String MISSING_HMAC_SIGNATURE = "HMAC signature should not be null or empty"; + private static final String MISSING_SECRET_VALUE = "Secret should not be null or empty"; + private static final String MISSING_ATTRIBUTES_IN_SIGNATURE = "Missing url or nonce or expire time in the signature"; + + @Override + public String getSignedSignature(String url, String secret) throws SignatureServiceException { + if (Strings.isNullOrEmpty(url) || Strings.isNullOrEmpty(secret)) { + throw new SignatureServiceException(ERROR_GENERATING_SIGNATURE); + } + final long currentTime = System.currentTimeMillis(); + final String expireTime = String.valueOf(currentTime + EXPIRE_DURATION); + final String timeStamp = String.valueOf(currentTime); + try { + String nonce = DatatypeConverter.printHexBinary(generateRandomBytes(16)).toLowerCase(); + String data = String.format(DATA_FORMAT, expireTime, url, nonce); + final byte[] signature = getSignature(secret, nonce, timeStamp, data); + byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8); + String dataBytesEncoded = Base64.getEncoder().encodeToString(dataBytes); + StringBuilder output = new StringBuilder(); + output.append(dataBytesEncoded).append(".") + .append(DatatypeConverter.printHexBinary(signature).toLowerCase()); + + return output.toString(); + } catch (Exception ex) { + throw new SignatureServiceException(ERROR_GENERATING_SIGNATURE, ex); + } + } + + @Override + public String getSignedSignature(String url, String secret, String expireTime, String nonce) + throws SignatureServiceException { + if (Strings.isNullOrEmpty(url) || Strings.isNullOrEmpty(secret) || !StringUtils.isNumeric(expireTime)) { + throw new SignatureServiceException(ERROR_GENERATING_SIGNATURE); + } + final long expiry = Long.parseLong(expireTime); + if (System.currentTimeMillis() > expiry) { + throw new SignatureServiceException(SIGNATURE_EXPIRED); + } + String timeStamp = String.valueOf(expiry - EXPIRE_DURATION); + String data = String.format(DATA_FORMAT, expireTime, url, nonce); + try { + final byte[] signature = getSignature(secret, nonce, timeStamp, data); + return DatatypeConverter.printHexBinary(signature).toLowerCase(); + } catch (Exception ex) { + throw new SignatureServiceException(ERROR_GENERATING_SIGNATURE, ex); + } + } + + @Override + public void verifyHmacSignature(String hmac, String secret) throws SignatureServiceException { + if (Strings.isNullOrEmpty(hmac)) { + throw new SignatureServiceException(MISSING_HMAC_SIGNATURE); + } + if (Strings.isNullOrEmpty(secret)) { + throw new SignatureServiceException(MISSING_SECRET_VALUE); + } + String[] tokens = hmac.split("\\."); + if (tokens.length != 2) { + throw new SignatureServiceException(INVALID_SIGNATURE); + } + byte[] dataBytes = Base64.getDecoder().decode(tokens[0]); + String requestSignature = tokens[1]; + + String data = new String(dataBytes, StandardCharsets.UTF_8); + HmacData hmacData = new Gson().fromJson(data, HmacData.class); + String url = hmacData.getEndpointUrl(); + String nonce = hmacData.getNonce(); + String expireTime = hmacData.getExpireMillisecond(); + if (Strings.isNullOrEmpty(url) || Strings.isNullOrEmpty(nonce) || Strings.isNullOrEmpty(expireTime)) { + throw new SignatureServiceException(MISSING_ATTRIBUTES_IN_SIGNATURE); + } + String newSignature = getSignedSignature(url, secret, expireTime, nonce); + if (!requestSignature.equalsIgnoreCase(newSignature)) { + throw new SignatureServiceException(INVALID_SIGNATURE); + } + } + + private byte[] getSignature(String secret, String nonce, String timeStamp, String data) + throws SignatureServiceException { + try { + final byte[] secretBytes = DatatypeConverter.parseHexBinary(secret); + final byte[] nonceBytes = DatatypeConverter.parseHexBinary(nonce); + final byte[] encryptedNonce = computeHmacSha256(nonceBytes, secretBytes); + final byte[] encryptedTimestamp = computeHmacSha256(timeStamp, encryptedNonce); + final byte[] signedKey = computeHmacSha256(NOTIFICATION_SERVICE, encryptedTimestamp); + return computeHmacSha256(data, signedKey); + } catch (Exception ex) { + throw new SignatureServiceException(ERROR_GENERATING_SIGNATURE, ex); + } + } + + private byte[] computeHmacSha256(final String data, final byte[] key) throws SignatureServiceException { + try { + final Mac mac = Mac.getInstance(HMAC_SHA_256); + mac.init(new SecretKeySpec(key, HMAC_SHA_256)); + + return mac.doFinal(data.getBytes(StandardCharsets.UTF_8)); + } catch (Exception ex) { + throw new SignatureServiceException(ERROR_GENERATING_SIGNATURE, ex); + } + } + + private byte[] computeHmacSha256(final byte[] data, final byte[] key) throws SignatureServiceException { + try { + final Mac mac = Mac.getInstance(HMAC_SHA_256); + mac.init(new SecretKeySpec(key, HMAC_SHA_256)); + + return mac.doFinal(data); + } catch (Exception ex) { + throw new SignatureServiceException(ERROR_GENERATING_SIGNATURE, ex); + } + } + + private byte[] generateRandomBytes(final int size) { + final byte[] key = new byte[size]; + SecureRandom secureRandom = new SecureRandom(); + secureRandom.nextBytes(key); + return key; + } } diff --git a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/utils/AwsCognitoClient.java b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/utils/AwsCognitoClient.java index a5975d3c94ce71e6422210f69b030c4161a22525..92555ea97744603a22791e3d05b431cf38fb67b8 100644 --- a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/utils/AwsCognitoClient.java +++ b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/utils/AwsCognitoClient.java @@ -17,7 +17,6 @@ package org.opengroup.osdu.notification.provider.aws.utils; import com.amazonaws.services.cognitoidp.AWSCognitoIdentityProvider; import com.amazonaws.services.cognitoidp.AWSCognitoIdentityProviderClientBuilder; import com.amazonaws.services.cognitoidp.model.AdminSetUserPasswordRequest; -import com.amazonaws.services.cognitoidp.model.AdminSetUserPasswordResult; import com.amazonaws.services.cognitoidp.model.InitiateAuthRequest; import com.amazonaws.services.cognitoidp.model.InitiateAuthResult; import org.opengroup.osdu.core.aws.iam.IAMConfig; @@ -28,12 +27,8 @@ import java.util.Map; public class AwsCognitoClient { // Parameter value locations - private final static String USERNAME_PARAM = "USERNAME"; - private final static String PASSWORD_PARAM = "PASSWORD"; - private final static String COGNITO_CLIENT_ID_PROPERTY = "AWS_COGNITO_CLIENT_ID"; - private final static String COGNITO_AUTH_FLOW_PROPERTY = "AWS_COGNITO_AUTH_FLOW"; - private final static String COGNITO_AUTH_PARAMS_USER_PROPERTY = "AWS_COGNITO_AUTH_PARAMS_USER"; - private final static String COGNITO_AUTH_PARAMS_PASSWORD_PROPERTY = "AWS_COGNITO_AUTH_PARAMS_PASSWORD"; + private static final String USERNAME_PARAM = "USERNAME"; + private static final String PASSWORD_PARAM = "PASSWORD"; String awsCognitoClientId; @@ -75,7 +70,7 @@ public class AwsCognitoClient { return provider; } - public static AWSCognitoIdentityProvider generateCognitoClient(String region) + public AWSCognitoIdentityProvider generateCognitoClient(String region) { if (System.getenv("AWS_COGNITO_REGION") != null) { region = System.getenv("AWS_COGNITO_REGION"); @@ -91,7 +86,6 @@ public class AwsCognitoClient { .withPassword(password) .withPermanent(true) .withUserPoolId(userPoolId); - AdminSetUserPasswordResult result = this.provider.adminSetUserPassword(request); - + this.provider.adminSetUserPassword(request); } } diff --git a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/utils/SQSUtils.java b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/utils/SQSUtils.java index c55b2400e4cd3fde9c3823ad44a578b53743f4b7..39f45642cf6938bfb7c3cae6e03b0c3aa4640fd6 100644 --- a/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/utils/SQSUtils.java +++ b/provider/notification-aws/src/main/java/org/opengroup/osdu/notification/provider/aws/utils/SQSUtils.java @@ -82,11 +82,11 @@ public class SQSUtils { exceptionAttribute.setStringValue("Exception message: missing dataPartitionId"); messageAttributes.put("Exception", exceptionAttribute); - SendMessageRequest send_msg_request = new SendMessageRequest() + SendMessageRequest sendMsgRequest = new SendMessageRequest() .withQueueUrl(deadLetterQueueUrl) .withMessageBody(message.getBody()) .withMessageAttributes(messageAttributes); - return sqsClient.sendMessage(send_msg_request); + return sqsClient.sendMessage(sendMsgRequest); } } \ No newline at end of file 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 new file mode 100644 index 0000000000000000000000000000000000000000..b5533616fabb8df7814522ab43fcf70f6b5f7f2b --- /dev/null +++ b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsAppPropertiesTest.java @@ -0,0 +1,37 @@ +package org.opengroup.osdu.notification.provider.aws; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.junit.MockitoJUnitRunner; +import org.opengroup.osdu.notification.provider.aws.impl.AwsAppProperties; +import org.powermock.reflect.Whitebox; + + +@RunWith(MockitoJUnitRunner.class) +public class AwsAppPropertiesTest { + + @InjectMocks + AwsAppProperties awsAppProperties; + + @Before + public void initTest() { + Whitebox.setInternalState(awsAppProperties, "authorizeAPI", "authorizeAPI"); + Whitebox.setInternalState(awsAppProperties, "registerAPI", "registerAPI"); + } + + @Test + public void getAuthorizeAPIReturnsAuthorizeAPI() { + String authorizeAPI = "authorizeAPI"; + assertEquals(authorizeAPI, awsAppProperties.getAuthorizeAPI()); + } + + @Test + public void getRegisterAPIReturnsAuthorizeAPI() { + String registerAPI = "registerAPI"; + assertEquals(registerAPI, awsAppProperties.getRegisterAPI()); + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..f7e17b0bf99d5cbb287fc5713bcda16d2cf281f1 --- /dev/null +++ b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsGoogleServiceAccountImplTest.java @@ -0,0 +1,20 @@ +package org.opengroup.osdu.notification.provider.aws; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.junit.MockitoJUnitRunner; +import org.opengroup.osdu.notification.provider.aws.impl.AwsGoogleServiceAccountImpl; + +@RunWith(MockitoJUnitRunner.class) +public class AwsGoogleServiceAccountImplTest { + + @InjectMocks + AwsGoogleServiceAccountImpl awsGoogleServiceAccountImpl; + + + @Test(expected = UnsupportedOperationException.class) + public void getIdTokenThorwsNotImplementedException() { + awsGoogleServiceAccountImpl.getIdToken("keyString", "audience"); + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..d48cbef2d0f95f9bf8a1a9ee240522c7c0d9fc01 --- /dev/null +++ b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsPubSubHandshakeHandlerTest.java @@ -0,0 +1,23 @@ +package org.opengroup.osdu.notification.provider.aws; + +import static org.junit.Assert.assertNull; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.junit.MockitoJUnitRunner; +import org.opengroup.osdu.notification.provider.aws.impl.AwsPubSubHandshakeHandler; + + +@RunWith(MockitoJUnitRunner.class) +public class AwsPubSubHandshakeHandlerTest { + + @InjectMocks + AwsPubSubHandshakeHandler AwsPubSubHandshakeHandler; + + + @Test + public void getIdTokenReturnsNull() { + assertNull( AwsPubSubHandshakeHandler.getHandshakeResponse()); + } +} diff --git a/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsPubsubRequestBodyExtractorTest.java b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsPubsubRequestBodyExtractorTest.java index 021cc17d22803ea24f0cdeec17bea522823d3614..b43a19ae21c74a0ae1f3f4c7369a95939caf9dea 100644 --- a/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsPubsubRequestBodyExtractorTest.java +++ b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsPubsubRequestBodyExtractorTest.java @@ -25,7 +25,7 @@ import org.mockito.junit.MockitoJUnitRunner; import org.opengroup.osdu.core.common.logging.JaxRsDpsLog; - +import org.opengroup.osdu.core.common.model.http.AppException; import org.opengroup.osdu.core.common.model.http.DpsHeaders; import org.opengroup.osdu.notification.provider.aws.impl.AwsPubsubRequestBodyExtractor; @@ -38,16 +38,12 @@ import java.io.StringReader; import java.util.Map; - - @RunWith(MockitoJUnitRunner.class) public class AwsPubsubRequestBodyExtractorTest { @Mock private DpsHeaders dpsHeaders; - - @Mock private JaxRsDpsLog logger; @@ -58,10 +54,7 @@ public class AwsPubsubRequestBodyExtractorTest { private AwsPubsubRequestBodyExtractor service; @Before - public void init() { - - - } + public void init() { } @Test @@ -87,9 +80,6 @@ public class AwsPubsubRequestBodyExtractorTest { String receivedData = service.extractDataFromRequestBody(); Assert.assertEquals(expectedData,receivedData); - - - } @@ -116,11 +106,69 @@ public class AwsPubsubRequestBodyExtractorTest { String receivedData = service.extractNotificationIdFromRequestBody(); Assert.assertEquals(expectedData,receivedData); + } + + @Test(expected = AppException.class) + public void extractNotificationIdFromRequestBodyThrowsAppExceptionOnNullSubscription() throws IOException, AppException { + String stringRequest = "{\n" + + "\t\"Type\": \"Notification\",\n" + + "\t\"message\": {\n" + + "\t\"attributes\": {\n" + + "\t\"correlation-id\": \"39137f49-67d6-4001-a6aa-15521ef4f49e\",\n" + + "\t\"data-partition-id\": \"" + TestUtils.getDataPartitionId() + "\"\n" + + "\t},\n" + + "\t\"data\": \"dGVzdERhdGE=\",\n" + + "\t\"messageId\": \"136969346945\"\n" + + "\t}\n" + + "}\n"; + BufferedReader reader = new BufferedReader(new StringReader(stringRequest)); + Mockito.when(request.getReader()).thenReturn(reader); + service = new AwsPubsubRequestBodyExtractor(request); + service.extractNotificationIdFromRequestBody(); + } + + @Test(expected = AppException.class) + public void extractAttributesFromRequestBodyThrowsAppExceptionOnNullAttributes() throws IOException, AppException { + String stringRequest = "{\n" + + "\t\"Type\": \"Notification\",\n" + + "\t\"message\": {\n" + + "\t\"attributes\": {\n" + + "\t},\n" + + "\t\"data\": \"dGVzdERhdGE=\",\n" + + "\t\"messageId\": \"136969346945\"\n" + + "\t},\n" + + "\t\"subscription\": \""+ "de12345" +"\"\n" + + "}\n"; + BufferedReader reader = new BufferedReader(new StringReader(stringRequest)); + Mockito.when(request.getReader()).thenReturn(reader); + service = new AwsPubsubRequestBodyExtractor(request); + service.extractAttributesFromRequestBody(); } + + + @Test(expected = AppException.class) + public void extractAttributesFromRequestBodyThrowsAppExceptionOnNullDataPartitionId() throws IOException, AppException { + String stringRequest = "{\n" + + "\t\"Type\": \"Notification\",\n" + + "\t\"message\": {\n" + + "\t\"attributes\": {\n" + + "\t\"correlation-id\": \"39137f49-67d6-4001-a6aa-15521ef4f49e\"\n" + + "\t},\n" + + "\t\"data\": \"dGVzdERhdGE=\",\n" + + "\t\"messageId\": \"136969346945\"\n" + + "\t},\n" + + "\t\"subscription\": \""+ "de12345" +"\"\n" + + "}\n"; + BufferedReader reader = new BufferedReader(new StringReader(stringRequest)); + Mockito.when(request.getReader()).thenReturn(reader); + service = new AwsPubsubRequestBodyExtractor(request); + service.extractAttributesFromRequestBody(); + } + @Test public void should_returnValidAttributes_FromRequestBody() throws IOException { String stringRequest = "{\n" + @@ -138,8 +186,6 @@ public class AwsPubsubRequestBodyExtractorTest { BufferedReader reader = new BufferedReader(new StringReader(stringRequest)); Mockito.when(request.getReader()).thenReturn(reader); - String expectedData = "de12345"; - service = new AwsPubsubRequestBodyExtractor(request); // Act Map<String, String> receivedAttributes = service.extractAttributesFromRequestBody(); @@ -147,8 +193,5 @@ public class AwsPubsubRequestBodyExtractorTest { // Asset Assert.assertEquals("39137f49-123-456", receivedAttributes.get("correlation-id")); Assert.assertEquals("opendes", receivedAttributes.get("data-partition-id")); - - - } } 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 new file mode 100644 index 0000000000000000000000000000000000000000..5649ab02c19c53adb92df25f6f61afc52e7bb138 --- /dev/null +++ b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/AwsServiceAccountValidatorTest.java @@ -0,0 +1,26 @@ +package org.opengroup.osdu.notification.provider.aws; + +import static org.junit.Assert.assertFalse; + +import org.junit.runner.RunWith; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.junit.MockitoJUnitRunner; +import org.opengroup.osdu.notification.provider.aws.impl.AwsServiceAccountValidator; + +@RunWith(MockitoJUnitRunner.class) +public class AwsServiceAccountValidatorTest { + + @InjectMocks + AwsServiceAccountValidator awsServiceAccountValidator; + + @Test + public void awsServiceAccountValidatorReturnsFalse() { + assertFalse(awsServiceAccountValidator.isValidPublisherServiceAccount("jwt")); + } + + @Test + public void isValidServiceAccountReturnsFalse() { + assertFalse(awsServiceAccountValidator.isValidServiceAccount("jwt", "userIdentity", "audiences")); + } +} diff --git a/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/queue/impl/NotificationQueueServiceImplTest.java b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/queue/impl/NotificationQueueServiceImplTest.java index 0f9bbedf0a31ef19e6383da7e96ab800712576b7..585556babd565ae99c9c42cf6688e39a3158f5a9 100644 --- a/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/queue/impl/NotificationQueueServiceImplTest.java +++ b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/queue/impl/NotificationQueueServiceImplTest.java @@ -16,6 +16,8 @@ package org.opengroup.osdu.notification.provider.aws.queue.impl; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.withSettings; @@ -39,7 +41,9 @@ import org.mockito.junit.MockitoJUnitRunner; import org.opengroup.osdu.core.aws.dynamodb.DynamoDBQueryHelperFactory; import org.opengroup.osdu.core.aws.dynamodb.DynamoDBQueryHelperV2; import org.opengroup.osdu.core.aws.ssm.K8sLocalParameterProvider; +import org.opengroup.osdu.core.aws.sns.PublishRequestBuilder; import org.opengroup.osdu.core.common.http.HttpResponse; +import org.opengroup.osdu.core.common.model.http.DpsHeaders; import org.opengroup.osdu.core.common.model.notification.Subscription; import org.opengroup.osdu.notification.provider.aws.model.FailedNotificationDoc; import org.opengroup.osdu.notification.provider.aws.queue.impl.NotificationQueueServiceImpl; @@ -75,6 +79,8 @@ public class NotificationQueueServiceImplTest { private static MockedConstruction<K8sLocalParameterProvider> mockedConstruction; + private static final String DEFAULT_MESSAGE_TOPIC = "some-topic"; + @BeforeClass public static void setup() { mockedConstruction = Mockito.mockConstruction(K8sLocalParameterProvider.class, @@ -98,7 +104,7 @@ public class NotificationQueueServiceImplTest { Subscription subscription1 = new Subscription(); subscription1.setName("My listener"); - subscription1.setTopic("records-changed"); + subscription1.setTopic(DEFAULT_MESSAGE_TOPIC); subscription1.setPushEndpoint("/api/test/subscriber"); subscription1.setNotificationId("de-859ea6a6-eefa-4e30-ba38-13f8cd71360a"); subscription1.setId("testSubscription1Id"); @@ -123,6 +129,18 @@ public class NotificationQueueServiceImplTest { assertEquals("testMessage1", responseMessageList.get(0).getMessageId()); } + @Test + public void processNotificationMessage_withNoSubuscriberForTopic() throws Exception { + List<FailedNotificationDoc> list = new ArrayList<>(); + when(dynamoDBQueryHelper.queryByGSI(any(), any())).thenReturn(mock(PaginatedQueryList.class, withSettings().defaultAnswer(new ForwardsInvocations(list)))); + + List<Message> messageList = Arrays.asList(createMessage("testMessage1", "testDataPartition", "non-subscribed-topic")); + + List<Message> responseMessageList = notificationQueueService.processNotificationMessages(messageList); + + verify(notificationHandler, never()).notifySubscriber(any(), any(), any()); + } + @Test public void processNotificationMessage_noSubscribers_success() { when(subscriptionRepository.getAllSubscriptionsByDataPartition(anyString())).thenReturn(Collections.emptyList()); @@ -233,13 +251,19 @@ public class NotificationQueueServiceImplTest { assertEquals("testMessage2", responseMessageList.get(1).getMessageId()); } - private Message createMessage(String messageId, String dataPartitionId) { + private void addMessageAttribute(Message message, String key, String value) { + message.getMessageAttributes().put(key, new MessageAttributeValue().withDataType("String").withStringValue(value)); + } + + private Message createMessage(String messageId, String dataPartitionId, String topicName) { Message message = new Message(); message.setMessageId(messageId); - MessageAttributeValue dataPartitionIdAttribute = new MessageAttributeValue() - .withDataType("String"); - dataPartitionIdAttribute.setStringValue(dataPartitionId); - message.getMessageAttributes().put("data-partition-id", dataPartitionIdAttribute); + addMessageAttribute(message, DpsHeaders.DATA_PARTITION_ID, dataPartitionId); + addMessageAttribute(message, PublishRequestBuilder.OSDU_TOPIC_ATTRIBUTE_NAME, topicName); return message; } + + private Message createMessage(String messageId, String dataPartitionId) { + return createMessage(messageId, dataPartitionId, DEFAULT_MESSAGE_TOPIC); + } } 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 new file mode 100644 index 0000000000000000000000000000000000000000..0eb25f1de6e315b0e4d0fce4fc8d13373de8d951 --- /dev/null +++ b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/security/KmsHelperTest.java @@ -0,0 +1,72 @@ +package org.opengroup.osdu.notification.provider.aws.security; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import java.nio.ByteBuffer; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedConstruction; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.opengroup.osdu.core.aws.ssm.K8sLocalParameterProvider; +import org.opengroup.osdu.core.common.model.http.DpsHeaders; +import org.powermock.reflect.Whitebox; + +import com.amazonaws.SdkClientException; +import com.amazonaws.services.kms.AWSKMS;; + +@RunWith(MockitoJUnitRunner.class) +public class KmsHelperTest { + + @InjectMocks + private KmsHelper kmsHelper; + + @Mock + private DpsHeaders dpsHeaders; + + @Mock + private ByteBuffer ciphertext; + + private static MockedConstruction<K8sLocalParameterProvider> mockedConstruction; + + + @BeforeClass + public static void setup() { + mockedConstruction = Mockito.mockConstruction(K8sLocalParameterProvider.class, + (mock, context) -> { + //implement initializer for mock. Set return value for object A mock methods + when(mock.getParameterAsString("notification-sqs-url")).thenReturn( + "test-sqs-url"); + }); + } + + @AfterClass + public static void close(){ + mockedConstruction.close(); + } + + @Before + public void initTest() { + Whitebox.setInternalState(kmsHelper, "amazonRegion", "us-east-1"); + Whitebox.setInternalState(kmsHelper, "kmsEndpoint", "aws.kms.endpoint"); + } + + @Test(expected = SdkClientException.class) + public void encrypt_EncryptsData() { + kmsHelper.init(); + kmsHelper.encrypt("plain text"); + } + + @Test(expected = SdkClientException.class ) + public void decryptThorwsFormMockedKmsClient() { + kmsHelper.init(); + kmsHelper.decrypt(ciphertext, "dataPartitionId"); + } +} diff --git a/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/security/ThreadSignatureServiceTest.java b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/security/ThreadSignatureServiceTest.java index fe7d7e5c15c0851183643bfd6ce35b7cca029f11..dc7551e1d66bf4776917268133ffad2999761179 100644 --- a/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/security/ThreadSignatureServiceTest.java +++ b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/security/ThreadSignatureServiceTest.java @@ -16,6 +16,10 @@ package org.opengroup.osdu.notification.provider.aws.security; import static org.junit.Assert.assertNotNull; import static org.mockito.ArgumentMatchers.any; +import java.security.NoSuchAlgorithmException; + +import javax.crypto.Mac; + import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; @@ -24,8 +28,7 @@ import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; import org.opengroup.osdu.core.common.cryptographic.SignatureServiceException; -import javax.crypto.Mac; -import java.security.NoSuchAlgorithmException; +import com.google.gson.JsonSyntaxException; @RunWith(MockitoJUnitRunner.class) public class ThreadSignatureServiceTest { @@ -106,4 +109,8 @@ public class ThreadSignatureServiceTest { threadSignatureService.verifyHmacSignature("invalidHmac", SECRET); } + @Test(expected = JsonSyntaxException.class) + public void verifyHmacSignature_() throws SignatureServiceException { + threadSignatureService.verifyHmacSignature(HMAC, SECRET); + } } 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 new file mode 100644 index 0000000000000000000000000000000000000000..2a1ac4996ce68d931bbc1c0963fd6794095fe808 --- /dev/null +++ b/provider/notification-aws/src/test/java/org/opengroup/osdu/notification/provider/aws/utils/AwsCognitoClientTest.java @@ -0,0 +1,72 @@ +package org.opengroup.osdu.notification.provider.aws.utils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import com.amazonaws.services.cognitoidp.AWSCognitoIdentityProvider; +import com.amazonaws.services.sqs.AmazonSQS; + +import io.jsonwebtoken.lang.Assert; + +@RunWith(MockitoJUnitRunner.class) +public class AwsCognitoClientTest { + + private AwsCognitoClient awsCognitoClient; + + @Mock + private AmazonSQS sqsClient; + + @Mock + private AWSCognitoIdentityProvider provider; + + @Before + public void setUp() { + awsCognitoClient = new AwsCognitoClient("region", "awsCognitoClientId", "awsCognitoAuthFlow", + "awsCognitoAuthParamsUser", "awsCognitoAuthParamsPassword"); + } + + @Test + public void constuctorCreatesObject() { + Assert.isInstanceOf(AwsCognitoClient.class, awsCognitoClient); + assertNotNull(awsCognitoClient); + } + + @Test + public void getToken() { + awsCognitoClient.provider = provider; + when(provider.initiateAuth(any())).thenReturn(null); + String expected = ""; + String actual = awsCognitoClient.getToken("username", "password", "tokenType"); + assertEquals(expected, actual); + } + + @Test + public void getProvider() { + AWSCognitoIdentityProvider object = awsCognitoClient.getProvider(); + assertTrue(object instanceof AWSCognitoIdentityProvider); + } + + @Test + public void generateCognitoClient() { + AWSCognitoIdentityProvider object = awsCognitoClient.generateCognitoClient("us-east-1"); + assertTrue(object instanceof AWSCognitoIdentityProvider); + } + + //the code on production side seems useless. hence useless test here just for coverage. + @Test + public void setPassword() { + awsCognitoClient.provider = provider; + when(provider.adminSetUserPassword(any())).thenReturn(null); + awsCognitoClient.setPassword("username", "password", "user-pool-id"); + assertNotNull(awsCognitoClient); + } +} diff --git a/provider/notification-azure/pom.xml b/provider/notification-azure/pom.xml index 8510da42bac14b256a75d4496a16e33d2c297cad..6bc1fe137098e3156ad587ae632a106fe5b19628 100644 --- a/provider/notification-azure/pom.xml +++ b/provider/notification-azure/pom.xml @@ -40,7 +40,7 @@ <reactor.netty.version>0.11.0.RELEASE</reactor.netty.version> <reactor.core.version>3.3.0.RELEASE</reactor.core.version> <osdu.corelibazure.version>0.21.0</osdu.corelibazure.version> - <osdu.oscorecommon.version>0.19.0-rc6</osdu.oscorecommon.version> + <osdu.oscorecommon.version>0.24.0-rc6</osdu.oscorecommon.version> <junit.version>5.6.0</junit.version> <jjwt.version>3.8.1</jjwt.version> <mockito.version>2.23.0</mockito.version> @@ -50,13 +50,23 @@ <oauth2-oidc-sdk.version>6.0</oauth2-oidc-sdk.version> <woodstox-core.version>5.4.0</woodstox-core.version> <spring-webmvc.version>5.3.22</spring-webmvc.version> - <undertow.version>2.2.19.Final</undertow.version> + <undertow.version>2.2.26.Final</undertow.version> <spring-boot-maven-plugin.version>2.7.6</spring-boot-maven-plugin.version> <xnio-api.version>3.8.8.Final</xnio-api.version> + <netty.version>4.1.98.Final</netty.version> </properties> <dependencyManagement> <dependencies> + <!-- netty-bom dependency to be declared before spring-boot-dependencies, + to pull all netty-transitive dependencies with same version --> + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty-bom</artifactId> + <version>${netty.version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> <!-- Inherit managed dependencies from core-lib-azure --> <dependency> <groupId>org.opengroup.osdu</groupId> @@ -139,6 +149,12 @@ <groupId>org.opengroup.osdu</groupId> <artifactId>core-lib-azure</artifactId> <version>${osdu.corelibazure.version}</version> + <exclusions> + <exclusion> + <groupId>com.microsoft.azure</groupId> + <artifactId>documentdb-bulkexecutor</artifactId> + </exclusion> + </exclusions> </dependency> <!-- Spring Dependencies --> 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 1809604630695c38de96bfc095eee2d7a7f1b75a..e5b9b32ce21bdb80172070c230776c5f2a645fb6 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 @@ -15,6 +15,7 @@ import org.opengroup.osdu.core.common.notification.SubscriptionFactory; import org.opengroup.osdu.notification.util.*; import java.util.Arrays; +import java.util.Base64; import java.util.HashMap; import java.util.Map; import java.util.UUID; @@ -44,8 +45,32 @@ public class TestNotificationsEndpoint extends TestBase { } @Before - public void setup() { + 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()); + + DpsHeaders dpsHeaders = DpsHeaders.createFromMap(headers); + awssubscriptionService = awsfactory.create(dpsHeaders); + + try { + // Ensure that there is no previous subscription already registered + // Sometimes this can happen if previous tests didn't exit properly + + // 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()); + + awssubscriptionService.delete(encodedSubscriptionId); + } + catch (Exception e) {} } @After @@ -57,25 +82,11 @@ public class TestNotificationsEndpoint extends TestBase { } private void createResourceForTestParition() throws Exception { - 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()); - DpsHeaders dpsHeaders = DpsHeaders.createFromMap(headers); - awssubscriptionService = awsfactory.create(dpsHeaders); - - Map<String,String> h = dpsHeaders.getHeaders(); - System.out.println(h); - - //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); - //This seems to be a bug. Don't need to add the string - //subscription.setPushEndpoint(Config.Instance().HMACPushUrl + "hmac-integration-test"); subscription.setPushEndpoint(Config.Instance().HMACPushUrl); HmacSecret secret = new HmacSecret(); secret.setValue(Config.Instance().hmacSecretValue);