From ecda41ee531101c9848b470c660d803b1ee01216 Mon Sep 17 00:00:00 2001
From: Michael Nguyen <michael.nguyen@parivedasolutions.com>
Date: Tue, 29 Oct 2019 15:55:12 -0500
Subject: [PATCH] updating record repo.

---
 indexer-service-aws/pom.xml                   | 19 ++++
 .../indexer/aws/IndexerAwsApplication.java    |  4 +-
 .../indexer/aws/model/RecordMetadata.java     | 82 +++++++++++++++++
 .../indexer/aws/model/RecordMetadataDoc.java  | 37 ++++++++
 .../osdu/indexer/aws/model/RecordState.java   | 18 ++++
 .../osdu/indexer/aws/model/SchemaDoc.java     | 37 ++++++++
 .../osdu/indexer/aws/model/SchemaItem.java    | 21 +++++
 .../indexer/aws/publish/PublisherImpl.java    | 11 ++-
 .../aws/service/AwsStorageServiceImpl.java    | 89 +++++++++++++++++++
 .../aws/util/AWSElasticSearchConfig.java      | 33 -------
 .../indexer/aws/util/AmazonSNSConfig.java     | 39 --------
 .../osdu/indexer/aws/util/IAMConfig.java      | 24 -----
 .../aws/util/dynamodb/DynamoDBConfig.java     | 37 ++++++++
 .../util/dynamodb/record/DynamoDBRecord.java  | 20 +++++
 .../record/LegalTagsTypeConverter.java        | 49 ++++++++++
 .../record/RecordMetadataTypeConverter.java   | 52 +++++++++++
 .../util/dynamodb/schema/DynamoDBSchema.java  | 24 +++++
 .../schema/SchemaExtTypeConverter.java        | 46 ++++++++++
 .../schema/SchemaItemTypeConverter.java       | 48 ++++++++++
 .../indexer/aws/util/s3/S3RecordClient.java   | 43 +++++++++
 .../src/main/resources/application.properties | 16 +++-
 21 files changed, 648 insertions(+), 101 deletions(-)
 create mode 100644 indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/model/RecordMetadata.java
 create mode 100644 indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/model/RecordMetadataDoc.java
 create mode 100644 indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/model/RecordState.java
 create mode 100644 indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/model/SchemaDoc.java
 create mode 100644 indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/model/SchemaItem.java
 create mode 100644 indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/service/AwsStorageServiceImpl.java
 delete mode 100644 indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/AWSElasticSearchConfig.java
 delete mode 100644 indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/AmazonSNSConfig.java
 delete mode 100644 indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/IAMConfig.java
 create mode 100644 indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/DynamoDBConfig.java
 create mode 100644 indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/record/DynamoDBRecord.java
 create mode 100644 indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/record/LegalTagsTypeConverter.java
 create mode 100644 indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/record/RecordMetadataTypeConverter.java
 create mode 100644 indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/schema/DynamoDBSchema.java
 create mode 100644 indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/schema/SchemaExtTypeConverter.java
 create mode 100644 indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/schema/SchemaItemTypeConverter.java
 create mode 100644 indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/s3/S3RecordClient.java

diff --git a/indexer-service-aws/pom.xml b/indexer-service-aws/pom.xml
index be2416219..5c95e90e1 100644
--- a/indexer-service-aws/pom.xml
+++ b/indexer-service-aws/pom.xml
@@ -18,6 +18,25 @@
           <artifactId>indexer-service-root</artifactId>
           <version>1.0-SNAPSHOT</version>
       </dependency>
+      <dependency>
+          <groupId>com.amazonaws</groupId>
+          <artifactId>aws-java-sdk-core</artifactId>
+          <version>1.11.651</version>
+      </dependency>
+      <dependency>
+          <groupId>com.amazonaws</groupId>
+          <artifactId>aws-osdu-util</artifactId>
+          <version>0.0.2</version>
+      </dependency>
+      <dependency>
+          <groupId>com.github.derjust</groupId>
+          <artifactId>spring-data-dynamodb</artifactId>
+          <version>5.1.0</version>
+      </dependency>
+      <dependency>
+          <groupId>org.projectlombok</groupId>
+          <artifactId>lombok</artifactId>
+      </dependency>
    <dependency>
       <groupId>com.amazonaws</groupId>
       <artifactId>aws-java-sdk</artifactId>
