diff --git a/docs/tutorial/ActionService.md b/docs/tutorial/ActionService.md
index 802a8361e2b7f44474283a9e871db77392857ef3..c8c250511c472fae1856e9cc058fcb11c2d562f9 100644
--- a/docs/tutorial/ActionService.md
+++ b/docs/tutorial/ActionService.md
@@ -308,4 +308,4 @@ There are mainly 2 limitations currently:
 - Users need to individually register for each data partition they want the action enabled from.
 - We don't support a wildcard in the action URL for the partition id. Something like myaction.com/kind?dpid={data-partition-id} may be supported in the future so that the request can be data partition aware.
 
-[Back to Table of Contents](#TOC)
\ No newline at end of file
+[Back to Table of Contents](#TOC)
diff --git a/pom.xml b/pom.xml
index 342e9aab35c16b4e0754bf7be8530c3f9cab8bbb..4a33e6496386e93b7002b38e9b490416020f359c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -90,6 +90,7 @@
     <modules>
         <module>register-core</module>
         <module>provider/register-gcp</module>
+        <module>provider/register-azure</module>
     </modules>
 
     <distributionManagement>
diff --git a/provider/register-azure/README.md b/provider/register-azure/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..c1c9b2ea74e88bb5dfe8cce4e64036708a1ee147
--- /dev/null
+++ b/provider/register-azure/README.md
@@ -0,0 +1,119 @@
+Copyright © Microsoft Corporation
+
+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.
+
+# os-register-azure
+
+os-register-azure is a [Spring Boot](https://spring.io/projects/spring-boot) service that hosts CRUD APIs that allows consumers to register a push endpoint that can be triggered when data change events happen within the OSDU R2 ecosystem.
+
+## Running locally
+
+### Requirements
+* Java 8
+* [Maven 3.6.0+](https://maven.apache.org/download.cgi)
+
+### General Tips
+
+**Environment Variable Management**
+The following tools make environment variable configuration simpler
+ - [direnv](https://direnv.net/) - for a shell/terminal environment
+ - [EnvFile](https://plugins.jetbrains.com/plugin/7861-envfile) - for [Intellij IDEA](https://www.jetbrains.com/idea/)
+
+**Lombok**
+This project uses [Lombok](https://projectlombok.org/) for code generation. You may need to configure your IDE to take advantage of this tool.
+ - [Intellij configuration](https://projectlombok.org/setup/intellij)
+ - [VSCode configuration](https://projectlombok.org/setup/vscode)
+
+
+### Configure Maven
+
+Check that maven is installed:
+```bash
+$ mvn --version
+Apache Maven 3.6.0
+Maven home: /usr/share/maven
+Java version: 1.8.0_212, vendor: AdoptOpenJDK, runtime: /usr/lib/jvm/jdk8u212-b04/jre
+...
+```
+
+You will need to configure access to the remote maven repository that holds the OSDU dependencies. This file should live within `~/.m2/settings.xml`:
+```bash
+$ cat ~/.m2/settings.xml
+<?xml version="1.0" encoding="UTF-8"?>
+<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
+    <servers>
+        <server>
+            <id>os-core</id>
+            <username>slb-des-ext-collaboration</username>
+            <!-- Treat this auth token like a password. Do not share it with anyone, including Microsoft support. -->
+            <password>${VSTS_FEED_TOKEN}</password>
+        </server>
+    </servers>
+</settings>
+```
+
+### Environment Variables
+
+In order to run the service locally, you will need to have the following environment variables defined.
+
+**System Environment required to run service**
+Refer to [application.properties](./src/main/resources/application.properties)
+
+Definitions for some variables used
+
+| name | value | description | sensitive? | source |
+| ---  | ---   | ---         | ---        | ---    |
+| `LOG_PREFIX` | `storage` | Logging prefix | no | - |
+| `server.servlet.contextPath` | `/api/storage/v2/` | Servlet context path | no | - |
+| `AUTHORIZE_API` | ex `https://foo-entitlements.azurewebsites.net` | Entitlements API endpoint | no | output of infrastructure deployment |
+| `AUTHORIZE_API_KEY` | `********` | The API key clients will need to use when calling the entitlements | yes | -- |
+| `azure.application-insights.instrumentation-key` | `********` | API Key for App Insights | yes | output of infrastructure deployment |
+| `azure.activedirectory.client-id` | `********` | AAD client application ID | yes | output of infrastructure deployment |
+| `azure.activedirectory.AppIdUri` | `api://${azure.activedirectory.client-id}` | URI for AAD Application | no | -- |
+| `azure.activedirectory.session-stateless` | `true` | Flag run in stateless mode (needed by AAD dependency) | no | -- |
+| `cosmosdb_account` | ex `devintosdur2cosmosacct` | Cosmos account name | no | output of infrastructure deployment |
+| `cosmosdb_key` | `********` | Key for CosmosDB | yes | output of infrastructure deployments |
+| `cosmosdb_database` | ex `dev-osdu-r2-db` | Cosmos database for storage documents | no | output of infrastructure deployment |
+| `azure.storage.account-name` | ex `foo-storage-account` | Storage account for storing documents | no | output of infrastructure deployment |
+| `azure.storage.enable-https` | `true` | Used by spring boot starter library | no | - |
+| `servicebus_topic_name` | `recordstopic` | Topic for async messaging | no | output of infrastructure deployment |
+| `servicebus_namespace_name` | ex `foo-sb-namespace` | Namespace for async messaging | no | output of infrastructure deployment |
+| `KEYVAULT_URI` | ex `https://foo-keyvault.vault.azure.net/` | URI of KeyVault that holds application secrets | no | output of infrastructure deployment |
+| `AZURE_CLIENT_ID` | `********` | Identity to run the service locally. This enables access to Azure resources. You only need this if running locally | yes | keyvault secret: `$KEYVAULT_URI/secrets/app-dev-sp-username` |
+| `AZURE_TENANT_ID` | `********` | AD tenant to authenticate users from | yes | keyvault secret: `$KEYVAULT_URI/secrets/app-dev-sp-tenant-id` |
+| `AZURE_CLIENT_SECRET` | `********` | Secret for `$AZURE_CLIENT_ID` | yes | keyvault secret: `$KEYVAULT_URI/secrets/app-dev-sp-password` |
+
+
+
+### Build and run the application
+After configuring your environment as specified above, you can follow these steps to build and run the application. These steps should be invoked from the *repository root*.
+```bash
+# build + test + install core service code
+$ cd register-core/ && mvn clean install
+
+# build + test + package azure service code
+$ cd provider/register-azure/ && mvn clean package
+
+# run service
+#
+# Note: this assumes that the environment variables for running the service as outlined
+#       above are already exported in your environment.
+$ mvn spring-boot:run -Dspring-boot.run.profiles=local   
+# or directly run the jar file  
+$ cd provider/register-azure/ && java -jar target\register-azure-1.0.0-spring-boot.jar
+```
+
+### Test the application
+After the service has started it should be accessible via a web browser by visiting [http://localhost:8080/api/register/v1/swagger-ui.html](http://localhost:8080/api/register/v1/swagger-ui.html). If the request does not fail, you can then run the integration tests.
\ No newline at end of file
diff --git a/provider/register-azure/pom.xml b/provider/register-azure/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a035b36c346887507e8acc7f3d1bc54c4ce05d00
--- /dev/null
+++ b/provider/register-azure/pom.xml
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Copyright © Microsoft Corporation
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>os-register</artifactId>
+        <groupId>org.opengroup.osdu</groupId>
+        <version>1.0.0</version>
+        <relativePath>../../</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>register-azure</artifactId>
+    <description>Register service on Azure</description>
+    <packaging>jar</packaging>
+    <properties>
+        <azure.version>2.1.7</azure.version>
+        <azure.appservice.resourcegroup></azure.appservice.resourcegroup>
+        <azure.appservice.plan></azure.appservice.plan>
+        <azure.appservice.appname></azure.appservice.appname>
+        <azure.appservice.subscription></azure.appservice.subscription>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>com.microsoft.azure</groupId>
+            <artifactId>azure-active-directory-spring-boot-starter</artifactId>
+            <version>${azure.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>ch.qos.logback</groupId>
+                    <artifactId>logback-classic</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.logging.log4j</groupId>
+                    <artifactId>log4j-to-slf4j</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-oauth2-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-logging</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-oauth2-jose</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opengroup.osdu</groupId>
+            <artifactId>core-lib-azure</artifactId>
+            <version>0.0.12</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opengroup.osdu</groupId>
+            <artifactId>os-core-common</artifactId>
+            <version>0.3.4</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opengroup.osdu</groupId>
+            <artifactId>register-core</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <!--
+         Override the spring-boot version of these dependencies to the ones
+         required by the azure-core library. This needs to be done for each
+         app that depends on this library
+        -->
+        <dependency>
+            <groupId>io.projectreactor.netty</groupId>
+            <artifactId>reactor-netty</artifactId>
+            <version>0.9.0.RELEASE</version>
+        </dependency>
+        <dependency>
+            <groupId>io.projectreactor</groupId>
+            <artifactId>reactor-core</artifactId>
+            <version>3.3.0.RELEASE</version>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter</artifactId>
+            <version>5.6.0</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-junit-jupiter</artifactId>
+            <version>2.23.0</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <repositories>
+        <repository>
+            <id>${gitlab-server}</id>
+            <url>https://community.opengroup.org/api/v4/groups/17/-/packages/maven</url>
+        </repository>
+    </repositories>
+
+    <distributionManagement>
+        <repository>
+            <id>${gitlab-server}</id>
+            <url>https://community.opengroup.org/api/v4/projects/44/packages/maven</url>
+        </repository>
+        <snapshotRepository>
+            <id>${gitlab-server}</id>
+            <url>https://community.opengroup.org/api/v4/projects/44/packages/maven</url>
+        </snapshotRepository>
+    </distributionManagement>
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>2.22.2</version>
+            </plugin>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                        <configuration>
+                            <classifier>spring-boot</classifier>
+                            <mainClass>org.opengroup.osdu.register.provider.azure.RegisterApplication</mainClass>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/RegisterApplication.java b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/RegisterApplication.java
new file mode 100644
index 0000000000000000000000000000000000000000..2045d5be47f2ffd7f98d3d89a0c9f0a378eed6bc
--- /dev/null
+++ b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/RegisterApplication.java
@@ -0,0 +1,46 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.provider.azure;
+
+import org.opengroup.osdu.azure.dependencies.AzureOSDUConfig;
+import org.opengroup.osdu.register.provider.azure.di.AzureBootstrapConfig;
+import org.opengroup.osdu.register.provider.azure.di.CosmosContainerConfig;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
+import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
+import org.springframework.context.annotation.ComponentScan;
+
+@SpringBootApplication(exclude = {
+        MongoAutoConfiguration.class,
+        MongoDataAutoConfiguration.class
+})
+@ComponentScan(value = {
+        "org.opengroup.osdu.register",
+        "org.opengroup.osdu.core",
+        "org.opengroup.osdu.azure"
+})
+public class RegisterApplication {
+
+    public static void main(String[] args) {
+        Class<?>[] sources = new Class<?>[]{
+                RegisterApplication.class,
+                AzureBootstrapConfig.class,
+                AzureOSDUConfig.class,
+                CosmosContainerConfig.class
+        };
+        SpringApplication.run(sources, args);
+    }
+}
diff --git a/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/Util/GoogleServiceAccountImpl.java b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/Util/GoogleServiceAccountImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..b4f61f10b40cb4c0fd544dfc0090ea2585afa88d
--- /dev/null
+++ b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/Util/GoogleServiceAccountImpl.java
@@ -0,0 +1,37 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.provider.azure.Util;
+
+import lombok.SneakyThrows;
+import org.opengroup.osdu.register.utils.IGoogleServiceAccount;
+import org.springframework.stereotype.Component;
+
+@Component
+public class GoogleServiceAccountImpl implements IGoogleServiceAccount {
+
+    @SneakyThrows
+    @Override
+    public String getIdToken(String keyString, String audience) {
+        // TODO Add implementation for generating GSA Tokens
+        return "Token";
+    }
+
+    @SneakyThrows
+    @Override
+    public String getPrivateKeyId(String keyString) {
+        // TODO Add implementation for fetching GSA Private Keys
+        return "Private-Key";
+    }
+}
diff --git a/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/action/ActionDoc.java b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/action/ActionDoc.java
new file mode 100644
index 0000000000000000000000000000000000000000..c7a08b56479213212f66a0830f24a668f765322b
--- /dev/null
+++ b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/action/ActionDoc.java
@@ -0,0 +1,50 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.provider.azure.action;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.opengroup.osdu.register.action.model.Action;
+import org.opengroup.osdu.register.action.model.Filter;
+
+import java.sql.Timestamp;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ActionDoc {
+    private String id;
+    private String name;
+    private String description;
+    private String img;
+    private String url;
+    private String contactEmail;
+    private Timestamp createdOnEpoch;
+    private Filter filter;
+    private String dataPartitionId;
+
+    public ActionDoc(Action action, String dataPartitionId){
+        this.id = action.getId();
+        this.name = action.getName();
+        this.description = action.getDescription();
+        this.img = action.getImg();
+        this.url = action.getUrl();
+        this.contactEmail = action.getContactEmail();
+        this.filter = action.getFilter();
+        this.createdOnEpoch = new Timestamp(System.currentTimeMillis());
+        this.dataPartitionId = dataPartitionId;
+    }
+}
diff --git a/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/action/ActionRepository.java b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/action/ActionRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..577e94fa6d3dec404043f114991b281740b7fc7e
--- /dev/null
+++ b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/action/ActionRepository.java
@@ -0,0 +1,125 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.provider.azure.action;
+
+import com.azure.cosmos.FeedOptions;
+import com.azure.cosmos.SqlParameter;
+import com.azure.cosmos.SqlParameterList;
+import com.azure.cosmos.SqlQuerySpec;
+import org.opengroup.osdu.core.common.model.http.AppException;
+import org.opengroup.osdu.register.action.model.Action;
+import org.opengroup.osdu.register.provider.interfaces.action.IActionRepo;
+import org.opengroup.osdu.azure.CosmosStore;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+import com.google.cloud.Timestamp;
+import java.util.List;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.stream.Collectors;
+import org.opengroup.osdu.core.common.model.http.DpsHeaders;
+
+@Repository
+public class ActionRepository implements IActionRepo {
+
+    private final ReentrantLock mutex = new ReentrantLock();
+
+    @Autowired
+    private String actionContainer;
+
+    @Autowired
+    private CosmosStore cosmosStore;
+
+    @Autowired
+    private DpsHeaders headers;
+
+    @Autowired
+    private String cosmosDBName;
+
+    @Override
+    public Action createAction(Action action) {
+
+        if(action.getId() == null){
+            throw new AppException(400, "Bad Request", "Action id cannot be null");
+        }
+        try {
+            mutex.lock();
+
+            if (exists(action.getId())) {
+                throwConflict();
+            }
+
+            ActionDoc doc = new ActionDoc(action, headers.getPartitionId());
+            cosmosStore.upsertItem(headers.getPartitionId(), cosmosDBName, actionContainer, doc);
+
+        } finally {
+            mutex.unlock();
+        }
+
+        return action;
+    }
+
+    @Override
+    public Action get(String id) {
+
+        ActionDoc doc = cosmosStore.findItem(headers.getPartitionId(), cosmosDBName, actionContainer, id, headers.getPartitionId(), ActionDoc.class)
+                .orElseThrow(() -> new AppException(404, "Not found", String.format("Action with id %s does not exist.", id)));
+
+        return convertToActionClass(doc);
+    }
+
+    @Override
+    public boolean delete(String id) {
+        if(!exists(id)){
+            return false;
+        }
+
+        cosmosStore.deleteItem(headers.getPartitionId(), cosmosDBName, actionContainer, id, headers.getPartitionId());
+        return true;
+    }
+
+    @Override
+    public List<Action> getAllActions() {
+        SqlQuerySpec query = new SqlQuerySpec("SELECT * FROM c where c.dataPartitionId = @partitionId");
+
+        SqlParameterList pars = query.getParameters();
+        pars.add(new SqlParameter("@partitionId", headers.getPartitionId()));
+
+        FeedOptions options = new FeedOptions();
+        return cosmosStore.queryItems(headers.getPartitionId(), cosmosDBName, actionContainer, query, options, ActionDoc.class)
+                .stream().map(this::convertToActionClass).collect(Collectors.toList());
+    }
+
+    private boolean exists(String id) {
+        return cosmosStore.findItem(headers.getPartitionId(), cosmosDBName, actionContainer, id, headers.getPartitionId(), ActionDoc.class).isPresent();
+    }
+
+    private Action convertToActionClass(ActionDoc doc){
+        Action action = new Action();
+        action.setId(doc.getId());
+        action.setName(doc.getName());
+        action.setDescription(doc.getDescription());
+        action.setImg(doc.getImg());
+        action.setUrl(doc.getUrl());
+        action.setContactEmail(doc.getContactEmail());
+        action.setCreatedOnEpoch(Timestamp.of(doc.getCreatedOnEpoch()));
+        action.setFilter(doc.getFilter());
+        return action;
+    }
+
+    private void throwConflict() {
+        throw new AppException(409, "Conflict", "An action already exists with the same message and endpoint combination");
+    }
+
+}
diff --git a/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/ddms/DdmsDoc.java b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/ddms/DdmsDoc.java
new file mode 100644
index 0000000000000000000000000000000000000000..c8341c1a1654653a0c30fade308cc64937cff9cd
--- /dev/null
+++ b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/ddms/DdmsDoc.java
@@ -0,0 +1,55 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.provider.azure.ddms;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.opengroup.osdu.register.ddms.model.Ddms;
+import org.opengroup.osdu.register.ddms.model.RegisteredInterface;
+
+import java.sql.Timestamp;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class DdmsDoc {
+
+    private String id;
+    private String name;
+    private String description;
+    private String contactEmail;
+    private Timestamp createdDateTimeEpoch;
+    private String dataPartitionId;
+    private Set<RegisteredInterfaceDoc> interfaces;
+
+    public DdmsDoc(Ddms ddms, String dataPartitionId){
+        this.id = ddms.getId();
+        this.name = ddms.getName();
+        this.description = ddms.getDescription();
+        this.contactEmail = ddms.getContactEmail();
+        this.createdDateTimeEpoch = new Timestamp(System.currentTimeMillis());
+        this.dataPartitionId = dataPartitionId;
+        this.interfaces = ddms.getInterfaces().stream().map(this::convertToRegisteredInterfaceDoc).collect(Collectors.toSet());
+    }
+
+    private RegisteredInterfaceDoc convertToRegisteredInterfaceDoc(RegisteredInterface item){
+        return new RegisteredInterfaceDoc(item.getEntityType(), item.getSchema());
+    }
+
+}
+
diff --git a/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/ddms/DdmsRepository.java b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/ddms/DdmsRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..e7c4f7d35368eacd385d65d375a334774167de75
--- /dev/null
+++ b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/ddms/DdmsRepository.java
@@ -0,0 +1,130 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.provider.azure.ddms;
+
+import com.azure.cosmos.FeedOptions;
+import com.azure.cosmos.SqlParameter;
+import com.azure.cosmos.SqlParameterList;
+import com.azure.cosmos.SqlQuerySpec;
+import com.google.cloud.Timestamp;
+import org.opengroup.osdu.azure.CosmosStore;
+import org.opengroup.osdu.core.common.model.http.DpsHeaders;
+import org.opengroup.osdu.register.ddms.model.Ddms;
+import org.opengroup.osdu.register.ddms.model.RegisteredInterface;
+import org.opengroup.osdu.register.provider.interfaces.ddms.IDdmsRepository;
+import org.opengroup.osdu.core.common.model.http.AppException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.stream.Collectors;
+
+@Repository
+public class DdmsRepository implements IDdmsRepository {
+
+    private final ReentrantLock mutex = new ReentrantLock();
+
+    @Autowired
+    private String ddmsContainer;
+
+    @Autowired
+    private CosmosStore cosmosStore;
+
+    @Autowired
+    private DpsHeaders headers;
+
+    @Autowired
+    private String cosmosDBName;
+
+    @Override
+    public Ddms create(Ddms ddms) {
+
+        try {
+            mutex.lock();
+
+            if(exists(ddms.getId())){
+                throw new AppException(409, "Conflict", "A DDMS already exists with the same id");
+            }
+            // TODO Size check for Ddms schema [Maximum Size for a CosmosDb item is 2MB]
+
+            DdmsDoc doc = new DdmsDoc(ddms, headers.getPartitionId());
+            cosmosStore.upsertItem(headers.getPartitionId(), cosmosDBName, ddmsContainer, doc);
+
+        } finally {
+            mutex.unlock();
+        }
+
+        return ddms;
+    }
+
+    @Override
+    public Ddms get(String id) {
+
+        DdmsDoc doc = cosmosStore.findItem(headers.getPartitionId(), cosmosDBName, ddmsContainer, id, headers.getPartitionId(), DdmsDoc.class)
+                .orElseThrow(() -> new AppException(404, "Not found", String.format("DDMS with id %s does not exist.", id)));
+
+        return ConvertToDdmsClass(doc);
+    }
+
+    @Override
+    public List<Ddms> query(String type) {
+
+        // Select * not supported, therefore writing all required fields
+        SqlQuerySpec query = new SqlQuerySpec("SELECT f.id, f.name, f.description, f.contactEmail, f.createdDateTimeEpoch, " +
+                "f.interfaces FROM f JOIN c IN f.interfaces where c.entityType = @type and f.dataPartitionId = @partitionId");
+
+        SqlParameterList pars = query.getParameters();
+        pars.add(new SqlParameter("@type", type));
+        pars.add(new SqlParameter("@partitionId", headers.getPartitionId()));
+
+        FeedOptions options = new FeedOptions();
+        return cosmosStore.queryItems(headers.getPartitionId(), cosmosDBName, ddmsContainer, query, options, DdmsDoc.class)
+                .stream().map(this::ConvertToDdmsClass).collect(Collectors.toList());
+    }
+
+    @Override
+    public boolean delete(String id) {
+
+        if(!exists(id)){
+            return false;
+        }
+
+        cosmosStore.deleteItem(headers.getPartitionId(), cosmosDBName, ddmsContainer, id, headers.getPartitionId());
+        return true;
+    }
+
+    private boolean exists(String id) {
+        return cosmosStore.findItem(headers.getPartitionId(), cosmosDBName, ddmsContainer, id, headers.getPartitionId(), DdmsDoc.class).isPresent();
+    }
+
+    private Ddms ConvertToDdmsClass(DdmsDoc doc){
+        Ddms ddms= new Ddms();
+        ddms.setId(doc.getId());
+        ddms.setName(doc.getName());
+        ddms.setDescription(doc.getDescription());
+        ddms.setContactEmail(doc.getContactEmail());
+        ddms.setCreatedDateTimeEpoch(Timestamp.of(doc.getCreatedDateTimeEpoch()));
+        ddms.setInterfaces(doc.getInterfaces().stream().map(this::convertToRegisteredInterfaceClass).collect(Collectors.toSet()));
+        return ddms;
+    }
+
+    private RegisteredInterface convertToRegisteredInterfaceClass(RegisteredInterfaceDoc doc){
+        RegisteredInterface registeredInterface = new RegisteredInterface();
+        registeredInterface.setEntityType(doc.getEntityType());
+        registeredInterface.setSchema(doc.getSchema());
+        return registeredInterface;
+    }
+}
diff --git a/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/ddms/RegisteredInterfaceDoc.java b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/ddms/RegisteredInterfaceDoc.java
new file mode 100644
index 0000000000000000000000000000000000000000..a37fd34f2ff4d7a1d4b7d905cf5b96a493fa72f3
--- /dev/null
+++ b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/ddms/RegisteredInterfaceDoc.java
@@ -0,0 +1,29 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.provider.azure.ddms;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Map;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class RegisteredInterfaceDoc {
+    private String entityType;
+    private Map<String, Object> schema;
+}
diff --git a/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/di/AzureBootstrapConfig.java b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/di/AzureBootstrapConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..3caaa89aa53b06362ba8e3cb8b167cfc1b77eb34
--- /dev/null
+++ b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/di/AzureBootstrapConfig.java
@@ -0,0 +1,71 @@
+//  Copyright © Microsoft Corporation
+//
+//  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.register.provider.azure.di;
+
+import com.azure.security.keyvault.secrets.SecretClient;
+import com.azure.security.keyvault.secrets.models.KeyVaultSecret;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.inject.Named;
+
+@Configuration
+public class AzureBootstrapConfig {
+    @Value("${azure.keyvault.url}")
+    private String keyVaultURL;
+
+    @Value("${azure.cosmosdb.database}")
+    private String cosmosDBName;
+
+    @Bean
+    @Named("KEY_VAULT_URL")
+    public String keyVaultURL() {
+        return keyVaultURL;
+    }
+
+    @Bean
+    @Named("COSMOS_DB_NAME")
+    public String cosmosDBName() {
+        return cosmosDBName;
+    }
+
+    @Bean
+    @Named("COSMOS_ENDPOINT")
+    public String cosmosEndpoint(SecretClient kv) {
+        return getKeyVaultSecret(kv, "cosmos-endpoint");
+    }
+
+    @Bean
+    @Named("COSMOS_KEY")
+    public String cosmosKey(SecretClient kv) {
+        return getKeyVaultSecret(kv, "cosmos-primary-key");
+    }
+
+    String getKeyVaultSecret(SecretClient kv, String secretName) {
+        KeyVaultSecret secret = kv.getSecret(secretName);
+        if (secret == null) {
+            throw new IllegalStateException(String.format("No secret found with name %s", secretName));
+        }
+
+        String secretValue = secret.getValue();
+        if (secretValue == null) {
+            throw new IllegalStateException(String.format(
+                    "Secret unexpectedly missing from KeyVault response for secret with name %s", secretName));
+        }
+
+        return secretValue;
+    }
+}
diff --git a/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/di/CosmosContainerConfig.java b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/di/CosmosContainerConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..497510f5709a71c8eb87ff3861edfe1d413f6e9e
--- /dev/null
+++ b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/di/CosmosContainerConfig.java
@@ -0,0 +1,45 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.provider.azure.di;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+
+public class CosmosContainerConfig {
+
+    @Value("${registerAction.container.name}")
+    private String actionContainerName;
+
+    @Value("${registerDdms.container.name}")
+    private String ddmsContainerName;
+
+    @Value("${registerSubscription.container.name}")
+    private String subscriptionContainerName;
+
+    @Bean
+    public String actionContainer(){
+        return actionContainerName;
+    }
+
+    @Bean
+    public String ddmsContainer(){
+        return ddmsContainerName;
+    }
+
+    @Bean
+    public String subscriptionContainer(){
+        return subscriptionContainerName;
+    }
+}
\ No newline at end of file
diff --git a/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/security/AADSecurityConfig.java b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/security/AADSecurityConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..9c658795fe86dabd08f44c7f7fd8edd48f30d9c2
--- /dev/null
+++ b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/security/AADSecurityConfig.java
@@ -0,0 +1,52 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.provider.azure.security;
+
+import com.microsoft.azure.spring.autoconfigure.aad.AADAppRoleStatelessAuthenticationFilter;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+import javax.inject.Inject;
+
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+public class AADSecurityConfig extends WebSecurityConfigurerAdapter {
+    @Inject
+    private AADAppRoleStatelessAuthenticationFilter appRoleAuthFilter;
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        http
+                .csrf().disable()
+                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)
+                .and()
+                .authorizeRequests()
+                .antMatchers("/", "/index.html",
+                        "/v2/api-docs",
+                        "/configuration/ui",
+                        "/swagger-resources/**",
+                        "/configuration/security",
+                        "/swagger",
+                        "/swagger-ui.html",
+                        "/webjars/**").permitAll()
+                .anyRequest().authenticated()
+                .and()
+                .addFilterBefore(appRoleAuthFilter, UsernamePasswordAuthenticationFilter.class);
+    }
+}
\ No newline at end of file
diff --git a/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/security/WhoamiController.java b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/security/WhoamiController.java
new file mode 100644
index 0000000000000000000000000000000000000000..db37944c350d5646085e318ddd2da9554aa3501b
--- /dev/null
+++ b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/security/WhoamiController.java
@@ -0,0 +1,38 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.provider.azure.security;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+@Controller
+public class WhoamiController {
+    @RequestMapping(value = "/whoami")
+    @ResponseBody
+    public String whoami() {
+        final Authentication auth = SecurityContextHolder.getContext().getAuthentication();
+
+        String userName = auth.getName();
+        String roles = String.valueOf(auth.getAuthorities());
+        String details = String.valueOf(auth.getPrincipal());
+
+        return "user: " + userName + "<BR>" +
+                "roles: " + roles + "<BR>" +
+                "details: " + details + "<BR>";
+    }
+}
diff --git a/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/subscriber/SubscriptionDoc.java b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/subscriber/SubscriptionDoc.java
new file mode 100644
index 0000000000000000000000000000000000000000..8d0d375c932f3849964db01e0e13599d1bf9aede
--- /dev/null
+++ b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/subscriber/SubscriptionDoc.java
@@ -0,0 +1,53 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.provider.azure.subscriber;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.opengroup.osdu.register.subscriber.model.Subscription;
+
+import java.sql.Timestamp;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class SubscriptionDoc {
+    private String id;
+    private String name;
+    private String description;
+    private String topic;
+    private String pushEndpoint;
+    private String createdBy;
+    private Timestamp createdOnEpoch;
+    private String notificationId;
+    private String secretType;
+    private String secretValue;
+    private String dataPartitionId;
+
+    public SubscriptionDoc(Subscription subscription, String dataPartitionId){
+        this.id = subscription.getId();
+        this.name = subscription.getName();
+        this.description = subscription.getDescription();
+        this.topic = subscription.getTopic();
+        this.pushEndpoint = subscription.getPushEndpoint();
+        this.createdBy = subscription.getCreatedBy();
+        this.createdOnEpoch = new Timestamp(System.currentTimeMillis());
+        this.notificationId = subscription.getNotificationId();
+        this.secretType = subscription.getSecret().getSecretType();
+        this.secretValue = subscription.getSecret().toString();
+        this.dataPartitionId = dataPartitionId;
+    }
+}
diff --git a/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/subscriber/SubscriptionRepository.java b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/subscriber/SubscriptionRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..3616cc98fa603f28d8abfea06ec3c3e087588fe4
--- /dev/null
+++ b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/subscriber/SubscriptionRepository.java
@@ -0,0 +1,154 @@
+package org.opengroup.osdu.register.provider.azure.subscriber;
+
+import com.azure.cosmos.FeedOptions;
+import com.azure.cosmos.SqlParameter;
+import com.azure.cosmos.SqlParameterList;
+import com.azure.cosmos.SqlQuerySpec;
+import com.google.cloud.Timestamp;
+import org.opengroup.osdu.azure.CosmosStore;
+import org.opengroup.osdu.core.common.model.http.AppException;
+import org.opengroup.osdu.core.common.model.http.DpsHeaders;
+import org.opengroup.osdu.register.subscriber.model.*;
+import org.opengroup.osdu.register.provider.interfaces.subscriber.ISubscriptionRepository;
+import org.opengroup.osdu.register.utils.Constants;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Repository
+public class SubscriptionRepository implements ISubscriptionRepository {
+
+    @Autowired
+    private String subscriptionContainer;
+
+    @Autowired
+    private CosmosStore cosmosStore;
+
+    @Autowired
+    private DpsHeaders headers;
+
+    @Autowired
+    private String cosmosDBName;
+
+    @Override
+    public Subscription create(Subscription input) throws Exception {
+
+        // TODO Validate if is there any upper limit required for maximum number of subscriptions for a tenant
+
+        if(exists(input.getId())){
+            throw new AppException(409, "Conflict", "A subscriber already exists with the same topic and endpoint combination");
+        }
+
+        // TODO Encryption required before storing the secret or Do we need Keyvault to know the secrets
+
+        SubscriptionDoc doc = new SubscriptionDoc(input, headers.getPartitionId());
+        cosmosStore.upsertItem(headers.getPartitionId(), cosmosDBName, subscriptionContainer, doc);
+
+        try{
+            // TODO Add the flow to create subscription to the given topic
+
+            return input;
+        }
+        catch (Exception e){
+            cosmosStore.deleteItem(headers.getPartitionId(), cosmosDBName, subscriptionContainer, input.getId(), headers.getPartitionId());
+            throw new AppException(500, "Server Error", "Unexpected error creating subscription", e);
+        }
+    }
+
+    @Override
+    public Subscription get(String id) {
+
+        SubscriptionDoc doc = cosmosStore.findItem(headers.getPartitionId(), cosmosDBName, subscriptionContainer, id, headers.getPartitionId(), SubscriptionDoc.class)
+                .orElseThrow(() -> new AppException(404, "Not found", String.format("Subscriber with id %s does not exist.", id)));
+
+        return convertToSubscriptionClass(doc);
+    }
+
+    @Override
+    public List<Subscription> query(String notificationId) {
+
+        SqlQuerySpec query = new SqlQuerySpec("SELECT * from c where c.notificationId = @notificationId and c.dataPartitionId = @partitionId");
+
+        SqlParameterList pars = query.getParameters();
+        pars.add(new SqlParameter("@notificationId", notificationId));
+        pars.add(new SqlParameter("@partitionId", headers.getPartitionId()));
+
+        FeedOptions options = new FeedOptions();
+
+        return cosmosStore.queryItems(headers.getPartitionId(), cosmosDBName, subscriptionContainer, query, options, SubscriptionDoc.class).stream()
+                .map(this::convertToSubscriptionClass)
+                .collect(Collectors.toList());
+
+    }
+
+    @Override
+    public boolean delete(String id) {
+
+        if(!exists(id)){
+            return false;
+        }
+
+        try{
+            // TODO Add flow for deleting the subscription to the topic
+
+            cosmosStore.deleteItem(headers.getPartitionId(), cosmosDBName, subscriptionContainer, id, headers.getPartitionId());
+            return true;
+        }
+        catch (Exception e){
+            throw new AppException(500, "Server Error", "Unexpected error deleting subscription.", e);
+        }
+
+    }
+
+    @Override
+    public boolean patch(Subscription subscription, Secret secret){
+        return updateSecret(subscription, secret);
+    }
+
+    @Override
+    public List<Subscription> getAll() throws Exception {
+
+        SqlQuerySpec query = new SqlQuerySpec("SELECT * from c where c.dataPartitionId = @partitionId");
+
+        SqlParameterList pars = query.getParameters();
+        pars.add(new SqlParameter("@partitionId", headers.getPartitionId()));
+
+        FeedOptions options = new FeedOptions();
+
+        return cosmosStore.queryItems(headers.getPartitionId(), cosmosDBName, subscriptionContainer, query, options, SubscriptionDoc.class).stream()
+                .map(this::convertToSubscriptionClass)
+                .collect(Collectors.toList());
+    }
+
+    private boolean updateSecret(Subscription subscription, Secret secret) {
+        SubscriptionDoc doc = new SubscriptionDoc(subscription, headers.getPartitionId());
+        doc.setSecretType(secret.getSecretType());
+        doc.setSecretValue(secret.toString());
+
+        cosmosStore.upsertItem(headers.getPartitionId(), cosmosDBName, subscriptionContainer, doc);
+        return true;
+    }
+
+    private boolean exists(String id) {
+        return cosmosStore.findItem(headers.getPartitionId(), cosmosDBName, subscriptionContainer, id, headers.getPartitionId(), SubscriptionDoc.class).isPresent();
+    }
+
+    private Subscription convertToSubscriptionClass(SubscriptionDoc doc) {
+        String secretValue = doc.getSecretValue();
+        Secret secret;
+        if (doc.getSecretType().equals(Constants.GSASecret)) {
+            GsaSecret gsaSecret = new GsaSecret();
+            String[] splitSecret = secretValue.split("`");
+            gsaSecret.setValue(new GsaSecretValue(splitSecret[0], splitSecret[1]));
+            secret = gsaSecret;
+        } else {
+            HmacSecret hmacSecret = new HmacSecret();
+            hmacSecret.setValue(secretValue);
+            secret = hmacSecret;
+        }
+        return new Subscription(doc.getId(), doc.getName(),doc.getDescription(), doc.getTopic(), doc.getPushEndpoint(),
+                doc.getCreatedBy(), Timestamp.of(doc.getCreatedOnEpoch()), doc.getNotificationId(), secret);
+    }
+}
diff --git a/provider/register-azure/src/main/resources/application.properties b/provider/register-azure/src/main/resources/application.properties
new file mode 100644
index 0000000000000000000000000000000000000000..a7e53f05ea460fe8b43c8838ab6f7b0a836e594f
--- /dev/null
+++ b/provider/register-azure/src/main/resources/application.properties
@@ -0,0 +1,45 @@
+#
+# Copyright © Microsoft Corporation
+#
+# 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.
+#
+LOG_PREFIX=register
+
+server.servlet.contextPath=/api/register/v1
+service.domain.name=${service_domain_name}
+
+# Azure AD configuration
+azure.activedirectory.client-id=${aad_client_id}
+azure.activedirectory.AppIdUri=api://${azure.activedirectory.client-id}
+azure.activedirectory.session-stateless=true
+
+# Azure CosmosDB configuration
+azure.cosmosdb.database=${cosmosdb_database}
+
+# Azure KeyVault configuration
+azure.keyvault.url=${KEYVAULT_URI}
+
+# Azure App Insights configuration
+azure.application-insights.instrumentation-key=${appinsights_key}
+
+# Application name
+spring.application.name=register-azure
+
+# Cosmosdb container name
+registerAction.container.name=RegisterAction
+registerDdms.container.name=RegisterDdms
+registerSubscription.container.name=RegisterSubscription
+
+#logging configuration
+logging.transaction.enabled=true
+logging.slf4jlogger.enabled=true
diff --git a/provider/register-azure/src/test/java/org/opengroup/osdu/register/provider/azure/action/ActionRepositoryTest.java b/provider/register-azure/src/test/java/org/opengroup/osdu/register/provider/azure/action/ActionRepositoryTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..46e570b4fbc30564b8ce6721030e7a119373cefd
--- /dev/null
+++ b/provider/register-azure/src/test/java/org/opengroup/osdu/register/provider/azure/action/ActionRepositoryTest.java
@@ -0,0 +1,200 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.provider.azure.action;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.opengroup.osdu.azure.CosmosStore;
+import org.opengroup.osdu.core.common.model.http.AppException;
+import org.opengroup.osdu.core.common.model.http.DpsHeaders;
+import org.opengroup.osdu.register.action.model.Action;
+import org.opengroup.osdu.register.action.model.Filter;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+@ExtendWith(MockitoExtension.class)
+public class ActionRepositoryTest {
+
+    private static final String dataPartitionId = "data-partition-id";
+    private static final String actionId = "id-1";
+
+    @Mock
+    private DpsHeaders headers;
+
+    @Mock
+    private CosmosStore cosmosStore;
+
+    @InjectMocks
+    private ActionRepository repo;
+
+    @BeforeEach
+    void init() {
+        lenient().doReturn(dataPartitionId).when(headers).getPartitionId();
+    }
+
+    @Test
+    public void createAction_throws400_whenNullId() {
+        Action action = createAction();
+        action.setId(null);
+
+        AppException exception = assertThrows(AppException.class, () -> {
+            repo.createAction(action);
+        });
+        assertEquals(400, exception.getError().getCode());
+        assertEquals("Bad Request", exception.getError().getReason());
+        assertEquals("Action id cannot be null", exception.getError().getMessage());
+    }
+
+    @Test
+    public void createAction_throws409_whenIdExists() {
+        Action action = createAction();
+        Optional<ActionDoc> cosmosItem = Optional.of(new ActionDoc());
+
+        doReturn(cosmosItem).when(cosmosStore).findItem(anyString(), any(), any(), anyString(), anyString(), any());
+
+        AppException exception = assertThrows(AppException.class, () -> {
+            repo.createAction(action);
+        });
+
+        assertEquals(409, exception.getError().getCode());
+        assertEquals("Conflict", exception.getError().getReason());
+        assertEquals("An action already exists with the same message and endpoint combination", exception.getError().getMessage());
+        verify(cosmosStore, times(1)).findItem(dataPartitionId, null, null, actionId, dataPartitionId, ActionDoc.class);
+    }
+
+    @Test
+    public void createAction_documentInsertedSuccessfully() {
+        Action action = createAction();
+
+        Optional<ActionDoc> cosmosItem = Optional.empty();
+        doReturn(cosmosItem).when(cosmosStore).findItem(anyString(), any(), any(), anyString(), anyString(), any());
+        doNothing().when(cosmosStore).upsertItem(anyString(), any(), any(), any());
+
+        Action output = repo.createAction(action);
+
+        assertEquals(action, output);
+        verify(cosmosStore, times(1)).findItem(dataPartitionId, null, null, actionId, dataPartitionId, ActionDoc.class);
+    }
+
+    @Test
+    public void getAction_throws404_whenIdNotFound() {
+
+        doReturn(Optional.empty()).when(cosmosStore).findItem(anyString(), any(), any(), anyString(), anyString(), any());
+
+        AppException exception = assertThrows(AppException.class, () -> {
+            repo.get(actionId);
+        });
+
+        assertEquals(404, exception.getError().getCode());
+        assertEquals("Not found", exception.getError().getReason());
+        assertEquals("Action with id id-1 does not exist.", exception.getError().getMessage());
+        verify(cosmosStore, times(1)).findItem(dataPartitionId, null, null, actionId, dataPartitionId, ActionDoc.class);
+    }
+
+    @Test
+    public void getAction_itemRetrievedSuccessfully() {
+
+        Action action = createAction();
+        ActionDoc doc = new ActionDoc(action, dataPartitionId);
+
+        doReturn(Optional.of(doc)).when(cosmosStore).findItem(anyString(), any(), any(), anyString(), anyString(), any());
+
+        Action output = repo.get(actionId);
+
+        assertEquals(action, output);
+        verify(cosmosStore, times(1)).findItem(dataPartitionId, null, null, actionId, dataPartitionId, ActionDoc.class);
+    }
+
+    @Test
+    public void deleteAction_returnsFalse_whenIdNotFound() {
+
+        doReturn(Optional.empty()).when(cosmosStore).findItem(anyString(), any(), any(), anyString(), anyString(), any());
+
+        boolean output = repo.delete(actionId);
+
+        assertFalse(output);
+        verify(cosmosStore, times(1)).findItem(dataPartitionId, null, null, actionId, dataPartitionId, ActionDoc.class);
+    }
+
+    @Test
+    public void deleteAction_returnsTrue_whenDeletedSuccessfully() {
+
+        Action action = createAction();
+        ActionDoc doc = new ActionDoc(action, dataPartitionId);
+
+        Optional<ActionDoc> cosmosItem = Optional.of(doc);
+        doReturn(cosmosItem).when(cosmosStore).findItem(anyString(), any(), any(), anyString(), anyString(), any());
+
+        boolean output = repo.delete(actionId);
+
+        assertTrue(output);
+        verify(cosmosStore, times(1)).findItem(dataPartitionId, null, null, actionId, dataPartitionId, ActionDoc.class);
+        verify(cosmosStore, times(1)).deleteItem(dataPartitionId, null, null, actionId, dataPartitionId);
+    }
+
+    @Test
+    public void getAllActions_returnAllItemsSuccessfully() {
+
+        Action action1 = createAction();
+        Action action2 = createAction();
+        action2.setId("id-2");
+
+        ActionDoc doc1 = new ActionDoc(action1, dataPartitionId);
+        ActionDoc doc2 = new ActionDoc(action2, dataPartitionId);
+
+        List<Action> actions = Stream.of(action1, action2).collect(Collectors.toList());
+        List<ActionDoc> actionDocs = Stream.of(doc1, doc2).collect(Collectors.toList());
+
+        doReturn(actionDocs).when(cosmosStore).queryItems(anyString(), any(), any(), any(), any(), any());
+
+        List<Action> output = repo.getAllActions();
+
+        actions.get(0).setCreatedOnEpoch(output.get(0).getCreatedOnEpoch());
+        actions.get(1).setCreatedOnEpoch(output.get(1).getCreatedOnEpoch());
+
+        assertEquals(actions, output);
+    }
+
+    private Action createAction() {
+        Action action = new Action();
+        action.setId(actionId);
+        action.setName("name");
+        action.setDescription("description");
+        action.setImg("https://mycdn.com/img.png");
+        action.setUrl("https://myapp.osdu.opengroup.org/action/{id}/{data.project}");
+        action.setFilter(new Filter());
+
+        return action;
+    }
+}
\ No newline at end of file
diff --git a/provider/register-azure/src/test/java/org/opengroup/osdu/register/provider/azure/ddms/DdmsRepositoryTest.java b/provider/register-azure/src/test/java/org/opengroup/osdu/register/provider/azure/ddms/DdmsRepositoryTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..1edd43af47e5e7a815aa7d8473066da44a7128c1
--- /dev/null
+++ b/provider/register-azure/src/test/java/org/opengroup/osdu/register/provider/azure/ddms/DdmsRepositoryTest.java
@@ -0,0 +1,191 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.provider.azure.ddms;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.opengroup.osdu.azure.CosmosStore;
+import org.opengroup.osdu.core.common.model.http.AppException;
+import org.opengroup.osdu.core.common.model.http.DpsHeaders;
+import org.opengroup.osdu.register.ddms.model.Ddms;
+import org.opengroup.osdu.register.ddms.model.RegisteredInterface;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+@ExtendWith(MockitoExtension.class)
+public class DdmsRepositoryTest {
+
+    private static final String dataPartitionId = "data-partition-id";
+    private static final String ddmsId = "id-1";
+
+    @Mock
+    private DpsHeaders headers;
+
+    @Mock
+    private CosmosStore cosmosStore;
+
+    @InjectMocks
+    private DdmsRepository repo;
+
+    @BeforeEach
+    void init() {
+        lenient().doReturn(dataPartitionId).when(headers).getPartitionId();
+    }
+
+    @Test
+    public void createDdms_throws409_whenIdExists() {
+        Ddms ddms = createDdms();
+        Optional<DdmsDoc> cosmosItem = Optional.of(new DdmsDoc());
+
+        doReturn(cosmosItem).when(cosmosStore).findItem(anyString(), any(), any(), anyString(), anyString(), any());
+
+        AppException exception = assertThrows(AppException.class, () -> {
+            repo.create(ddms);
+        });
+
+        assertEquals(409, exception.getError().getCode());
+        assertEquals("Conflict", exception.getError().getReason());
+        assertEquals("A DDMS already exists with the same id", exception.getError().getMessage());
+        verify(cosmosStore, times(1)).findItem(dataPartitionId, null, null, ddmsId, dataPartitionId, DdmsDoc.class);
+    }
+
+    @Test
+    public void createDdms_documentInsertedSuccessfully() {
+        Ddms ddms = createDdms();
+
+        Optional<DdmsDoc> cosmosItem = Optional.empty();
+        doReturn(cosmosItem).when(cosmosStore).findItem(anyString(), any(), any(), anyString(), anyString(), any());
+        doNothing().when(cosmosStore).upsertItem(anyString(), any(), any(), any());
+
+        Ddms output = repo.create(ddms);
+
+        assertEquals(ddms, output);
+        verify(cosmosStore, times(1)).findItem(dataPartitionId, null, null, ddmsId, dataPartitionId, DdmsDoc.class);
+    }
+
+    @Test
+    public void getDdms_throws404_whenIdNotFound() {
+
+        doReturn(Optional.empty()).when(cosmosStore).findItem(anyString(), any(), any(), anyString(), anyString(), any());
+
+        AppException exception = assertThrows(AppException.class, () -> {
+            repo.get(ddmsId);
+        });
+
+        assertEquals(404, exception.getError().getCode());
+        assertEquals("Not found", exception.getError().getReason());
+        assertEquals("DDMS with id id-1 does not exist.", exception.getError().getMessage());
+        verify(cosmosStore, times(1)).findItem(dataPartitionId, null, null, ddmsId, dataPartitionId, DdmsDoc.class);
+    }
+
+    @Test
+    public void getDdms_itemRetrievedSuccessfully() {
+
+        Ddms ddms = createDdms();
+        DdmsDoc doc = new DdmsDoc(ddms, dataPartitionId);
+
+        doReturn(Optional.of(doc)).when(cosmosStore).findItem(anyString(), any(), any(), anyString(), anyString(), any());
+
+        Ddms output = repo.get(ddmsId);
+
+        assertEquals(ddms, output);
+        verify(cosmosStore, times(1)).findItem(dataPartitionId, null, null, ddmsId, dataPartitionId, DdmsDoc.class);
+    }
+
+    @Test
+    public void deleteDdms_returnsFalse_whenIdNotFound() {
+
+        doReturn(Optional.empty()).when(cosmosStore).findItem(anyString(), any(), any(), anyString(), anyString(), any());
+
+        boolean output = repo.delete(ddmsId);
+
+        assertFalse(output);
+        verify(cosmosStore, times(1)).findItem(dataPartitionId, null, null, ddmsId, dataPartitionId, DdmsDoc.class);
+    }
+
+    @Test
+    public void deleteDdms_returnsTrue_whenDeletedSuccessfully() {
+
+        Ddms ddms = createDdms();
+        DdmsDoc doc = new DdmsDoc(ddms, dataPartitionId);
+
+        Optional<DdmsDoc> cosmosItem = Optional.of(doc);
+        doReturn(cosmosItem).when(cosmosStore).findItem(anyString(), any(), any(), anyString(), anyString(), any());
+
+        boolean output = repo.delete(ddmsId);
+
+        assertTrue(output);
+        verify(cosmosStore, times(1)).findItem(dataPartitionId, null, null, ddmsId, dataPartitionId, DdmsDoc.class);
+        verify(cosmosStore, times(1)).deleteItem(dataPartitionId, null, null, ddmsId, dataPartitionId);
+    }
+
+    @Test
+    public void queryDdms_returnItemsSuccessfully() {
+
+        Ddms ddms1 = createDdms();
+        Ddms ddms2 = createDdms();
+        ddms2.setId("id-2");
+
+        DdmsDoc doc1 = new DdmsDoc(ddms1, dataPartitionId);
+        DdmsDoc doc2 = new DdmsDoc(ddms2, dataPartitionId);
+
+        List<Ddms> ddmsList = Stream.of(ddms1, ddms2).collect(Collectors.toList());
+        List<DdmsDoc> ddmsDocList = Stream.of(doc1, doc2).collect(Collectors.toList());
+
+        doReturn(ddmsDocList).when(cosmosStore).queryItems(anyString(), any(), any(), any(), any(), any());
+
+        List<Ddms> output = repo.query("type");
+
+        ddmsList.get(0).setCreatedDateTimeEpoch(output.get(0).getCreatedDateTimeEpoch());
+        ddmsList.get(1).setCreatedDateTimeEpoch(output.get(1).getCreatedDateTimeEpoch());
+
+        assertEquals(ddmsList, output);
+    }
+
+    private Ddms createDdms() {
+        Ddms ddms = new Ddms();
+        RegisteredInterface ri = new RegisteredInterface();
+        ri.setEntityType("type");
+        ri.setSchema(Collections.singletonMap("first", "second"));
+
+        ddms.setId(ddmsId);
+        ddms.setName("mock-name");
+        ddms.setDescription("mock-description");
+        ddms.setContactEmail("mock-contactEmail");
+        ddms.getInterfaces().add(ri);
+        return ddms;
+    }
+
+}
diff --git a/testing/register-test-azure/Readme.md b/testing/register-test-azure/Readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..9342a00bda976d6881f7c9984f8d06a39f6e33ed
--- /dev/null
+++ b/testing/register-test-azure/Readme.md
@@ -0,0 +1,43 @@
+Copyright 2017-2020, Schlumberger
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+# Register Azure integration tests
+
+Register integration tests are refactored so that the business logic for integration tests resides in the `register-test-core` module and provider specific logic and execution steps reside in provider module (e.g. `register-test-azure`). To run the integration tests, the core module is built first and then the provider module is executed. Please read further to know more details.
+
+### Dependencies needed to run the integration tests 
+* JDK8
+* Maven
+* Azure Devops access to slb-des-ext-collaboration organization. You need to generate a PAT that can access dependencies held in the Azure artifacts
+* Values for the following environment variables in Config.java
+  
+  ```
+   INTEGRATION_TESTER (System identity to assume for API calls. Note: this user must have entitlements configured already)
+   TESTER_SERVICEPRINCIPAL_SECRET (service account key which has admins api access)
+   NO_DATA_ACCESS_TESTER (Secret for $INTEGRATION_TESTER)
+   NO_DATA_ACCESS_TESTER_SERVICEPRINCIPAL_SECRET (Secret for $NO_DATA_ACCESS_TESTER)
+   ENVIRONMENT ('local' for local testing or 'dev' for dev testing)
+   AZURE_AD_TENANT_ID (AD tenant to authenticate users from)
+   AZURE_AD_APP_RESOURCE_ID (AAD client application ID)
+   DOMAIN (OSDU R2 to run tests under)
+   SUBSCRIBER_SECRET (sensitive secret to run HMAC tests)
+   REGISTER_BASE_URL (register service endpoint)
+   
+   ```
+
+  Above variables should be configured in the release pipeline to run integration tests. You should also replace them with proper values if you wish to run tests locally.
+
+### Commands to run tests
+* Integration tests are refactored into two pieces: Core and Provider. Core contains business logic for tests and is a dependency for executing the tests from provider module. To build the core module, simply navigate to `register-test-core` directory and run `mvn clean install`. This will build the core module
+* Next use the Junit template in IntelliJ to run all the tests in register-test-azure [ Use the EnvFile plugin to use environment variables directly from .env or .json/.yaml file]
diff --git a/testing/register-test-azure/pom.xml b/testing/register-test-azure/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..796478b4f0b488e5396022c20fb84aeb20137f45
--- /dev/null
+++ b/testing/register-test-azure/pom.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright 2017-2020 Schlumberger
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.opengroup.osdu.register</groupId>
+    <artifactId>register-test-azure</artifactId>
+    <version>1.0-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <description>Register service Azure integration tests </description>
+
+    <properties>
+        <maven.compiler.target>1.8</maven.compiler.target>
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>1.18.8</version>
+        </dependency>
+        <dependency>
+            <groupId>javax.json</groupId>
+            <artifactId>javax.json-api</artifactId>
+            <version>1.1.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish</groupId>
+            <artifactId>javax.json</artifactId>
+            <version>1.1.2</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.oauth-client</groupId>
+            <artifactId>google-oauth-client</artifactId>
+            <version>1.30.2</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.api-client</groupId>
+            <artifactId>google-api-client</artifactId>
+            <version>1.30.2</version>
+            <scope>compile</scope>
+            <exclusions>
+                <exclusion>
+                    <artifactId>guava-jdk5</artifactId>
+                    <groupId>com.google.guava</groupId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.fasterxml.jackson.core</groupId>
+                    <artifactId>jackson-core</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.jersey</groupId>
+            <artifactId>jersey-client</artifactId>
+            <version>1.19.4</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>2.8.5</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.auth</groupId>
+            <artifactId>google-auth-library-oauth2-http</artifactId>
+            <version>0.15.0</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+            <version>0.9.1</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>27.1-jre</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opengroup.osdu.register</groupId>
+            <artifactId>register-test-core</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.12</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>au.com.dius</groupId>
+            <artifactId>pact-jvm-provider-junit_2.12</artifactId>
+            <version>3.5.5</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest</artifactId>
+            <version>2.1</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <repositories>
+        <repository>
+            <id>${gitlab-server}</id>
+            <url>https://community.opengroup.org/api/v4/groups/17/-/packages/maven</url>
+        </repository>
+    </repositories>
+
+    <distributionManagement>
+        <repository>
+            <id>${gitlab-server}</id>
+            <url>https://community.opengroup.org/api/v4/projects/157/packages/maven</url>
+        </repository>
+        <snapshotRepository>
+            <id>${gitlab-server}</id>
+            <url>https://community.opengroup.org/api/v4/projects/157/packages/maven</url>
+        </snapshotRepository>
+    </distributionManagement>
+</project>
diff --git a/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/action/TestCreateActionApi.java b/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/action/TestCreateActionApi.java
new file mode 100644
index 0000000000000000000000000000000000000000..61ae03f55fbea7a7863d96cd41853b6bd71b3103
--- /dev/null
+++ b/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/action/TestCreateActionApi.java
@@ -0,0 +1,45 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.action;
+
+import com.sun.jersey.api.client.ClientResponse;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.opengroup.osdu.register.util.AzureTestUtils;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestCreateActionApi extends CreateActionApiTest {
+
+    @Before
+    @Override
+    public void setup() {
+        this.testUtils = new AzureTestUtils();
+    }
+
+    @After
+    @Override
+    public void tearDown() {
+        this.testUtils = null;
+    }
+
+    @Test
+    @Override
+    public void should_return400_when_makingHttpRequestWithoutToken() throws Exception {
+        ClientResponse response = descriptor.run(getId(), "");
+        assertEquals(error(response.getEntity(String.class)), 403, response.getStatus());
+    }
+}
diff --git a/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/action/TestDeleteActionApi.java b/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/action/TestDeleteActionApi.java
new file mode 100644
index 0000000000000000000000000000000000000000..4568b57f7c76ab5a22edac92932407a1ad02c2b6
--- /dev/null
+++ b/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/action/TestDeleteActionApi.java
@@ -0,0 +1,45 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.action;
+
+import com.sun.jersey.api.client.ClientResponse;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.opengroup.osdu.register.util.AzureTestUtils;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestDeleteActionApi extends DeleteActionApiTest {
+
+    @Before
+    @Override
+    public void setup() {
+        this.testUtils = new AzureTestUtils();
+    }
+
+    @After
+    @Override
+    public void tearDown() {
+        this.testUtils = null;
+    }
+
+    @Test
+    @Override
+    public void should_return400_when_makingHttpRequestWithoutToken() throws Exception {
+        ClientResponse response = descriptor.run(getId(), "");
+        assertEquals(error(response.getEntity(String.class)), 403, response.getStatus());
+    }
+}
diff --git a/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/action/TestGetActionByIdApi.java b/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/action/TestGetActionByIdApi.java
new file mode 100644
index 0000000000000000000000000000000000000000..0361e167677ebc80b87d73cda50c737cf7cf0178
--- /dev/null
+++ b/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/action/TestGetActionByIdApi.java
@@ -0,0 +1,45 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.action;
+
+import com.sun.jersey.api.client.ClientResponse;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.opengroup.osdu.register.util.AzureTestUtils;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestGetActionByIdApi extends GetActionByIdApiTest {
+
+    @Before
+    @Override
+    public void setup() {
+        this.testUtils = new AzureTestUtils();
+    }
+
+    @After
+    @Override
+    public void tearDown() {
+        this.testUtils = null;
+    }
+
+    @Test
+    @Override
+    public void should_return400_when_makingHttpRequestWithoutToken() throws Exception {
+        ClientResponse response = descriptor.run(getId(), "");
+        assertEquals(error(response.getEntity(String.class)), 403, response.getStatus());
+    }
+}
diff --git a/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/action/TestRetrieveActionApi.java b/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/action/TestRetrieveActionApi.java
new file mode 100644
index 0000000000000000000000000000000000000000..43e12504e6759e75b8fb9c6e67816aa74569ac99
--- /dev/null
+++ b/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/action/TestRetrieveActionApi.java
@@ -0,0 +1,45 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.action;
+
+import com.sun.jersey.api.client.ClientResponse;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.opengroup.osdu.register.util.AzureTestUtils;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestRetrieveActionApi extends RetrieveActionApiTest {
+
+    @Before
+    @Override
+    public void setup() {
+        this.testUtils = new AzureTestUtils();
+    }
+
+    @After
+    @Override
+    public void tearDown() {
+        this.testUtils = null;
+    }
+
+    @Test
+    @Override
+    public void should_return400_when_makingHttpRequestWithoutToken() throws Exception {
+        ClientResponse response = descriptor.run(getId(), "");
+        assertEquals(error(response.getEntity(String.class)), 403, response.getStatus());
+    }
+}
diff --git a/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/ddms/TestCreateRegistrationApi.java b/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/ddms/TestCreateRegistrationApi.java
new file mode 100644
index 0000000000000000000000000000000000000000..ed01212993a00a9ab4175e6b86545939fd0dfc08
--- /dev/null
+++ b/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/ddms/TestCreateRegistrationApi.java
@@ -0,0 +1,45 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.ddms;
+
+import com.sun.jersey.api.client.ClientResponse;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.opengroup.osdu.register.util.AzureTestUtils;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestCreateRegistrationApi extends CreateRegistrationApiTest {
+
+    @Before
+    @Override
+    public void setup() {
+        this.testUtils = new AzureTestUtils();
+    }
+
+    @After
+    @Override
+    public void tearDown() {
+        this.testUtils = null;
+    }
+
+    @Test
+    @Override
+    public void should_return400_when_makingHttpRequestWithoutToken() throws Exception {
+        ClientResponse response = descriptor.run(getId(), "");
+        assertEquals(error(response.getEntity(String.class)), 403, response.getStatus());
+    }
+}
diff --git a/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/ddms/TestDeleteRegistrationApi.java b/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/ddms/TestDeleteRegistrationApi.java
new file mode 100644
index 0000000000000000000000000000000000000000..bb29ed00edd49ded73c61238bbc3d1c739b5e6dd
--- /dev/null
+++ b/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/ddms/TestDeleteRegistrationApi.java
@@ -0,0 +1,45 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.ddms;
+
+import com.sun.jersey.api.client.ClientResponse;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.opengroup.osdu.register.util.AzureTestUtils;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestDeleteRegistrationApi extends DeleteRegistrationApiTest {
+
+    @Before
+    @Override
+    public void setup() {
+        this.testUtils = new AzureTestUtils();
+    }
+
+    @After
+    @Override
+    public void tearDown() {
+        this.testUtils = null;
+    }
+
+    @Test
+    @Override
+    public void should_return400_when_makingHttpRequestWithoutToken() throws Exception {
+        ClientResponse response = descriptor.run(getId(), "");
+        assertEquals(error(response.getEntity(String.class)), 403, response.getStatus());
+    }
+}
diff --git a/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/ddms/TestGetConsumptionByIdApi.java b/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/ddms/TestGetConsumptionByIdApi.java
new file mode 100644
index 0000000000000000000000000000000000000000..9885eb911f2ffac4bd61e03222be4b0befb96722
--- /dev/null
+++ b/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/ddms/TestGetConsumptionByIdApi.java
@@ -0,0 +1,45 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.ddms;
+
+import com.sun.jersey.api.client.ClientResponse;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.opengroup.osdu.register.util.AzureTestUtils;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestGetConsumptionByIdApi extends GetConsumptionByIdApiTest {
+
+    @Before
+    @Override
+    public void setup() {
+        this.testUtils = new AzureTestUtils();
+    }
+
+    @After
+    @Override
+    public void tearDown() {
+        this.testUtils = null;
+    }
+
+    @Test
+    @Override
+    public void should_return400_when_makingHttpRequestWithoutToken() throws Exception {
+        ClientResponse response = descriptor.run(getId(), "");
+        assertEquals(error(response.getEntity(String.class)), 403, response.getStatus());
+    }
+}
diff --git a/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/ddms/TestGetRegistrationByIdApi.java b/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/ddms/TestGetRegistrationByIdApi.java
new file mode 100644
index 0000000000000000000000000000000000000000..01537b432c1a6dcfde27ea77ae02acc2007f74c6
--- /dev/null
+++ b/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/ddms/TestGetRegistrationByIdApi.java
@@ -0,0 +1,45 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.ddms;
+
+import com.sun.jersey.api.client.ClientResponse;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.opengroup.osdu.register.util.AzureTestUtils;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestGetRegistrationByIdApi extends GetRegistrationByIdApiTest {
+
+    @Before
+    @Override
+    public void setup() {
+        this.testUtils = new AzureTestUtils();
+    }
+
+    @After
+    @Override
+    public void tearDown() {
+        this.testUtils = null;
+    }
+
+    @Test
+    @Override
+    public void should_return400_when_makingHttpRequestWithoutToken() throws Exception {
+        ClientResponse response = descriptor.run(getId(), "");
+        assertEquals(error(response.getEntity(String.class)), 403, response.getStatus());
+    }
+}
diff --git a/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/ddms/TestQueryDdmsByType.java b/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/ddms/TestQueryDdmsByType.java
new file mode 100644
index 0000000000000000000000000000000000000000..1a20bada2670ccf7834100f898863d547b912e7f
--- /dev/null
+++ b/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/ddms/TestQueryDdmsByType.java
@@ -0,0 +1,45 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.ddms;
+
+import com.sun.jersey.api.client.ClientResponse;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.opengroup.osdu.register.util.AzureTestUtils;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestQueryDdmsByType extends QueryDdmsByTypeTest {
+
+    @Before
+    @Override
+    public void setup() {
+        this.testUtils = new AzureTestUtils();
+    }
+
+    @After
+    @Override
+    public void tearDown() {
+        this.testUtils = null;
+    }
+
+    @Test
+    @Override
+    public void should_return400_when_makingHttpRequestWithoutToken() throws Exception {
+        ClientResponse response = descriptor.run(getId(), "");
+        assertEquals(error(response.getEntity(String.class)), 403, response.getStatus());
+    }
+}
diff --git a/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/util/AzureServicePrincipal.java b/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/util/AzureServicePrincipal.java
new file mode 100644
index 0000000000000000000000000000000000000000..ebe11ce88a1ecb8370ac4f33944d6070ab0f00ea
--- /dev/null
+++ b/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/util/AzureServicePrincipal.java
@@ -0,0 +1,84 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.util;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.HashMap;
+import java.util.Map;
+
+public class AzureServicePrincipal {
+    public static String getIdToken(String sp_id, String sp_secret, String tenant_id, String app_resource_id) throws Exception {
+        String aad_endpoint = String.format("https://login.microsoftonline.com/%s/oauth2/token", tenant_id);
+        URL url = new URL(aad_endpoint);
+        HttpURLConnection con = (HttpURLConnection) url.openConnection();
+        con.setRequestMethod("POST");
+        con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
+
+        Map<String, String> parameters = new HashMap<>();
+        parameters.put("grant_type", "client_credentials");
+        parameters.put("client_id", sp_id);
+        parameters.put("client_secret", sp_secret);
+        parameters.put("resource", app_resource_id);
+
+        con.setDoOutput(true);
+        DataOutputStream out = new DataOutputStream(con.getOutputStream());
+        out.writeBytes(getParamsString(parameters));
+        out.flush();
+        out.close();
+
+        BufferedReader in = new BufferedReader(
+                new InputStreamReader(con.getInputStream()));
+        String inputLine;
+        StringBuffer content = new StringBuffer();
+        while ((inputLine = in.readLine()) != null) {
+            content.append(inputLine);
+        }
+        in.close();
+
+        con.disconnect();
+
+        Gson gson = new Gson();
+        JsonObject jobj = gson.fromJson(content.toString(), JsonObject.class);
+        String token = jobj.get("access_token").getAsString();
+        return token;
+    }
+
+    private static String getParamsString(Map<String, String> params)
+            throws UnsupportedEncodingException {
+        StringBuilder result = new StringBuilder();
+
+        for (Map.Entry<String, String> entry : params.entrySet()) {
+            result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
+            result.append("=");
+            result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
+            result.append("&");
+        }
+
+        String resultString = result.toString();
+        return resultString.length() > 0
+                ? resultString.substring(0, resultString.length() - 1)
+                : resultString;
+    }
+}
+
diff --git a/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/util/AzureTestUtils.java b/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/util/AzureTestUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..6a3db22003fcb37a4d43546b17c5fdbe46753490
--- /dev/null
+++ b/testing/register-test-azure/src/test/java/org/opengroup/osdu/register/util/AzureTestUtils.java
@@ -0,0 +1,62 @@
+// Copyright © Microsoft Corporation
+//
+// 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.register.util;
+
+import com.google.common.base.Strings;
+
+public class AzureTestUtils extends TestUtils{
+
+    @Override
+    public synchronized String getOpsAccessToken() throws Exception {
+        if (Strings.isNullOrEmpty(opsToken)) {
+            opsToken = getToken(System.getProperty("INTEGRATION_TESTER", System.getenv("INTEGRATION_TESTER")),
+                    System.getProperty("TESTER_SERVICEPRINCIPAL_SECRET", System.getenv("TESTER_SERVICEPRINCIPAL_SECRET")));
+        }
+        return "Bearer " + opsToken;
+    }
+
+    @Override
+    public synchronized String getAdmAccessToken() throws Exception {
+        if (Strings.isNullOrEmpty(admToken)) {
+            admToken = getToken(System.getProperty("INTEGRATION_TESTER", System.getenv("INTEGRATION_TESTER")),
+                    System.getProperty("TESTER_SERVICEPRINCIPAL_SECRET", System.getenv("TESTER_SERVICEPRINCIPAL_SECRET")));
+        }
+        return "Bearer " + admToken;
+    }
+
+    @Override
+    public synchronized String getEditorAccessToken() throws Exception {
+        if (Strings.isNullOrEmpty(editorToken)) {
+            editorToken = getToken(System.getProperty("INTEGRATION_TESTER", System.getenv("INTEGRATION_TESTER")),
+                    System.getProperty("TESTER_SERVICEPRINCIPAL_SECRET", System.getenv("TESTER_SERVICEPRINCIPAL_SECRET")));
+        }
+        return "Bearer " + editorToken;
+    }
+
+    @Override
+    public synchronized String getNoDataAccessToken() throws Exception {
+        if (Strings.isNullOrEmpty(noAccessToken)) {
+            noAccessToken = getToken(System.getProperty("NO_DATA_ACCESS_TESTER", System.getenv("NO_DATA_ACCESS_TESTER")),
+                    System.getProperty("NO_DATA_ACCESS_TESTER_SERVICEPRINCIPAL_SECRET", System.getenv("NO_DATA_ACCESS_TESTER_SERVICEPRINCIPAL_SECRET")));
+        }
+        return "Bearer " + noAccessToken;
+    }
+
+    private String getToken(String sp_id, String sp_secret) throws Exception {
+        String tenant_id = System.getProperty("AZURE_AD_TENANT_ID", System.getenv("AZURE_AD_TENANT_ID"));
+        String app_resource_id = System.getProperty("AZURE_AD_APP_RESOURCE_ID", System.getenv("AZURE_AD_APP_RESOURCE_ID"));
+        return AzureServicePrincipal.getIdToken(sp_id, sp_secret, tenant_id, app_resource_id);
+    }
+}