diff --git a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/IndexerAwsApplication.java b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/IndexerAwsApplication.java
index a3adb4f2e..f39452c46 100644
--- a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/IndexerAwsApplication.java
+++ b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/IndexerAwsApplication.java
@@ -2,10 +2,12 @@ package org.opengroup.osdu.indexer.aws;
 
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.actuate.autoconfigure.elasticsearch.ElasticSearchRestHealthIndicatorAutoConfiguration;
+import org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
 import org.springframework.context.annotation.ComponentScan;
 
-@SpringBootApplication(exclude = {ElasticSearchRestHealthIndicatorAutoConfiguration.class})
+@SpringBootApplication(exclude = {ElasticSearchRestHealthIndicatorAutoConfiguration.class, SecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class})
 @ComponentScan({"org.opengroup.osdu.is.core", "org.opengroup.osdu.indexer"})
 public class IndexerAwsApplication {
     public static void main( String[] args )
diff --git a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/model/RecordMetadata.java b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/model/RecordMetadata.java
new file mode 100644
index 000000000..aa52ae69a
--- /dev/null
+++ b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/model/RecordMetadata.java
@@ -0,0 +1,82 @@
+package org.opengroup.osdu.indexer.aws.model;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.apache.http.HttpStatus;
+import org.opengroup.osdu.indexer.model.*;
+import org.opengroup.osdu.is.core.util.AppException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Data
+@NoArgsConstructor
+public class RecordMetadata {
+    private String id;
+
+    private String kind;
+
+    private StorageAcl acl;
+
+    private Legal legal;
+
+    private RecordAncestry ancestry;
+
+    private List<String> gcsVersionPaths = new ArrayList<>();
+
+    private RecordState status;
+
+    private String user;
+
+    // epoch time
+    private long createTime;
+
+    private String modifyUser;
+
+    // epoch time
+    private long modifyTime;
+
+    public RecordMetadata(RecordIndexerPayload.Record record) {
+        this.id = record.getId();
+        this.kind = record.getKind();
+        this.acl = record.getAcl();
+        this.legal = record.getLegal();
+        this.ancestry = record.getAncestry();
+    }
+
+    public Long getLatestVersion() {
+        String latestVersionPath = this.gcsVersionPaths.get(gcsVersionPaths.size() - 1);
+        String[] versionTokens = latestVersionPath.split("/");
+        return Long.parseLong(versionTokens[versionTokens.length - 1]);
+    }
+
+    public boolean hasVersion() {
+        if (gcsVersionPaths.isEmpty()) {
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    public void addGcsPath(long version) {
+        this.gcsVersionPaths.add(String.format("%s/%s/%s", this.kind, this.id, version));
+    }
+
+    public String getVersionPath(Long version) {
+        for (String path : this.gcsVersionPaths) {
+            if (path.contains(Long.toString(version))) {
+                return path;
+            }
+        }
+
+        throw new AppException(HttpStatus.SC_NOT_FOUND, "Record version not found",
+                "The requested record version was not found");
+    }
+
+    public void resetGcsPath(List<String> gcsVersionPathList) {
+        this.gcsVersionPaths.clear();
+        for (String path: gcsVersionPathList) {
+            this.gcsVersionPaths.add(path);
+        }
+    }
+}
diff --git a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/model/RecordMetadataDoc.java b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/model/RecordMetadataDoc.java
new file mode 100644
index 000000000..caa128dcd
--- /dev/null
+++ b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/model/RecordMetadataDoc.java
@@ -0,0 +1,37 @@
+package org.opengroup.osdu.indexer.aws.model;
+
+import com.amazonaws.services.dynamodbv2.datamodeling.*;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.opengroup.osdu.indexer.aws.util.dynamodb.record.LegalTagsTypeConverter;
+import org.opengroup.osdu.indexer.aws.util.dynamodb.record.RecordMetadataTypeConverter;
+
+import java.util.Set;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@DynamoDBTable(tableName = "RecordMetadataRepository") // DynamoDB table name (without environment prefix)
+public class RecordMetadataDoc {
+
+    @DynamoDBHashKey(attributeName = "Id")
+    private String id;
+
+    @DynamoDBIndexHashKey(attributeName = "Kind", globalSecondaryIndexName = "KindStatusIndex")
+    private String kind;
+
+    @DynamoDBIndexRangeKey(attributeName = "Status", globalSecondaryIndexName = "KindStatusIndex")
+    private String status;
+
+    @DynamoDBIndexHashKey(attributeName = "User", globalSecondaryIndexName = "UserIndex")
+    private String user;
+
+    @DynamoDBTypeConverted(converter = RecordMetadataTypeConverter.class)
+    @DynamoDBAttribute(attributeName = "metadata")
+    private RecordMetadata metadata;
+
+    @DynamoDBTypeConverted(converter = LegalTagsTypeConverter.class)
+    @DynamoDBAttribute(attributeName = "LegalTags")
+    private Set<String> legaltags;
+}
diff --git a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/model/RecordState.java b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/model/RecordState.java
new file mode 100644
index 000000000..21c495140
--- /dev/null
+++ b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/model/RecordState.java
@@ -0,0 +1,18 @@
+package org.opengroup.osdu.indexer.aws.model;
+
+public enum RecordState {
+    /**
+     * An active record
+     */
+    active,
+
+    /**
+     * A deleted record
+     */
+    deleted,
+
+    /**
+     * A purged record
+     */
+    purged
+}
diff --git a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/model/SchemaDoc.java b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/model/SchemaDoc.java
new file mode 100644
index 000000000..def063bf8
--- /dev/null
+++ b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/model/SchemaDoc.java
@@ -0,0 +1,37 @@
+package org.opengroup.osdu.indexer.aws.model;
+
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTypeConverted;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.opengroup.osdu.indexer.aws.util.dynamodb.schema.SchemaExtTypeConverter;
+import org.opengroup.osdu.indexer.aws.util.dynamodb.schema.SchemaItemTypeConverter;
+import org.opengroup.osdu.indexer.model.Schema;
+
+import java.util.List;
+import java.util.Map;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@DynamoDBTable(tableName = "SchemaRepository") // DynamoDB table name (without environment prefix)
+public class SchemaDoc {
+
+    @DynamoDBHashKey(attributeName = "Kind")
+    private String kind;
+
+    @DynamoDBTypeConverted(converter = SchemaExtTypeConverter.class)
+    @DynamoDBAttribute(attributeName = "ext")
+    private Map<String,Object> extension;
+
+    @DynamoDBAttribute(attributeName = "User")
+    private String user;
+
+    @DynamoDBTypeConverted(converter = SchemaItemTypeConverter.class)
+    @DynamoDBAttribute(attributeName = "schema")
+    private List<SchemaItem> schemaItems;
+}
+
diff --git a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/model/SchemaItem.java b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/model/SchemaItem.java
new file mode 100644
index 000000000..b00593b50
--- /dev/null
+++ b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/model/SchemaItem.java
@@ -0,0 +1,21 @@
+package org.opengroup.osdu.indexer.aws.model;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Map;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class SchemaItem {
+
+    private String path;
+
+    private String kind;
+
+    @JsonInclude(value = JsonInclude.Include.NON_NULL)
+    private Map<String, Object> ext;
+}
\ No newline at end of file
diff --git a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/publish/PublisherImpl.java b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/publish/PublisherImpl.java
index 9a748fbb7..9e9fec608 100644
--- a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/publish/PublisherImpl.java
+++ b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/publish/PublisherImpl.java
@@ -1,5 +1,6 @@
 package org.opengroup.osdu.indexer.aws.publish;
 
+import com.amazonaws.osdu.util.sns.SNSBuilder;
 import com.amazonaws.services.sns.model.MessageAttributeValue;
 import com.amazonaws.services.sns.model.PublishRequest;
 import com.google.gson.Gson;
@@ -16,12 +17,20 @@ import java.util.Map;
 
 @Component
 public class PublisherImpl implements IPublisher {
-    @Inject
+
     private AmazonSNS snsClient;
 
     @Value("${aws.sns.arn}")
     private String amazonSNSTopic;
 
+    @Value("${aws.sns.region}")
+    private String amazonSNSRegion;
+
+    @Inject
+    public void init(){
+        snsClient = SNSBuilder.generateAmazonSNSClient(amazonSNSRegion);
+    }
+
     public void publishStatusChangedTagsToTopic(DpsHeaders headers, JobStatus indexerBatchStatus) throws Exception
     {
         String json = new Gson().toJson(indexerBatchStatus.getStatusesList());
diff --git a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/service/AwsStorageServiceImpl.java b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/service/AwsStorageServiceImpl.java
new file mode 100644
index 000000000..f8b8f3072
--- /dev/null
+++ b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/service/AwsStorageServiceImpl.java
@@ -0,0 +1,89 @@
+package org.opengroup.osdu.indexer.aws.service;
+
+import com.google.gson.Gson;
+import org.checkerframework.checker.units.qual.A;
+import org.opengroup.osdu.indexer.aws.model.RecordMetadataDoc;
+import org.opengroup.osdu.indexer.aws.model.SchemaDoc;
+import org.opengroup.osdu.indexer.aws.util.dynamodb.record.DynamoDBRecord;
+import org.opengroup.osdu.indexer.aws.util.dynamodb.schema.DynamoDBSchema;
+import org.opengroup.osdu.indexer.aws.util.s3.S3RecordClient;
+import org.opengroup.osdu.indexer.model.*;
+import org.opengroup.osdu.indexer.service.StorageService;
+import org.opengroup.osdu.is.core.util.AppException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Component;
+
+
+import javax.inject.Inject;
+import java.io.Console;
+import java.io.UnsupportedEncodingException;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+@Primary
+@Component
+public class AwsStorageServiceImpl implements StorageService {
+
+    @Inject
+    DynamoDBSchema dynamoDBSchema;
+
+    @Inject
+    DynamoDBRecord dynamoDBRecord;
+
+    @Inject
+    S3RecordClient s3Client;
+
+//    private String getKeyNameForLatestVersion( recordMetadata){
+//        return recordMetadata.getKind() + "/" + recordMetadata.getId() + "/" + recordMetadata.getLatestVersion();
+//    }
+    @Override
+    public org.opengroup.osdu.indexer.model.Records getStorageRecords(List<String> ids) throws AppException, URISyntaxException {
+        Records records = new Records();
+        List<String> notFound = new ArrayList<>();
+        List<Records.Entity> entities = new ArrayList<>();
+        List<ConversionStatus> statuses = new ArrayList<>();
+        Gson gson = new Gson();
+        for (String id: ids) {
+            Optional<RecordMetadataDoc> doc = dynamoDBRecord.findById(id);
+            if (!doc.isPresent()){
+                notFound.add(id);
+            }
+
+            String record = s3Client.getRecord(doc.get().getMetadata());
+            Records.Entity entity = gson.fromJson(record, Records.Entity.class);
+            statuses.add(ConversionStatus.builder().status(doc.get().getStatus()).build());
+            entities.add(entity);
+        }
+        records.setNotFound(notFound);
+        records.setRecords(entities);
+        records.setConversionStatuses(statuses);
+        return records;
+    }
+
+    @Override
+    public RecordQueryResponse getRecordsByKind(RecordReindexRequest request) throws URISyntaxException {
+
+        return null;
+    }
+
+    @Override
+    public String getStorageSchema(String kind) throws URISyntaxException, UnsupportedEncodingException {
+        Optional<SchemaDoc> sd = dynamoDBSchema.findById(kind);
+        if (!sd.isPresent()) {
+            return null;
+        }
+        // Create a Schema object and assign the values retrieved from DynamoDB
+        Schema newSchema = new Schema();
+        newSchema.setKind(kind);
+        List<Schema.Mapping> mappings;
+        mappings = sd.get().getSchemaItems().stream().map(schemaItem -> Schema.Mapping.builder().kind(schemaItem.getKind()).path(schemaItem.getPath()).build()).collect(Collectors.toList());
+        newSchema.setSchema(mappings);
+        return new Gson().toJson(newSchema);
+    }
+}
diff --git a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/AWSElasticSearchConfig.java b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/AWSElasticSearchConfig.java
deleted file mode 100644
index b4ed0958e..000000000
--- a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/AWSElasticSearchConfig.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.opengroup.osdu.indexer.aws.util;
-
-import com.amazonaws.auth.AWSCredentials;
-import com.amazonaws.auth.AWSCredentialsProvider;
-import com.amazonaws.auth.AWSCredentialsProviderChain;
-import com.amazonaws.auth.AWSStaticCredentialsProvider;
-import com.amazonaws.services.elasticsearch.AWSElasticsearch;
-import com.amazonaws.services.elasticsearch.AWSElasticsearchClientBuilder;
-import com.amazonaws.services.elasticsearch.model.ElasticsearchClusterConfig;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Import;
-
-import javax.inject.Inject;
-
-@Configuration
-@Import({IAMConfig.class})
-public class AWSElasticSearchConfig {
-
-    @Value("${aws.sns.region}")
-    private String amazonSNSRegion;
-
-    @Inject
-    private AWSCredentials amazonAWSCredentials;
-
-    public AWSElasticsearch AWSElasticsearch() {
-        return AWSElasticsearchClientBuilder.standard()
-                .withRegion(amazonSNSRegion)
-                .withCredentials(new AWSStaticCredentialsProvider(amazonAWSCredentials)).build();
-
-    }
-
-}
diff --git a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/AmazonSNSConfig.java b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/AmazonSNSConfig.java
deleted file mode 100644
index 5ecbb027a..000000000
--- a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/AmazonSNSConfig.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.opengroup.osdu.indexer.aws.util;
-
-import com.amazonaws.auth.AWSCredentials;
-import com.amazonaws.auth.AWSStaticCredentialsProvider;
-import com.amazonaws.services.sns.AmazonSNS;
-import com.amazonaws.services.sns.AmazonSNSClientBuilder;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Import;
-
-import javax.inject.Inject;
-
-@Configuration
-@Import({IAMConfig.class})
-public class AmazonSNSConfig {
-
-    @Value("${aws.sns.region}")
-    private String amazonSNSRegion;
-
-    @Value("${aws.sns.topic-name}")
-    private String amazonSNSTopicName;
-
-    @Value("${aws.sns.arn}")
-    private String amazonSNSARN;
-
-
-    @Inject
-    private AWSCredentials amazonAWSCredentials;
-
-    @Bean
-    public AmazonSNS AmazonSNS() {
-        return AmazonSNSClientBuilder.standard()
-                .withCredentials(new AWSStaticCredentialsProvider(amazonAWSCredentials))
-                .withRegion(amazonSNSRegion)
-                .build();
-    }
-
-}
\ No newline at end of file
diff --git a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/IAMConfig.java b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/IAMConfig.java
deleted file mode 100644
index 12fe7b7c8..000000000
--- a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/IAMConfig.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.opengroup.osdu.indexer.aws.util;
-
-import com.amazonaws.auth.AWSCredentials;
-import com.amazonaws.auth.BasicAWSCredentials;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-@Configuration
-public class IAMConfig {
-
-    @Value("${aws.accessKeyId}")
-    private String amazonAWSAccessKey;
-
-    @Value("${aws.secretKey}")
-    private String amazonAWSSecretKey;
-
-    @Bean
-    public AWSCredentials amazonAWSCredentials() {
-        // Generate AWS basic credentials from the access keys provided in application.properties
-        return new BasicAWSCredentials(
-                amazonAWSAccessKey, amazonAWSSecretKey);
-    }
-}
\ No newline at end of file
diff --git a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/DynamoDBConfig.java b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/DynamoDBConfig.java
new file mode 100644
index 000000000..7a7f00611
--- /dev/null
+++ b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/DynamoDBConfig.java
@@ -0,0 +1,37 @@
+package org.opengroup.osdu.indexer.aws.util.dynamodb;
+
+import com.amazonaws.osdu.util.dynamodb.DynamoDBBuilder;
+import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
+import org.socialsignin.spring.data.dynamodb.repository.config.EnableDynamoDBRepositories;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+
+@Configuration
+@EnableDynamoDBRepositories
+        (basePackages = "org.opengroup.osdu.indexer.aws")
+public class DynamoDBConfig {
+
+    @Value("${aws.dynamodb.endpoint}")
+    private String amazonDynamoDBEndpoint;
+
+    @Value("${aws.dynamodb.region}")
+    private String amazonDynamoDBRegion;
+
+    @Value("${aws.dynamodb.table.prefix}")
+    private String tablePrefix;
+
+    @Bean
+    public AmazonDynamoDB amazonDynamoDB() {
+        // Generate the DynamoDB client
+        return DynamoDBBuilder.generateDynamoDBClient(amazonDynamoDBEndpoint, amazonDynamoDBRegion);
+    }
+
+    @Bean
+    @Primary
+    public DynamoDBMapper DynamoDBMapper() {
+        return DynamoDBBuilder.generateDynamoDBMapper(amazonDynamoDB(), tablePrefix);
+    }
+}
diff --git a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/record/DynamoDBRecord.java b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/record/DynamoDBRecord.java
new file mode 100644
index 000000000..676c904d2
--- /dev/null
+++ b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/record/DynamoDBRecord.java
@@ -0,0 +1,20 @@
+package org.opengroup.osdu.indexer.aws.util.dynamodb.record;
+
+import com.amazonaws.osdu.util.dynamodb.DynamoDBRepository;
+import org.opengroup.osdu.indexer.aws.model.RecordMetadataDoc;
+import org.socialsignin.spring.data.dynamodb.repository.EnableScan;
+import org.socialsignin.spring.data.dynamodb.repository.EnableScanCount;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+
+import java.util.List;
+
+@EnableScan
+@EnableScanCount
+public interface DynamoDBRecord extends DynamoDBRepository<RecordMetadataDoc, String> {
+    // Currently unsupported by the spring-data-dynamodb library, see: https://github.com/derjust/spring-data-dynamodb/issues/114
+    // No release timeline at this time
+    List<RecordMetadataDoc> findByKindAndStatus(String kind, String status);
+    Page<RecordMetadataDoc> findByKindAndStatus(String kind, String status, Pageable pageable);
+    List<RecordMetadataDoc> findByUser(String user);
+}
diff --git a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/record/LegalTagsTypeConverter.java b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/record/LegalTagsTypeConverter.java
new file mode 100644
index 000000000..b2aad3dd2
--- /dev/null
+++ b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/record/LegalTagsTypeConverter.java
@@ -0,0 +1,49 @@
+package org.opengroup.osdu.indexer.aws.util.dynamodb.record;
+
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTypeConverter;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.opengroup.osdu.is.core.logging.JaxRsDpsLog;
+
+import javax.inject.Inject;
+import java.io.IOException;
+import java.util.Set;
+
+public class LegalTagsTypeConverter implements DynamoDBTypeConverter<String, Set<String>> {
+
+@Inject
+private JaxRsDpsLog logger;
+
+@Override
+// Converts an array of legaltag strings to a JSON string for DynamoDB
+public String convert(Set<String> legaltags) {
+    ObjectMapper objectMapper = new ObjectMapper();
+    try {
+        return objectMapper.writeValueAsString(legaltags);
+    } catch (JsonProcessingException e) {
+        logger.error(String.format("There was an error converting the schema to a JSON string. %s", e.getMessage()));
+    }
+    return null;
+    }
+
+@Override
+// Converts a JSON string of an array of legaltag strings to a list of legaltag strings
+public Set<String> unconvert(String legaltagsString) {
+    ObjectMapper objectMapper = new ObjectMapper();
+        try {
+            return objectMapper.readValue(legaltagsString, new TypeReference<Set<String>>(){});
+        } catch (JsonParseException e) {
+            logger.error(String.format("There was an error parsing the legaltags JSON string. %s", e.getMessage()));
+        } catch (JsonMappingException e) {
+            logger.error(String.format("There was an error mapping the legaltags JSON string. %s", e.getMessage()));
+        } catch (IOException e) {
+            logger.error(String.format("There was an IO exception while mapping the legaltags objects. %s", e.getMessage()));
+        } catch (Exception e) {
+            logger.error(String.format("There was an unknown exception legaltags the schema. %s", e.getMessage()));
+        }
+    return null;
+    }
+}
diff --git a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/record/RecordMetadataTypeConverter.java b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/record/RecordMetadataTypeConverter.java
new file mode 100644
index 000000000..832e8633c
--- /dev/null
+++ b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/record/RecordMetadataTypeConverter.java
@@ -0,0 +1,52 @@
+package org.opengroup.osdu.indexer.aws.util.dynamodb.record;
+
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTypeConverter;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.opengroup.osdu.indexer.aws.model.RecordMetadata;
+import org.opengroup.osdu.indexer.aws.model.RecordMetadataDoc;
+import org.opengroup.osdu.is.core.logging.JaxRsDpsLog;
+
+import javax.inject.Inject;
+import java.io.IOException;
+
+public class RecordMetadataTypeConverter implements DynamoDBTypeConverter<String, RecordMetadata> {
+
+    @Inject
+    private JaxRsDpsLog logger;
+
+    @Override
+    // Converts RecordMetadata to a JSON string for DynamoDB
+    public String convert(RecordMetadata recordMetadata) {
+        ObjectMapper objectMapper = new ObjectMapper();
+        try {
+            return objectMapper.writeValueAsString(recordMetadata);
+        } catch (JsonProcessingException e) {
+            logger.error(String.format("There was an error converting the record metadata to a JSON string. %s", e.getMessage()));
+        }
+        return null;
+    }
+
+    @Override
+    // Converts a JSON string of an array of RecordMetadata to a RecordMetadata object
+    public RecordMetadata unconvert(String recordMetadataString) {
+        ObjectMapper objectMapper = new ObjectMapper();
+        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+        try {
+            return objectMapper.readValue(recordMetadataString, new TypeReference<RecordMetadata>(){});
+        } catch (JsonParseException e) {
+            logger.error(String.format("There was an error parsing the record metadata JSON string. %s", e.getMessage()));
+        } catch (JsonMappingException e) {
+            logger.error(String.format("There was an error mapping the record metadata JSON string. %s", e.getMessage()));
+        } catch (IOException e) {
+            logger.error(String.format("There was an IO exception while mapping the record metadata objects. %s", e.getMessage()));
+        } catch (Exception e) {
+            logger.error(String.format("There was an unknown exception converting the record metadata. %s", e.getMessage()));
+        }
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/schema/DynamoDBSchema.java b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/schema/DynamoDBSchema.java
new file mode 100644
index 000000000..628475112
--- /dev/null
+++ b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/schema/DynamoDBSchema.java
@@ -0,0 +1,24 @@
+// 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.indexer.aws.util.dynamodb.schema;
+
+import com.amazonaws.osdu.util.dynamodb.DynamoDBRepository;
+import org.opengroup.osdu.indexer.aws.model.SchemaDoc;
+import org.socialsignin.spring.data.dynamodb.repository.EnableScan;
+import org.socialsignin.spring.data.dynamodb.repository.EnableScanCount;
+
+@EnableScan
+@EnableScanCount
+public interface DynamoDBSchema extends DynamoDBRepository<SchemaDoc, String> {}
diff --git a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/schema/SchemaExtTypeConverter.java b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/schema/SchemaExtTypeConverter.java
new file mode 100644
index 000000000..2b76a0e36
--- /dev/null
+++ b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/schema/SchemaExtTypeConverter.java
@@ -0,0 +1,46 @@
+package org.opengroup.osdu.indexer.aws.util.dynamodb.schema;
+
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTypeConverter;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.opengroup.osdu.is.core.logging.JaxRsDpsLog;
+
+import javax.inject.Inject;
+import java.io.IOException;
+import java.util.Map;
+
+public class SchemaExtTypeConverter implements DynamoDBTypeConverter<String, Map<String, Object>> {
+    @Inject
+    private JaxRsDpsLog logger;
+
+    @Override
+    public String convert(Map<String, Object> stringObjectMap) {
+        ObjectMapper objectMapper = new ObjectMapper();
+        try {
+            return objectMapper.writeValueAsString(stringObjectMap);
+        } catch (JsonProcessingException e) {
+            logger.error(String.format("There was an error converting the schema to a JSON string. %s", e.getMessage()));
+        }
+        return null;
+    }
+
+    @Override
+    public Map<String, Object> unconvert(String s) {
+        ObjectMapper objectMapper = new ObjectMapper();
+        try {
+            return objectMapper.readValue(s, new TypeReference<Map<String, Object>>(){});
+        } catch (JsonParseException e) {
+            logger.error(String.format("There was an error parsing the schema JSON string. %s", e.getMessage()));
+        } catch (JsonMappingException e) {
+            logger.error(String.format("There was an error mapping the schema JSON string. %s", e.getMessage()));
+        } catch (IOException e) {
+            logger.error(String.format("There was an IO exception while mapping the schema objects. %s", e.getMessage()));
+        } catch (Exception e) {
+            logger.error(String.format("There was an unknown exception converting the schema. %s", e.getMessage()));
+        }
+        return null;
+    }
+}
diff --git a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/schema/SchemaItemTypeConverter.java b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/schema/SchemaItemTypeConverter.java
new file mode 100644
index 000000000..b7e8b6a82
--- /dev/null
+++ b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/dynamodb/schema/SchemaItemTypeConverter.java
@@ -0,0 +1,48 @@
+package org.opengroup.osdu.indexer.aws.util.dynamodb.schema;
+
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTypeConverter;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.opengroup.osdu.core.api.storage.models.SchemaNode;
+import org.opengroup.osdu.indexer.aws.model.SchemaItem;
+import org.opengroup.osdu.is.core.logging.JaxRsDpsLog;
+
+import javax.inject.Inject;
+import java.io.IOException;
+import java.util.List;
+
+public class SchemaItemTypeConverter implements DynamoDBTypeConverter<String, List<SchemaItem>> {
+    @Inject
+    private JaxRsDpsLog logger;
+
+    @Override
+    public String convert(List<SchemaItem> schemaNodes) {
+        ObjectMapper objectMapper = new ObjectMapper();
+        try {
+            return objectMapper.writeValueAsString(schemaNodes);
+        } catch (JsonProcessingException e) {
+            logger.error(String.format("There was an error converting the schema to a JSON string. %s", e.getMessage()));
+        }
+        return null;
+    }
+
+    @Override
+    public List<SchemaItem> unconvert(String s) {
+        ObjectMapper objectMapper = new ObjectMapper();
+        try {
+            return objectMapper.readValue(s, new TypeReference<List<SchemaItem>>(){});
+        } catch (JsonParseException e) {
+            logger.error(String.format("There was an error parsing the schema JSON string. %s", e.getMessage()));
+        } catch (JsonMappingException e) {
+            logger.error(String.format("There was an error mapping the schema JSON string. %s", e.getMessage()));
+        } catch (IOException e) {
+            logger.error(String.format("There was an IO exception while mapping the schema objects. %s", e.getMessage()));
+        } catch (Exception e) {
+            logger.error(String.format("There was an unknown exception converting the schema. %s", e.getMessage()));
+        }
+        return null;
+    }
+}
diff --git a/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/s3/S3RecordClient.java b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/s3/S3RecordClient.java
new file mode 100644
index 000000000..ca98fcafd
--- /dev/null
+++ b/indexer-service-aws/src/main/java/org/opengroup/osdu/indexer/aws/util/s3/S3RecordClient.java
@@ -0,0 +1,43 @@
+package org.opengroup.osdu.indexer.aws.util.s3;
+
+import com.amazonaws.AmazonServiceException;
+import com.amazonaws.SdkClientException;
+import com.amazonaws.osdu.util.s3.S3Builder;
+import com.amazonaws.services.s3.AmazonS3;
+import org.apache.http.HttpStatus;
+import org.opengroup.osdu.indexer.aws.model.RecordMetadata;
+import org.opengroup.osdu.is.core.util.AppException;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+
+@Configuration
+public class S3RecordClient {
+
+    private AmazonS3 s3;
+
+    @Value("${aws.s3.records.bucket-name}")
+    private String recordsBucketName;
+
+
+    // Constructor Injection
+    public S3RecordClient(@Value("${aws.s3.region}") String awsS3Region,  @Value("${aws.s3.endpoint}") String awsS3Endpoint){
+        s3 = S3Builder.generateS3Client(awsS3Endpoint, awsS3Region);
+    }
+
+
+    public String getRecord(RecordMetadata recordMetadata) {
+        String record = "";
+        String keyName = getKeyNameForLatestVersion(recordMetadata);
+        record = s3.getObjectAsString(recordsBucketName, keyName);
+        return record;
+    }
+
+    private String getKeyNameForLatestVersion(RecordMetadata recordMetadata){
+        return recordMetadata.getKind() + "/" + recordMetadata.getId() + "/" + recordMetadata.getLatestVersion();
+    }
+}
diff --git a/indexer-service-aws/src/main/resources/application.properties b/indexer-service-aws/src/main/resources/application.properties
index 603398728..698d068e6 100644
--- a/indexer-service-aws/src/main/resources/application.properties
+++ b/indexer-service-aws/src/main/resources/application.properties
@@ -8,19 +8,29 @@ DEFAULT_DATA_COUNTRY=US
 CRON_INDEX_CLEANUP_THRESHOLD_DAYS=3
 CRON_EMPTY_INDEX_CLEANUP_THRESHOLD_DAYS=7
 
-## AWS IAM configuration
-aws.accessKeyId=AKIA453FG2R346APY3VT
-aws.secretKey=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
+## AWS S3 configuration
+aws.s3.records.bucket-name=dev-osdu-data
+aws.s3.max-record-threads=2000
+aws.s3.enable-https=true
+aws.s3.region=us-east-1
+aws.s3.endpoint=s3.us-east-1.amazonaws.com
 
 ## AWS SNS configuration
 aws.sns.region=us-east-1
 aws.sns.arn=arn:aws:sns:us-east-1:888733619319:dev-osdu-messages
 aws.sns.topic-name=dev-osdu-messages
 
+#Spring Configuration
 spring.security.user.name=opendes@byoc.local
 spring.security.user.password=123
 spring.security.user.roles=service.storage.admin
 
+## AWS DynamoDB configuration
+aws.dynamodb.key=kind
+aws.dynamodb.table.prefix=dev-
+aws.dynamodb.region=us-east-1
+aws.dynamodb.endpoint=dynamodb.us-east-1.amazonaws.com
+
 ## AWS ES configuration
 #aws.es.host=https://search-osdu-indexer-nj62ktooaiug2mjqzguzx5utr4.us-east-1.es.amazonaws.com
 #aws.es.port=443
-- 
GitLab