You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by di...@apache.org on 2021/02/12 06:21:31 UTC

[airavata] 01/01: Initial user stprage group preferences

This is an automated email from the ASF dual-hosted git repository.

dimuthuupe pushed a commit to branch storage-resource-profile
in repository https://gitbox.apache.org/repos/asf/airavata.git

commit 687002b51be2f8a9fe5861cc8f13a5ba72d05825
Author: Dimuthu Wannipurage <di...@gmail.com>
AuthorDate: Fri Feb 12 01:21:08 2021 -0500

    Initial user stprage group preferences
---
 modules/resource-profile/pom.xml                   |  56 +++
 .../resource-profile-service/pom.xml               |  86 ++++
 .../profile/handler/storage/S3StorageHandler.java  | 450 +++++++++++++++++++++
 .../profile/handler/storage/SCPStorageHandler.java | 449 ++++++++++++++++++++
 .../resource/profile/service/AppConfig.java        |  30 ++
 .../service/ResourceProfileServiceApplication.java |  33 ++
 .../resource/profile/service/SampleClient.java     |  25 ++
 .../resource/profile/service/XmlConfiguration.java |  26 ++
 .../resource/profile/sharing/SharingImpl.java      |  36 ++
 .../s3/entity/S3StoGroupPreferenceEntity.java      |  89 ++++
 .../storage/s3/entity/S3StoGroupPreferenceId.java  |  62 +++
 .../s3/entity/S3StoGroupResourceProfileEntity.java | 112 +++++
 .../profile/storage/s3/entity/S3StorageEntity.java |  66 +++
 .../repository/S3StoGroupPreferenceRepository.java |  24 ++
 .../S3StoGroupResourceProfileRepository.java       |  23 ++
 .../storage/s3/repository/S3StorageRepository.java |  23 ++
 .../scp/entity/SCPStoGroupPreferenceEntity.java    | 104 +++++
 .../scp/entity/SCPStoGroupPreferenceId.java        |  63 +++
 .../entity/SCPStoGroupResourceProfileEntity.java   | 112 +++++
 .../storage/scp/entity/SCPStorageEntity.java       |  65 +++
 .../SCPStoGroupPreferenceRepository.java           |  24 ++
 .../SCPStoGroupResourceProfileRepository.java      |  23 ++
 .../scp/repository/SCPStorageRepository.java       |  24 ++
 .../src/main/resources/application.properties      |   2 +
 .../src/main/resources/applicationContext.xml      |  10 +
 .../resource-profile-stubs/pom.xml                 |  92 +++++
 .../src/main/proto/common.proto                    |   8 +
 .../src/main/proto/storage/s3/service.proto        | 158 ++++++++
 .../src/main/proto/storage/s3/stubs.proto          |  26 ++
 .../src/main/proto/storage/scp/service.proto       | 158 ++++++++
 .../src/main/proto/storage/scp/stubs.proto         |  27 ++
 pom.xml                                            |   9 +-
 32 files changed, 2488 insertions(+), 7 deletions(-)

diff --git a/modules/resource-profile/pom.xml b/modules/resource-profile/pom.xml
new file mode 100644
index 0000000..94d145b
--- /dev/null
+++ b/modules/resource-profile/pom.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you 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>airavata</artifactId>
+        <groupId>org.apache.airavata</groupId>
+        <version>0.21-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>resource-profile</artifactId>
+    <packaging>pom</packaging>
+    <modules>
+        <module>resource-profile-stubs</module>
+        <module>resource-profile-service</module>
+    </modules>
+
+    <properties>
+        <maven.compiler.source>11</maven.compiler.source>
+        <maven.compiler.target>11</maven.compiler.target>
+        <protobuf.maven.plugin>0.5.1</protobuf.maven.plugin>
+        <os.maven.plugin>1.5.0.Final</os.maven.plugin>
+        <javax.annotation>1.3.2</javax.annotation>
+        <h2>1.4.191</h2>
+        <protobuf.java>3.10.0</protobuf.java>
+        <grpc.spring.boot>4.4.3</grpc.spring.boot>
+        <spring.boot.data.jpa>2.4.2</spring.boot.data.jpa>
+        <log4j.over.slf4j>1.7.26</log4j.over.slf4j>
+        <dozer>5.5.1</dozer>
+        <mariadb.jdbc>2.5.1</mariadb.jdbc>
+    </properties>
+
+</project>
\ No newline at end of file
diff --git a/modules/resource-profile/resource-profile-service/pom.xml b/modules/resource-profile/resource-profile-service/pom.xml
new file mode 100644
index 0000000..03fe6fc
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/pom.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you 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>resource-profile</artifactId>
+        <groupId>org.apache.airavata</groupId>
+        <version>0.21-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>resource-profile-service</artifactId>
+
+    <properties>
+        <maven.compiler.source>11</maven.compiler.source>
+        <maven.compiler.target>11</maven.compiler.target>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>io.github.lognet</groupId>
+            <artifactId>grpc-spring-boot-starter</artifactId>
+            <version>${grpc.spring.boot}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jpa</artifactId>
+            <version>${spring.boot.data.jpa}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>2.8.5</version>
+        </dependency>
+        <dependency>
+            <groupId>net.sf.dozer</groupId>
+            <artifactId>dozer</artifactId>
+            <version>${dozer}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+            <version>${h2}</version>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.airavata</groupId>
+            <artifactId>resource-profile-stubs</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jetbrains</groupId>
+            <artifactId>annotations</artifactId>
+            <version>RELEASE</version>
+            <scope>compile</scope>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/handler/storage/S3StorageHandler.java b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/handler/storage/S3StorageHandler.java
new file mode 100644
index 0000000..bad3e4d
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/handler/storage/S3StorageHandler.java
@@ -0,0 +1,450 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.airavata.resource.profile.handler.storage;
+
+import com.google.protobuf.Empty;
+import io.grpc.Status;
+import io.grpc.stub.StreamObserver;
+import org.apache.airavata.resource.profile.service.s3.*;
+import org.apache.airavata.resource.profile.sharing.SharingImpl;
+import org.apache.airavata.resource.profile.sharing.SharingImpl.AccessLevel;
+import org.apache.airavata.resource.profile.storage.s3.entity.S3StoGroupPreferenceEntity;
+import org.apache.airavata.resource.profile.storage.s3.entity.S3StoGroupPreferenceId;
+import org.apache.airavata.resource.profile.storage.s3.entity.S3StoGroupResourceProfileEntity;
+import org.apache.airavata.resource.profile.storage.s3.entity.S3StorageEntity;
+import org.apache.airavata.resource.profile.storage.s3.repository.S3StoGroupPreferenceRepository;
+import org.apache.airavata.resource.profile.storage.s3.repository.S3StoGroupResourceProfileRepository;
+import org.apache.airavata.resource.profile.storage.s3.repository.S3StorageRepository;
+import org.apache.airavata.resource.profile.stubs.s3.S3Storage;
+import org.dozer.DozerBeanMapper;
+import org.lognet.springboot.grpc.GRpcService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.Optional;
+
+@GRpcService
+public class S3StorageHandler extends S3StorageServiceGrpc.S3StorageServiceImplBase {
+
+    private static final Logger logger = LoggerFactory.getLogger(S3StorageHandler.class);
+
+    @Autowired
+    private S3StorageRepository storageRepository;
+
+    @Autowired
+    private S3StoGroupPreferenceRepository groupPreferenceRepository;
+
+    @Autowired
+    private S3StoGroupResourceProfileRepository groupResourceProfileRepository;
+
+    @Autowired
+    private SharingImpl sharingImpl;
+
+    private DozerBeanMapper mapper = new DozerBeanMapper();
+
+    @Override
+    public void createS3Storage(S3StorageCreateRequest request, StreamObserver<S3StorageCreateResponse> responseObserver) {
+
+        try {
+            S3StorageEntity savedEntity = storageRepository.save(mapper.map(request.getS3Storage(), S3StorageEntity.class));
+
+            sharingImpl.createSharingEntity("S3", savedEntity.getS3StorageId(), request.getAuthzToken(), AccessLevel.WRITE);
+
+            S3Storage savedStorage = mapper.map(savedEntity, S3Storage.newBuilder().getClass()).build();
+            responseObserver.onNext(S3StorageCreateResponse.newBuilder().setS3Storage(savedStorage).build());
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to create the S3 Storage with bucket name {}", request.getS3Storage().getBucketName(), e);
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to create the S3 Storage with bucket name " + request.getS3Storage().getBucketName())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void updateS3Storage(S3StorageUpdateRequest request, StreamObserver<Empty> responseObserver) {
+
+        try {
+            boolean hasAccess = sharingImpl.hasAccess("S3",
+                    request.getS3Storage().getS3StorageId(), request.getAuthzToken(), AccessLevel.WRITE);
+
+            if (!hasAccess) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("User does not have access for storage " + request.getS3Storage().getS3StorageId())
+                        .asRuntimeException());
+            }
+
+            boolean exists = storageRepository.existsById(request.getS3Storage().getS3StorageId());
+
+            if (!exists) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("S3 storage with id" + request.getS3Storage().getS3StorageId() + " does not exist")
+                        .asRuntimeException());
+            }
+
+            storageRepository.save(mapper.map(request.getS3Storage(), S3StorageEntity.class));
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to update the S3 Storage with id {}", request.getS3Storage().getS3StorageId(), e);
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to update the S3 Storage with id " + request.getS3Storage().getS3StorageId())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void removeS3Storage(S3StorageRemoveRequest request, StreamObserver<Empty> responseObserver) {
+
+        try {
+            boolean hasAccess = sharingImpl.hasAccess("S3",
+                    request.getS3StorageId(), request.getAuthzToken(), AccessLevel.WRITE);
+
+            if (!hasAccess) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("User does not have access for storage " + request.getS3StorageId())
+                        .asRuntimeException());
+            }
+
+            boolean exists = storageRepository.existsById(request.getS3StorageId());
+
+            if (!exists) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("S3 storage with id " + request.getS3StorageId() + " does not exist")
+                        .asRuntimeException());
+            }
+
+            storageRepository.deleteById(request.getS3StorageId());
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to remove the S3 Storage with id {}", request.getS3StorageId(), e);
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to remove the S3 Storage with id " + request.getS3StorageId())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void fetchS3Storage(S3StorageFetchRequest request, StreamObserver<S3StorageFetchResponse> responseObserver) {
+        try {
+            boolean hasAccess = sharingImpl.hasAccess("S3",
+                    request.getS3StorageId(), request.getAuthzToken(), AccessLevel.READ);
+
+            if (!hasAccess) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("User does not have access for storage " + request.getS3StorageId())
+                        .asRuntimeException());
+            }
+
+            boolean exists = storageRepository.existsById(request.getS3StorageId());
+
+            if (!exists) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("S3 storage with id " + request.getS3StorageId() + " does not exist")
+                        .asRuntimeException());
+            }
+
+            Optional<S3StorageEntity> storageEntityOp = storageRepository.findById(request.getS3StorageId());
+
+            S3Storage fetchedStorage = mapper.map(storageEntityOp.get(), S3Storage.newBuilder().getClass()).build();
+            responseObserver.onNext(S3StorageFetchResponse.newBuilder().setS3Storage(fetchedStorage).build());
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to fetch the S3 Storage with id {}", request.getS3StorageId(), e);
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to fetch the S3 Storage with id " + request.getS3StorageId())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void listS3Storage(S3StorageListRequest request, StreamObserver<S3StorageListResponse> responseObserver) {
+        responseObserver.onError(Status.INTERNAL
+                .withDescription("Method not implemented")
+                .asRuntimeException());
+    }
+
+    @Override
+    public void createS3StoGroupPreference(S3StoGroupPreferenceCreateRequest request, StreamObserver<S3StoGroupPreferenceCreateResponse> responseObserver) {
+
+        try {
+            S3StoGroupPreferenceEntity savedEntity = groupPreferenceRepository.save(mapper.map(request.getS3StoGroupPreference(), S3StoGroupPreferenceEntity.class));
+
+            sharingImpl.createSharingEntity("S3",
+                    savedEntity.getS3StorageId() + "-" + savedEntity.getS3GroupResourceProfileId(),
+                    request.getAuthzToken(), AccessLevel.WRITE);
+
+            responseObserver.onNext(mapper.map(savedEntity, S3StoGroupPreferenceCreateResponse.newBuilder().getClass()).build());
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to create the S3 storage group preference with storage id {}",
+                    request.getS3StoGroupPreference().getS3StorageId(), e);
+
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to create the S3 storage group preference with storage id " +
+                            request.getS3StoGroupPreference().getS3StorageId())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void updateS3StoGroupPreference(S3StoGroupPreferenceUpdateRequest request, StreamObserver<Empty> responseObserver) {
+        try {
+            boolean hasAccess = sharingImpl.hasAccess("S3",
+                    request.getS3StoGroupPreference().getS3StorageId() + "-" + request.getS3StoGroupPreference().getS3GroupResourceProfileId(),
+                    request.getAuthzToken(), AccessLevel.WRITE);
+
+            if (!hasAccess) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("User does not have access for storage group preference with storage id " +
+                                request.getS3StoGroupPreference().getS3StorageId())
+                        .asRuntimeException());
+            }
+
+            boolean exists = groupPreferenceRepository.existsById(new S3StoGroupPreferenceId(
+                    request.getS3StoGroupPreference().getS3StorageId(),
+                    request.getS3StoGroupPreference().getS3GroupResourceProfileId()));
+
+            if (!exists) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("S3 storage with id" + request.getS3StoGroupPreference().getS3StorageId() + " does not exist")
+                        .asRuntimeException());
+            }
+
+            groupPreferenceRepository.save(mapper.map(request.getS3StoGroupPreference(), S3StoGroupPreferenceEntity.class));
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to update the S3 Storage with id {}", request.getS3StoGroupPreference().getS3StorageId(), e);
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to update the S3 Storage with id " + request.getS3StoGroupPreference().getS3StorageId())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void removeS3StoGroupPreference(S3StoGroupPreferenceRemoveRequest request, StreamObserver<Empty> responseObserver) {
+        try {
+            boolean hasAccess = sharingImpl.hasAccess("S3",
+                    request.getS3StorageId() + "-" + request.getS3GroupResourceProfileId(),
+                    request.getAuthzToken(), AccessLevel.WRITE);
+
+            if (!hasAccess) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("User does not have access for storage group preference with storage id  " +
+                                request.getS3StorageId())
+                        .asRuntimeException());
+            }
+
+            S3StoGroupPreferenceId id = new S3StoGroupPreferenceId(
+                    request.getS3StorageId(),
+                    request.getS3GroupResourceProfileId());
+
+            boolean exists = groupPreferenceRepository.existsById(id);
+
+            if (!exists) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("S3 storage group preference with storage id " + request.getS3StorageId() + " does not exist")
+                        .asRuntimeException());
+            }
+
+            groupPreferenceRepository.deleteById(id);
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to remove the S3 storage group preference with storage id {}", request.getS3StorageId(), e);
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to remove the S3 storage group preference with storage id " + request.getS3StorageId())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void fetchS3StoGroupPreference(S3StoGroupPreferenceFetchRequest request, StreamObserver<S3StoGroupPreferenceFetchResponse> responseObserver) {
+        try {
+            boolean hasAccess = sharingImpl.hasAccess("S3",
+                    request.getS3StorageId() + "-" + request.getS3GroupResourceProfileId(),
+                    request.getAuthzToken(), AccessLevel.WRITE);
+
+            if (!hasAccess) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("User does not have access for storage group preference with storage id  " +
+                                request.getS3StorageId())
+                        .asRuntimeException());
+            }
+
+            S3StoGroupPreferenceId id = new S3StoGroupPreferenceId(
+                    request.getS3StorageId(),
+                    request.getS3GroupResourceProfileId());
+
+            boolean exists = groupPreferenceRepository.existsById(id);
+
+            Optional<S3StoGroupPreferenceEntity> groupPreferenceOp = groupPreferenceRepository.findById(id);
+
+            responseObserver.onNext(mapper.map(groupPreferenceOp.get(),
+                    S3StoGroupPreferenceFetchResponse.newBuilder().getClass()).build());
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to fetch the S3 storage group preference with storage id {}", request.getS3StorageId(), e);
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to fetch the S3 storage group preference with storage id  " + request.getS3StorageId())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void createS3StoGroupResourceProfile(S3StoGroupResourceProfileCreateRequest request, StreamObserver<S3StoGroupResourceProfileCreateResponse> responseObserver) {
+        try {
+            S3StoGroupResourceProfileEntity savedEntity = groupResourceProfileRepository.save(
+                    mapper.map(request.getS3StoGroupResourceProfile(), S3StoGroupResourceProfileEntity.class));
+
+            sharingImpl.createSharingEntity("S3", savedEntity.getS3GroupResourceProfileId(),
+                    request.getAuthzToken(), AccessLevel.WRITE);
+
+            responseObserver.onNext(mapper.map(savedEntity,
+                    S3StoGroupResourceProfileCreateResponse.newBuilder().getClass()).build());
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to create the S3 group resource profile with name {}",
+                    request.getS3StoGroupResourceProfile().getS3GroupResourceProfileName(), e);
+
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to create the S3 group resource profile with name " +
+                            request.getS3StoGroupResourceProfile().getS3GroupResourceProfileName())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void updateS3StoGroupResourceProfile(S3StoGroupResourceProfileUpdateRequest request, StreamObserver<Empty> responseObserver) {
+        try {
+            boolean hasAccess = sharingImpl.hasAccess("S3",
+                    request.getS3StoGroupResourceProfile().getS3GroupResourceProfileId(), request.getAuthzToken(), AccessLevel.WRITE);
+
+            if (!hasAccess) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("User does not have access for S3 group resource profile with id " +
+                                request.getS3StoGroupResourceProfile().getS3GroupResourceProfileId())
+                        .asRuntimeException());
+            }
+
+            boolean exists = groupResourceProfileRepository.existsById(
+                    request.getS3StoGroupResourceProfile().getS3GroupResourceProfileId());
+
+            if (!exists) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("S3 group resource profile with id " +
+                                request.getS3StoGroupResourceProfile().getS3GroupResourceProfileId() + " does not exist")
+                        .asRuntimeException());
+            }
+
+            groupResourceProfileRepository.save(mapper.map(request.getS3StoGroupResourceProfile(),
+                    S3StoGroupResourceProfileEntity.class));
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to update the S3 group resource profile with id {}",
+                    request.getS3StoGroupResourceProfile().getS3GroupResourceProfileId(), e);
+
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to update the S3 group resource profile with id " +
+                            request.getS3StoGroupResourceProfile().getS3GroupResourceProfileId())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void removeS3StoGroupResourceProfile(S3StoGroupResourceProfileRemoveRequest request, StreamObserver<Empty> responseObserver) {
+        try {
+            boolean hasAccess = sharingImpl.hasAccess("S3",
+                    request.getS3StoGroupResourceProfileId(), request.getAuthzToken(), AccessLevel.WRITE);
+
+            if (!hasAccess) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("User does not have access for S3 group resource profile with id " +
+                                request.getS3StoGroupResourceProfileId())
+                        .asRuntimeException());
+            }
+
+            boolean exists = groupResourceProfileRepository.existsById(request.getS3StoGroupResourceProfileId());
+
+            if (!exists) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("S3 group resource profile with id " + request.getS3StoGroupResourceProfileId() + " does not exist")
+                        .asRuntimeException());
+            }
+
+            groupResourceProfileRepository.deleteById(request.getS3StoGroupResourceProfileId());
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to remove the S3 group resource profile with id {}", request.getS3StoGroupResourceProfileId(), e);
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to remove the S3 group resource profile with id {} " + request.getS3StoGroupResourceProfileId())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void fetchS3StoGroupResourceProfile(S3StoGroupResourceProfileFetchRequest request, StreamObserver<S3StoGroupResourceProfileFetchResponse> responseObserver) {
+        try {
+            boolean hasAccess = sharingImpl.hasAccess("S3",
+                    request.getS3StoGroupResourceProfileId(), request.getAuthzToken(), AccessLevel.READ);
+
+            if (!hasAccess) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("User does not have access for S3 group resource profile with id " +
+                                request.getS3StoGroupResourceProfileId())
+                        .asRuntimeException());
+            }
+
+            boolean exists = groupResourceProfileRepository.existsById(request.getS3StoGroupResourceProfileId());
+
+            if (!exists) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("S3 group resource profile with id " + request.getS3StoGroupResourceProfileId() + " does not exist")
+                        .asRuntimeException());
+            }
+
+            Optional<S3StoGroupResourceProfileEntity> groupResProfOp = groupResourceProfileRepository.findById(request.getS3StoGroupResourceProfileId());
+
+            responseObserver.onNext(mapper.map(groupResProfOp.get(),
+                    S3StoGroupResourceProfileFetchResponse.newBuilder().getClass()).build());
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to fetch the S3 group resource profile with id {}", request.getS3StoGroupResourceProfileId(), e);
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to fetch the S3 group resource profile with id " + request.getS3StoGroupResourceProfileId())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void listS3StoGroupResourceProfile(S3StoGroupResourceProfileListRequest request, StreamObserver<S3StoGroupResourceProfileListResponse> responseObserver) {
+        responseObserver.onError(Status.INTERNAL
+                .withDescription("Method not implemented")
+                .asRuntimeException());
+    }
+}
diff --git a/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/handler/storage/SCPStorageHandler.java b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/handler/storage/SCPStorageHandler.java
new file mode 100644
index 0000000..8696a7b
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/handler/storage/SCPStorageHandler.java
@@ -0,0 +1,449 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.airavata.resource.profile.handler.storage;
+
+import com.google.protobuf.Empty;
+import io.grpc.Status;
+import io.grpc.stub.StreamObserver;
+import org.apache.airavata.resource.profile.service.s3.S3StorageCreateResponse;
+import org.apache.airavata.resource.profile.service.s3.S3StorageFetchResponse;
+import org.apache.airavata.resource.profile.service.scp.*;
+import org.apache.airavata.resource.profile.sharing.SharingImpl;
+import org.apache.airavata.resource.profile.storage.scp.entity.SCPStoGroupPreferenceEntity;
+import org.apache.airavata.resource.profile.storage.scp.entity.SCPStoGroupPreferenceId;
+import org.apache.airavata.resource.profile.storage.scp.entity.SCPStoGroupResourceProfileEntity;
+import org.apache.airavata.resource.profile.storage.scp.entity.SCPStorageEntity;
+import org.apache.airavata.resource.profile.storage.scp.repository.SCPStoGroupPreferenceRepository;
+import org.apache.airavata.resource.profile.storage.scp.repository.SCPStoGroupResourceProfileRepository;
+import org.apache.airavata.resource.profile.storage.scp.repository.SCPStorageRepository;
+import org.apache.airavata.resource.profile.stubs.s3.S3Storage;
+import org.apache.airavata.resource.profile.stubs.scp.SCPStorage;
+import org.dozer.DozerBeanMapper;
+import org.lognet.springboot.grpc.GRpcService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.Optional;
+
+@GRpcService
+public class SCPStorageHandler extends SCPStorageServiceGrpc.SCPStorageServiceImplBase {
+
+    private static final Logger logger = LoggerFactory.getLogger(SCPStorageHandler.class);
+
+    @Autowired
+    private SCPStorageRepository storageRepository;
+
+    @Autowired
+    private SCPStoGroupPreferenceRepository groupPreferenceRepository;
+
+    @Autowired
+    private SCPStoGroupResourceProfileRepository groupResourceProfileRepository;
+
+    @Autowired
+    private SharingImpl sharingImpl;
+
+    private DozerBeanMapper mapper = new DozerBeanMapper();
+
+    @Override
+    public void createSCPStorage(SCPStorageCreateRequest request, StreamObserver<SCPStorageCreateResponse> responseObserver) {
+        try {
+            SCPStorageEntity savedEntity = storageRepository.save(mapper.map(request.getScpStorage(), SCPStorageEntity.class));
+
+            sharingImpl.createSharingEntity("SCP", savedEntity.getScpStorageId(), request.getAuthzToken(), SharingImpl.AccessLevel.WRITE);
+
+            SCPStorage savedStorage = mapper.map(savedEntity, SCPStorage.newBuilder().getClass()).build();
+            responseObserver.onNext(SCPStorageCreateResponse.newBuilder().setScpStorage(savedStorage).build());
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to create the SCP Storage with host name {}", request.getScpStorage().getHostName(), e);
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to create the SCP Storage with host name " + request.getScpStorage().getHostName())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void updateSCPStorage(SCPStorageUpdateRequest request, StreamObserver<Empty> responseObserver) {
+        try {
+            boolean hasAccess = sharingImpl.hasAccess("SCP",
+                    request.getScpStorage().getScpStorageId(), request.getAuthzToken(), SharingImpl.AccessLevel.WRITE);
+
+            if (!hasAccess) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("User does not have access for storage " + request.getScpStorage().getScpStorageId())
+                        .asRuntimeException());
+            }
+
+            boolean exists = storageRepository.existsById(request.getScpStorage().getScpStorageId());
+
+            if (!exists) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("SCP storage with id" + request.getScpStorage().getScpStorageId() + " does not exist")
+                        .asRuntimeException());
+            }
+
+            storageRepository.save(mapper.map(request.getScpStorage(), SCPStorageEntity.class));
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to update the SCP Storage with id {}", request.getScpStorage().getScpStorageId(), e);
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to update the SCP Storage with id " + request.getScpStorage().getScpStorageId())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void removeSCPStorage(SCPStorageRemoveRequest request, StreamObserver<Empty> responseObserver) {
+        try {
+            boolean hasAccess = sharingImpl.hasAccess("SCP",
+                    request.getScpStorageId(), request.getAuthzToken(), SharingImpl.AccessLevel.WRITE);
+
+            if (!hasAccess) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("User does not have access for storage " + request.getScpStorageId())
+                        .asRuntimeException());
+            }
+
+            boolean exists = storageRepository.existsById(request.getScpStorageId());
+
+            if (!exists) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("SCP storage with id " + request.getScpStorageId() + " does not exist")
+                        .asRuntimeException());
+            }
+
+            storageRepository.deleteById(request.getScpStorageId());
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to remove the SCP Storage with id {}", request.getScpStorageId(), e);
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to remove the SCP Storage with id {} " + request.getScpStorageId())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void fetchSCPStorage(SCPStorageFetchRequest request, StreamObserver<SCPStorageFetchResponse> responseObserver) {
+        try {
+            boolean hasAccess = sharingImpl.hasAccess("SCP",
+                    request.getScpStorageId(), request.getAuthzToken(), SharingImpl.AccessLevel.READ);
+
+            if (!hasAccess) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("User does not have access for storage " + request.getScpStorageId())
+                        .asRuntimeException());
+            }
+
+            boolean exists = storageRepository.existsById(request.getScpStorageId());
+
+            if (!exists) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("SCP storage with id" + request.getScpStorageId() + " does not exist")
+                        .asRuntimeException());
+            }
+
+            Optional<SCPStorageEntity> storageEntityOp = storageRepository.findById(request.getScpStorageId());
+
+            SCPStorage fetchedStorage = mapper.map(storageEntityOp.get(), SCPStorage.newBuilder().getClass()).build();
+            responseObserver.onNext(SCPStorageFetchResponse.newBuilder().setScpStorage(fetchedStorage).build());
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to fetch the SCP Storage with id {}", request.getScpStorageId(), e);
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to fetch the SCP Storage with id " + request.getScpStorageId())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void listSCPStorage(SCPStorageListRequest request, StreamObserver<SCPStorageListResponse> responseObserver) {
+        responseObserver.onError(Status.INTERNAL
+                .withDescription("Method not implemented")
+                .asRuntimeException());
+    }
+
+    @Override
+    public void createSCPStoGroupPreference(SCPStoGroupPreferenceCreateRequest request, StreamObserver<SCPStoGroupPreferenceCreateResponse> responseObserver) {
+        try {
+            SCPStoGroupPreferenceEntity savedEntity = groupPreferenceRepository.save(mapper.map(request.getScpStoGroupPreference(), SCPStoGroupPreferenceEntity.class));
+
+            sharingImpl.createSharingEntity("SCP",
+                    savedEntity.getScpStorageId() + "-" + savedEntity.getScpGroupResourceProfileId(),
+                    request.getAuthzToken(), SharingImpl.AccessLevel.WRITE);
+
+            responseObserver.onNext(mapper.map(savedEntity, SCPStoGroupPreferenceCreateResponse.newBuilder().getClass()).build());
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to create the SCP storage group preference with storage id {}",
+                    request.getScpStoGroupPreference().getScpStorageId(), e);
+
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to create the SCP storage group preference with storage id " +
+                            request.getScpStoGroupPreference().getScpStorageId())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void updateSCPStoGroupPreference(SCPStoGroupPreferenceUpdateRequest request, StreamObserver<Empty> responseObserver) {
+        try {
+            boolean hasAccess = sharingImpl.hasAccess("SCP",
+                    request.getScpStoGroupPreference().getScpStorageId() + "-" + request.getScpStoGroupPreference().getScpGroupResourceProfileId(),
+                    request.getAuthzToken(), SharingImpl.AccessLevel.WRITE);
+
+            if (!hasAccess) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("User does not have access for storage group preference with storage id " +
+                                request.getScpStoGroupPreference().getScpStorageId())
+                        .asRuntimeException());
+            }
+
+            boolean exists = groupPreferenceRepository.existsById(new SCPStoGroupPreferenceId(
+                    request.getScpStoGroupPreference().getScpStorageId(),
+                    request.getScpStoGroupPreference().getScpGroupResourceProfileId()));
+
+            if (!exists) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("SCP storage with id" + request.getScpStoGroupPreference().getScpStorageId() + " does not exist")
+                        .asRuntimeException());
+            }
+
+            groupPreferenceRepository.save(mapper.map(request.getScpStoGroupPreference(), SCPStoGroupPreferenceEntity.class));
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to update the SCP Storage with id {}", request.getScpStoGroupPreference().getScpStorageId(), e);
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to update the SCP Storage with id " + request.getScpStoGroupPreference().getScpStorageId())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void removeSCPStoGroupPreference(SCPStoGroupPreferenceRemoveRequest request, StreamObserver<Empty> responseObserver) {
+        try {
+            boolean hasAccess = sharingImpl.hasAccess("SCP",
+                    request.getScpStorageId() + "-" + request.getScpGroupResourceProfileId(),
+                    request.getAuthzToken(), SharingImpl.AccessLevel.WRITE);
+
+            if (!hasAccess) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("User does not have access for storage group preference with storage id  " +
+                                request.getScpStorageId())
+                        .asRuntimeException());
+            }
+
+            SCPStoGroupPreferenceId id = new SCPStoGroupPreferenceId(
+                    request.getScpStorageId(),
+                    request.getScpGroupResourceProfileId());
+
+            boolean exists = groupPreferenceRepository.existsById(id);
+
+            if (!exists) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("SCP storage group preference with storage id " + request.getScpStorageId() + " does not exist")
+                        .asRuntimeException());
+            }
+
+            groupPreferenceRepository.deleteById(id);
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to remove the SCP storage group preference with storage id {}", request.getScpStorageId(), e);
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to remove the SCP storage group preference with storage id " + request.getScpStorageId())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void fetchSCPStoGroupPreference(SCPStoGroupPreferenceFetchRequest request, StreamObserver<SCPStoGroupPreferenceFetchResponse> responseObserver) {
+        try {
+            boolean hasAccess = sharingImpl.hasAccess("SCP",
+                    request.getScpStorageId() + "-" + request.getScpGroupResourceProfileId(),
+                    request.getAuthzToken(), SharingImpl.AccessLevel.WRITE);
+
+            if (!hasAccess) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("User does not have access for storage group preference with storage id  " +
+                                request.getScpStorageId())
+                        .asRuntimeException());
+            }
+
+            SCPStoGroupPreferenceId id = new SCPStoGroupPreferenceId(
+                    request.getScpStorageId(),
+                    request.getScpGroupResourceProfileId());
+
+            boolean exists = groupPreferenceRepository.existsById(id);
+
+            Optional<SCPStoGroupPreferenceEntity> groupPreferenceOp = groupPreferenceRepository.findById(id);
+
+            responseObserver.onNext(mapper.map(groupPreferenceOp.get(),
+                    SCPStoGroupPreferenceFetchResponse.newBuilder().getClass()).build());
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to fetch the SCP storage group preference with storage id {}", request.getScpStorageId(), e);
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to fetch the SCP storage group preference with storage id  " + request.getScpStorageId())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void createSCPStoGroupResourceProfile(SCPStoGroupResourceProfileCreateRequest request, StreamObserver<SCPStoGroupResourceProfileCreateResponse> responseObserver) {
+        try {
+            SCPStoGroupResourceProfileEntity savedEntity = groupResourceProfileRepository.save(
+                    mapper.map(request.getScpStoGroupResourceProfile(), SCPStoGroupResourceProfileEntity.class));
+
+            sharingImpl.createSharingEntity("SCP", savedEntity.getScpGroupResourceProfileId(),
+                    request.getAuthzToken(), SharingImpl.AccessLevel.WRITE);
+
+            responseObserver.onNext(mapper.map(savedEntity,
+                    SCPStoGroupResourceProfileCreateResponse.newBuilder().getClass()).build());
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to create the SCP group resource profile with name {}",
+                    request.getScpStoGroupResourceProfile().getScpGroupResourceProfileName(), e);
+
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to create the SCP group resource profile with name " +
+                            request.getScpStoGroupResourceProfile().getScpGroupResourceProfileName())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void updateSCPStoGroupResourceProfile(SCPStoGroupResourceProfileUpdateRequest request, StreamObserver<Empty> responseObserver) {
+        try {
+            boolean hasAccess = sharingImpl.hasAccess("SCP",
+                    request.getScpStoGroupResourceProfile().getScpGroupResourceProfileId(), request.getAuthzToken(), SharingImpl.AccessLevel.WRITE);
+
+            if (!hasAccess) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("User does not have access for SCP group resource profile with id " +
+                                request.getScpStoGroupResourceProfile().getScpGroupResourceProfileId())
+                        .asRuntimeException());
+            }
+
+            boolean exists = groupResourceProfileRepository.existsById(
+                    request.getScpStoGroupResourceProfile().getScpGroupResourceProfileId());
+
+            if (!exists) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("SCP group resource profile with id " +
+                                request.getScpStoGroupResourceProfile().getScpGroupResourceProfileId() + " does not exist")
+                        .asRuntimeException());
+            }
+
+            groupResourceProfileRepository.save(mapper.map(request.getScpStoGroupResourceProfile(),
+                    SCPStoGroupResourceProfileEntity.class));
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to update the SCP group resource profile with id {}",
+                    request.getScpStoGroupResourceProfile().getScpGroupResourceProfileId(), e);
+
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to update the SCP group resource profile with id " +
+                            request.getScpStoGroupResourceProfile().getScpGroupResourceProfileId())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void removeSCPStoGroupResourceProfile(SCPStoGroupResourceProfileRemoveRequest request, StreamObserver<Empty> responseObserver) {
+        try {
+            boolean hasAccess = sharingImpl.hasAccess("SCP",
+                    request.getScpStoGroupResourceProfileId(), request.getAuthzToken(), SharingImpl.AccessLevel.WRITE);
+
+            if (!hasAccess) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("User does not have access for SCP group resource profile with id " +
+                                request.getScpStoGroupResourceProfileId())
+                        .asRuntimeException());
+            }
+
+            boolean exists = groupResourceProfileRepository.existsById(request.getScpStoGroupResourceProfileId());
+
+            if (!exists) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("SCP group resource profile with id " + request.getScpStoGroupResourceProfileId() + " does not exist")
+                        .asRuntimeException());
+            }
+
+            groupResourceProfileRepository.deleteById(request.getScpStoGroupResourceProfileId());
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to remove the SCP group resource profile with id {}", request.getScpStoGroupResourceProfileId(), e);
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to remove the SCP group resource profile with id {} " + request.getScpStoGroupResourceProfileId())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void fetchSCPStoGroupResourceProfile(SCPStoGroupResourceProfileFetchRequest request, StreamObserver<SCPStoGroupResourceProfileFetchResponse> responseObserver) {
+        try {
+            boolean hasAccess = sharingImpl.hasAccess("SCP",
+                    request.getScpStoGroupResourceProfileId(), request.getAuthzToken(), SharingImpl.AccessLevel.READ);
+
+            if (!hasAccess) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("User does not have access for SCP group resource profile with id " +
+                                request.getScpStoGroupResourceProfileId())
+                        .asRuntimeException());
+            }
+
+            boolean exists = groupResourceProfileRepository.existsById(request.getScpStoGroupResourceProfileId());
+
+            if (!exists) {
+                responseObserver.onError(Status.INTERNAL
+                        .withDescription("SCP group resource profile with id " + request.getScpStoGroupResourceProfileId() + " does not exist")
+                        .asRuntimeException());
+            }
+
+            Optional<SCPStoGroupResourceProfileEntity> groupResProfOp = groupResourceProfileRepository.findById(request.getScpStoGroupResourceProfileId());
+
+            responseObserver.onNext(mapper.map(groupResProfOp.get(),
+                    SCPStoGroupResourceProfileFetchResponse.newBuilder().getClass()).build());
+            responseObserver.onCompleted();
+
+        } catch (Exception e) {
+            logger.error("Failed to fetch the SCP group resource profile with id {}", request.getScpStoGroupResourceProfileId(), e);
+            responseObserver.onError(Status.INTERNAL.withCause(e)
+                    .withDescription("Failed to fetch the SCP group resource profile with id " + request.getScpStoGroupResourceProfileId())
+                    .asRuntimeException());
+        }
+    }
+
+    @Override
+    public void listSCPStoGroupResourceProfile(SCPStoGroupResourceProfileListRequest request, StreamObserver<SCPStoGroupResourceProfileListResponse> responseObserver) {
+        responseObserver.onError(Status.INTERNAL
+                .withDescription("Method not implemented")
+                .asRuntimeException());
+    }
+}
diff --git a/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/service/AppConfig.java b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/service/AppConfig.java
new file mode 100644
index 0000000..0adcaac
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/service/AppConfig.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.airavata.resource.profile.service;
+
+import org.apache.airavata.resource.profile.sharing.SharingImpl;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class AppConfig {
+
+    @Bean
+    public SharingImpl sharingImpl() {
+        return new SharingImpl();
+    }
+}
diff --git a/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/service/ResourceProfileServiceApplication.java b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/service/ResourceProfileServiceApplication.java
new file mode 100644
index 0000000..0e29aa4
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/service/ResourceProfileServiceApplication.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.airavata.resource.profile.service;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+
+@SpringBootApplication
+@ComponentScan(basePackages = {"org.apache.airavata.resource.profile"})
+@EnableJpaRepositories("org.apache.airavata.resource.profile.storage")
+@EntityScan("org.apache.airavata.resource.profile.storage")
+public class ResourceProfileServiceApplication {
+    public static void main(String args[]) {
+        SpringApplication.run(ResourceProfileServiceApplication.class, args);
+    }
+}
diff --git a/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/service/SampleClient.java b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/service/SampleClient.java
new file mode 100644
index 0000000..ec9b221
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/service/SampleClient.java
@@ -0,0 +1,25 @@
+package org.apache.airavata.resource.profile.service;
+
+import io.grpc.ManagedChannel;
+import io.grpc.ManagedChannelBuilder;
+import org.apache.airavata.resource.profile.service.s3.*;
+import org.apache.airavata.resource.profile.stubs.common.AuthzToken;
+import org.apache.airavata.resource.profile.stubs.s3.S3Storage;
+
+public class SampleClient {
+    public static void main(String args[]) {
+        ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 17002).usePlaintext().build();
+
+
+
+        S3StorageServiceGrpc.S3StorageServiceBlockingStub s3StorageServiceBlockingStub = S3StorageServiceGrpc.newBlockingStub(channel);
+        S3StorageCreateResponse s3Storage = s3StorageServiceBlockingStub.createS3Storage(S3StorageCreateRequest.newBuilder()
+                .setAuthzToken(AuthzToken.newBuilder().setAuthorizationToken("token").build())
+                .setS3Storage(S3Storage.newBuilder().setBucketName("bucket-1").setRegion("us-east").build()).build());
+
+        System.out.println(s3Storage.getS3Storage());
+
+        S3StorageFetchResponse s3StorageFetchResponse = s3StorageServiceBlockingStub.fetchS3Storage(S3StorageFetchRequest.newBuilder().setS3StorageId(s3Storage.getS3Storage().getS3StorageId()).setAuthzToken(AuthzToken.newBuilder().setAuthorizationToken("token").build()).build());
+        System.out.println(s3StorageFetchResponse.getS3Storage());
+    }
+}
diff --git a/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/service/XmlConfiguration.java b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/service/XmlConfiguration.java
new file mode 100644
index 0000000..f970c5a
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/service/XmlConfiguration.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.airavata.resource.profile.service;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.ImportResource;
+
+@Configuration
+@ImportResource({"applicationContext.xml"})
+public class XmlConfiguration {
+}
diff --git a/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/sharing/SharingImpl.java b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/sharing/SharingImpl.java
new file mode 100644
index 0000000..06745d9
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/sharing/SharingImpl.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.airavata.resource.profile.sharing;
+
+import org.apache.airavata.resource.profile.stubs.common.AuthzToken;
+
+public class SharingImpl {
+
+    public enum AccessLevel {
+        READ, WRITE
+    }
+
+    public void createSharingEntity(String resourceType, String resourceId, AuthzToken authzToken, AccessLevel accessLevel) {
+        // TODO implement to talk to sharing service
+    }
+
+    public boolean hasAccess(String resourceType, String resourceId, AuthzToken authzToken, AccessLevel accessLevel) {
+        // TODO implement to talk to sharing service
+        return true;
+    }
+}
diff --git a/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/s3/entity/S3StoGroupPreferenceEntity.java b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/s3/entity/S3StoGroupPreferenceEntity.java
new file mode 100644
index 0000000..df5bb54
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/s3/entity/S3StoGroupPreferenceEntity.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.airavata.resource.profile.storage.s3.entity;
+
+import javax.persistence.*;
+
+@Entity
+@Table(name = "S3_STORAGE_GROUP_PREFERENCE")
+@IdClass(S3StoGroupPreferenceId.class)
+public class S3StoGroupPreferenceEntity {
+
+    @Id
+    @Column(name = "S3_STORAGE_ID")
+    private String s3StorageId;
+
+    @Id
+    @Column(name = "S3_GROUP_RESOURCE_PROFILE_ID")
+    private String s3GroupResourceProfileId;
+
+    @Column(name = "RESOURCE_CS_TOKEN")
+    private String resourceSpecificCredentialToken;
+
+    @ManyToOne(targetEntity = S3StoGroupResourceProfileEntity.class, cascade = CascadeType.ALL)
+    @JoinColumn(name = "S3_GROUP_RESOURCE_PROFILE_ID", insertable = false, updatable = false)
+    private S3StoGroupResourceProfileEntity s3GroupResourceProfile;
+
+    @ManyToOne(targetEntity = S3StorageEntity.class, cascade = CascadeType.ALL)
+    @JoinColumn(name = "S3_STORAGE_ID", insertable = false, updatable = false)
+    private  S3StorageEntity s3Storage;
+
+    public String getS3StorageId() {
+        return s3StorageId;
+    }
+
+    public S3StoGroupPreferenceEntity setS3StorageId(String s3StorageId) {
+        this.s3StorageId = s3StorageId;
+        return this;
+    }
+
+    public String getS3GroupResourceProfileId() {
+        return s3GroupResourceProfileId;
+    }
+
+    public S3StoGroupPreferenceEntity setS3GroupResourceProfileId(String s3GroupResourceProfileId) {
+        this.s3GroupResourceProfileId = s3GroupResourceProfileId;
+        return this;
+    }
+
+    public String getResourceSpecificCredentialToken() {
+        return resourceSpecificCredentialToken;
+    }
+
+    public S3StoGroupPreferenceEntity setResourceSpecificCredentialToken(String resourceSpecificCredentialToken) {
+        this.resourceSpecificCredentialToken = resourceSpecificCredentialToken;
+        return this;
+    }
+
+    public S3StoGroupResourceProfileEntity getS3GroupResourceProfile() {
+        return s3GroupResourceProfile;
+    }
+
+    public S3StoGroupPreferenceEntity setS3GroupResourceProfile(S3StoGroupResourceProfileEntity s3GroupResourceProfile) {
+        this.s3GroupResourceProfile = s3GroupResourceProfile;
+        return this;
+    }
+
+    public S3StorageEntity getS3Storage() {
+        return s3Storage;
+    }
+
+    public S3StoGroupPreferenceEntity setS3Storage(S3StorageEntity s3Storage) {
+        this.s3Storage = s3Storage;
+        return this;
+    }
+}
diff --git a/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/s3/entity/S3StoGroupPreferenceId.java b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/s3/entity/S3StoGroupPreferenceId.java
new file mode 100644
index 0000000..14a2459
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/s3/entity/S3StoGroupPreferenceId.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.airavata.resource.profile.storage.s3.entity;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+public class S3StoGroupPreferenceId implements Serializable {
+    private String s3StorageId;
+    private String s3GroupResourceProfileId;
+
+    public S3StoGroupPreferenceId(String s3StorageId, String s3GroupResourceProfileId) {
+        this.s3StorageId = s3StorageId;
+        this.s3GroupResourceProfileId = s3GroupResourceProfileId;
+    }
+
+    public String getS3StorageId() {
+        return s3StorageId;
+    }
+
+    public S3StoGroupPreferenceId setS3StorageId(String s3StorageId) {
+        this.s3StorageId = s3StorageId;
+        return this;
+    }
+
+    public String getS3GroupResourceProfileId() {
+        return s3GroupResourceProfileId;
+    }
+
+    public S3StoGroupPreferenceId setS3GroupResourceProfileId(String s3GroupResourceProfileId) {
+        this.s3GroupResourceProfileId = s3GroupResourceProfileId;
+        return this;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof S3StoGroupPreferenceId)) return false;
+        S3StoGroupPreferenceId that = (S3StoGroupPreferenceId) o;
+        return Objects.equals(getS3StorageId(), that.getS3StorageId()) &&
+                Objects.equals(getS3GroupResourceProfileId(), that.getS3GroupResourceProfileId());
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(getS3StorageId(), getS3GroupResourceProfileId());
+    }
+}
diff --git a/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/s3/entity/S3StoGroupResourceProfileEntity.java b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/s3/entity/S3StoGroupResourceProfileEntity.java
new file mode 100644
index 0000000..78b4c3d
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/s3/entity/S3StoGroupResourceProfileEntity.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.airavata.resource.profile.storage.s3.entity;
+
+import javax.persistence.*;
+import java.util.List;
+
+@Entity
+@Table(name = "S3_STORAGE_GROUP_RESOURCE_PROFILE")
+public class S3StoGroupResourceProfileEntity {
+
+    @Id
+    @Column(name = "S3_GROUP_RESOURCE_PROFILE_ID")
+    private String s3GroupResourceProfileId;
+
+    @Column(name = "GATEWAY_ID")
+    private String gatewayId;
+
+    @Column(name = "S3_GROUP_RESOURCE_PROFILE_NAME")
+    private String s3GroupResourceProfileName;
+
+    @Column(name = "CREATION_TIME", updatable = false)
+    private Long creationTime;
+
+    @Column(name = "UPDATE_TIME")
+    private Long updatedTime;
+
+    @Column(name = "DEFAULT_S3_CREDENTIAL_STORE_TOKEN")
+    private String defaultS3CredentialStoreToken;
+
+    @OneToMany(targetEntity = S3StoGroupPreferenceEntity.class, cascade = CascadeType.ALL,
+            mappedBy = "s3GroupResourceProfileId", fetch = FetchType.EAGER, orphanRemoval = true)
+    private List<S3StoGroupPreferenceEntity> s3StoragePreferences;
+
+    public String getS3GroupResourceProfileId() {
+        return s3GroupResourceProfileId;
+    }
+
+    public S3StoGroupResourceProfileEntity setS3GroupResourceProfileId(String s3GroupResourceProfileId) {
+        this.s3GroupResourceProfileId = s3GroupResourceProfileId;
+        return this;
+    }
+
+    public String getGatewayId() {
+        return gatewayId;
+    }
+
+    public S3StoGroupResourceProfileEntity setGatewayId(String gatewayId) {
+        this.gatewayId = gatewayId;
+        return this;
+    }
+
+    public String getS3GroupResourceProfileName() {
+        return s3GroupResourceProfileName;
+    }
+
+    public S3StoGroupResourceProfileEntity setS3GroupResourceProfileName(String s3GroupResourceProfileName) {
+        this.s3GroupResourceProfileName = s3GroupResourceProfileName;
+        return this;
+    }
+
+    public Long getCreationTime() {
+        return creationTime;
+    }
+
+    public S3StoGroupResourceProfileEntity setCreationTime(Long creationTime) {
+        this.creationTime = creationTime;
+        return this;
+    }
+
+    public Long getUpdatedTime() {
+        return updatedTime;
+    }
+
+    public S3StoGroupResourceProfileEntity setUpdatedTime(Long updatedTime) {
+        this.updatedTime = updatedTime;
+        return this;
+    }
+
+    public String getDefaultS3CredentialStoreToken() {
+        return defaultS3CredentialStoreToken;
+    }
+
+    public S3StoGroupResourceProfileEntity setDefaultS3CredentialStoreToken(String defaultS3CredentialStoreToken) {
+        this.defaultS3CredentialStoreToken = defaultS3CredentialStoreToken;
+        return this;
+    }
+
+    public List<S3StoGroupPreferenceEntity> getS3StoragePreferences() {
+        return s3StoragePreferences;
+    }
+
+    public S3StoGroupResourceProfileEntity setS3StoragePreferences(List<S3StoGroupPreferenceEntity> s3StoragePreferences) {
+        this.s3StoragePreferences = s3StoragePreferences;
+        return this;
+    }
+}
+
diff --git a/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/s3/entity/S3StorageEntity.java b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/s3/entity/S3StorageEntity.java
new file mode 100644
index 0000000..ce0ecc4
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/s3/entity/S3StorageEntity.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.airavata.resource.profile.storage.s3.entity;
+
+import org.hibernate.annotations.GenericGenerator;
+
+import javax.persistence.*;
+
+@Entity
+@Table(name = "S3_STORAGE_ENTITY")
+public class S3StorageEntity {
+
+    @Id
+    @GeneratedValue(generator = "UUID")
+    @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
+    @Column(name = "S3_STORAGE_ID")
+    private String s3StorageId;
+
+    @Column(name = "REGION")
+    private String region;
+
+    @Column(name = "BUCKET_NAME")
+    private String bucketName;
+
+    public String getS3StorageId() {
+        return s3StorageId;
+    }
+
+    public S3StorageEntity setS3StorageId(String s3StorageId) {
+        this.s3StorageId = s3StorageId;
+        return this;
+    }
+
+    public String getRegion() {
+        return region;
+    }
+
+    public S3StorageEntity setRegion(String region) {
+        this.region = region;
+        return this;
+    }
+
+    public String getBucketName() {
+        return bucketName;
+    }
+
+    public S3StorageEntity setBucketName(String bucketName) {
+        this.bucketName = bucketName;
+        return this;
+    }
+}
+
diff --git a/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/s3/repository/S3StoGroupPreferenceRepository.java b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/s3/repository/S3StoGroupPreferenceRepository.java
new file mode 100644
index 0000000..5573bd1
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/s3/repository/S3StoGroupPreferenceRepository.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.airavata.resource.profile.storage.s3.repository;
+
+import org.apache.airavata.resource.profile.storage.s3.entity.S3StoGroupPreferenceEntity;
+import org.apache.airavata.resource.profile.storage.s3.entity.S3StoGroupPreferenceId;
+import org.springframework.data.repository.CrudRepository;
+
+public interface S3StoGroupPreferenceRepository extends CrudRepository<S3StoGroupPreferenceEntity, S3StoGroupPreferenceId> {
+}
diff --git a/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/s3/repository/S3StoGroupResourceProfileRepository.java b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/s3/repository/S3StoGroupResourceProfileRepository.java
new file mode 100644
index 0000000..0719042
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/s3/repository/S3StoGroupResourceProfileRepository.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.airavata.resource.profile.storage.s3.repository;
+
+import org.apache.airavata.resource.profile.storage.s3.entity.S3StoGroupResourceProfileEntity;
+import org.springframework.data.repository.CrudRepository;
+
+public interface S3StoGroupResourceProfileRepository extends CrudRepository<S3StoGroupResourceProfileEntity, String> {
+}
diff --git a/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/s3/repository/S3StorageRepository.java b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/s3/repository/S3StorageRepository.java
new file mode 100644
index 0000000..1f9ad9d
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/s3/repository/S3StorageRepository.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.airavata.resource.profile.storage.s3.repository;
+
+import org.apache.airavata.resource.profile.storage.s3.entity.S3StorageEntity;
+import org.springframework.data.repository.CrudRepository;
+
+public interface S3StorageRepository extends CrudRepository<S3StorageEntity, String> {
+}
diff --git a/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/scp/entity/SCPStoGroupPreferenceEntity.java b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/scp/entity/SCPStoGroupPreferenceEntity.java
new file mode 100644
index 0000000..4aa1cc9
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/scp/entity/SCPStoGroupPreferenceEntity.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.airavata.resource.profile.storage.scp.entity;
+
+import javax.persistence.*;
+
+@Entity
+// TODO Add PK class
+@Table(name = "SCP_STORAGE_GROUP_PREFERENCE")
+@IdClass(SCPStoGroupPreferenceId.class)
+public class SCPStoGroupPreferenceEntity {
+
+    @Id
+    @Column(name = "SCP_STORAGE_ID")
+    private String scpStorageId;
+
+    @Id
+    @Column(name = "SCP_GROUP_RESOURCE_PROFILE_ID")
+    private String scpGroupResourceProfileId;
+
+    @Column(name = "LOGIN_USER_NAME")
+    private String loginUserName;
+
+    @Column(name = "RESOURCE_CS_TOKEN")
+    private String resourceSpecificCredentialToken;
+
+    @ManyToOne(targetEntity = SCPStoGroupResourceProfileEntity.class, cascade = CascadeType.ALL)
+    @JoinColumn(name = "SCP_GROUP_RESOURCE_PROFILE_ID", insertable = false, updatable = false)
+    private SCPStoGroupResourceProfileEntity scpGroupResourceProfile;
+
+
+    @ManyToOne(targetEntity = SCPStorageEntity.class, cascade = CascadeType.ALL)
+    @JoinColumn(name = "SCP_STORAGE_ID", insertable = false, updatable = false)
+    private  SCPStorageEntity scpStorage;
+
+    public String getScpStorageId() {
+        return scpStorageId;
+    }
+
+    public SCPStoGroupPreferenceEntity setScpStorageId(String scpStorageId) {
+        this.scpStorageId = scpStorageId;
+        return this;
+    }
+
+    public String getScpGroupResourceProfileId() {
+        return scpGroupResourceProfileId;
+    }
+
+    public SCPStoGroupPreferenceEntity setScpGroupResourceProfileId(String scpGroupResourceProfileId) {
+        this.scpGroupResourceProfileId = scpGroupResourceProfileId;
+        return this;
+    }
+
+    public String getLoginUserName() {
+        return loginUserName;
+    }
+
+    public SCPStoGroupPreferenceEntity setLoginUserName(String loginUserName) {
+        this.loginUserName = loginUserName;
+        return this;
+    }
+
+    public String getResourceSpecificCredentialToken() {
+        return resourceSpecificCredentialToken;
+    }
+
+    public SCPStoGroupPreferenceEntity setResourceSpecificCredentialToken(String resourceSpecificCredentialToken) {
+        this.resourceSpecificCredentialToken = resourceSpecificCredentialToken;
+        return this;
+    }
+
+    public SCPStoGroupResourceProfileEntity getScpGroupResourceProfile() {
+        return scpGroupResourceProfile;
+    }
+
+    public SCPStoGroupPreferenceEntity setScpGroupResourceProfile(SCPStoGroupResourceProfileEntity scpGroupResourceProfile) {
+        this.scpGroupResourceProfile = scpGroupResourceProfile;
+        return this;
+    }
+
+    public SCPStorageEntity getScpStorage() {
+        return scpStorage;
+    }
+
+    public SCPStoGroupPreferenceEntity setScpStorage(SCPStorageEntity scpStorage) {
+        this.scpStorage = scpStorage;
+        return this;
+    }
+}
+
diff --git a/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/scp/entity/SCPStoGroupPreferenceId.java b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/scp/entity/SCPStoGroupPreferenceId.java
new file mode 100644
index 0000000..2d181b8
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/scp/entity/SCPStoGroupPreferenceId.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.airavata.resource.profile.storage.scp.entity;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+public class SCPStoGroupPreferenceId implements Serializable {
+
+    private String scpStorageId;
+    private String scpGroupResourceProfileId;
+
+    public SCPStoGroupPreferenceId(String scpStorageId, String scpGroupResourceProfileId) {
+        this.scpStorageId = scpStorageId;
+        this.scpGroupResourceProfileId = scpGroupResourceProfileId;
+    }
+
+    public String getScpStorageId() {
+        return scpStorageId;
+    }
+
+    public SCPStoGroupPreferenceId setScpStorageId(String scpStorageId) {
+        this.scpStorageId = scpStorageId;
+        return this;
+    }
+
+    public String getScpGroupResourceProfileId() {
+        return scpGroupResourceProfileId;
+    }
+
+    public SCPStoGroupPreferenceId setScpGroupResourceProfileId(String scpGroupResourceProfileId) {
+        this.scpGroupResourceProfileId = scpGroupResourceProfileId;
+        return this;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof SCPStoGroupPreferenceId)) return false;
+        SCPStoGroupPreferenceId that = (SCPStoGroupPreferenceId) o;
+        return Objects.equals(getScpStorageId(), that.getScpStorageId()) &&
+                Objects.equals(getScpGroupResourceProfileId(), that.getScpGroupResourceProfileId());
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(getScpStorageId(), getScpGroupResourceProfileId());
+    }
+}
diff --git a/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/scp/entity/SCPStoGroupResourceProfileEntity.java b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/scp/entity/SCPStoGroupResourceProfileEntity.java
new file mode 100644
index 0000000..64df304
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/scp/entity/SCPStoGroupResourceProfileEntity.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.airavata.resource.profile.storage.scp.entity;
+
+import javax.persistence.*;
+import java.util.List;
+
+@Entity
+@Table(name = "SCP_STORAGE_GROUP_RESOURCE_PROFILE")
+public class SCPStoGroupResourceProfileEntity {
+
+    @Id
+    @Column(name = "SCP_GROUP_RESOURCE_PROFILE_ID")
+    private String scpGroupResourceProfileId;
+
+    @Column(name = "GATEWAY_ID")
+    private String gatewayId;
+
+    @Column(name = "SCP_GROUP_RESOURCE_PROFILE_NAME")
+    private String scpGroupResourceProfileName;
+
+    @Column(name = "CREATION_TIME", updatable = false)
+    private Long creationTime;
+
+    @Column(name = "UPDATE_TIME")
+    private Long updatedTime;
+
+    @Column(name = "DEFAULT_SCP_CREDENTIAL_STORE_TOKEN")
+    private String defaultSCPCredentialStoreToken;
+
+    @OneToMany(targetEntity = SCPStoGroupPreferenceEntity.class, cascade = CascadeType.ALL,
+            mappedBy = "scpGroupResourceProfileId", fetch = FetchType.EAGER, orphanRemoval = true)
+    private List<SCPStoGroupPreferenceEntity> scpStoragePreferences;
+
+    public String getScpGroupResourceProfileId() {
+        return scpGroupResourceProfileId;
+    }
+
+    public SCPStoGroupResourceProfileEntity setScpGroupResourceProfileId(String scpGroupResourceProfileId) {
+        this.scpGroupResourceProfileId = scpGroupResourceProfileId;
+        return this;
+    }
+
+    public String getGatewayId() {
+        return gatewayId;
+    }
+
+    public SCPStoGroupResourceProfileEntity setGatewayId(String gatewayId) {
+        this.gatewayId = gatewayId;
+        return this;
+    }
+
+    public String getScpGroupResourceProfileName() {
+        return scpGroupResourceProfileName;
+    }
+
+    public SCPStoGroupResourceProfileEntity setScpGroupResourceProfileName(String scpGroupResourceProfileName) {
+        this.scpGroupResourceProfileName = scpGroupResourceProfileName;
+        return this;
+    }
+
+    public Long getCreationTime() {
+        return creationTime;
+    }
+
+    public SCPStoGroupResourceProfileEntity setCreationTime(Long creationTime) {
+        this.creationTime = creationTime;
+        return this;
+    }
+
+    public Long getUpdatedTime() {
+        return updatedTime;
+    }
+
+    public SCPStoGroupResourceProfileEntity setUpdatedTime(Long updatedTime) {
+        this.updatedTime = updatedTime;
+        return this;
+    }
+
+    public String getDefaultSCPCredentialStoreToken() {
+        return defaultSCPCredentialStoreToken;
+    }
+
+    public SCPStoGroupResourceProfileEntity setDefaultSCPCredentialStoreToken(String defaultSCPCredentialStoreToken) {
+        this.defaultSCPCredentialStoreToken = defaultSCPCredentialStoreToken;
+        return this;
+    }
+
+    public List<SCPStoGroupPreferenceEntity> getScpStoragePreferences() {
+        return scpStoragePreferences;
+    }
+
+    public SCPStoGroupResourceProfileEntity setScpStoragePreferences(List<SCPStoGroupPreferenceEntity> scpStoragePreferences) {
+        this.scpStoragePreferences = scpStoragePreferences;
+        return this;
+    }
+}
diff --git a/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/scp/entity/SCPStorageEntity.java b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/scp/entity/SCPStorageEntity.java
new file mode 100644
index 0000000..d1db065
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/scp/entity/SCPStorageEntity.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.airavata.resource.profile.storage.scp.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "SCP_STORAGE_ENTITY")
+public class SCPStorageEntity {
+
+    @Id
+    @Column(name = "SCP_STORAGE_ID")
+    private String scpStorageId;
+
+    @Column(name = "HOST_NAME")
+    private String hostName;
+
+    @Column(name = "PORT")
+    private String port;
+
+    public String getScpStorageId() {
+        return scpStorageId;
+    }
+
+    public SCPStorageEntity setScpStorageId(String scpStorageId) {
+        this.scpStorageId = scpStorageId;
+        return this;
+    }
+
+    public String getHostName() {
+        return hostName;
+    }
+
+    public SCPStorageEntity setHostName(String hostName) {
+        this.hostName = hostName;
+        return this;
+    }
+
+    public String getPort() {
+        return port;
+    }
+
+    public SCPStorageEntity setPort(String port) {
+        this.port = port;
+        return this;
+    }
+}
diff --git a/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/scp/repository/SCPStoGroupPreferenceRepository.java b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/scp/repository/SCPStoGroupPreferenceRepository.java
new file mode 100644
index 0000000..320638f
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/scp/repository/SCPStoGroupPreferenceRepository.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.airavata.resource.profile.storage.scp.repository;
+
+import org.apache.airavata.resource.profile.storage.scp.entity.SCPStoGroupPreferenceEntity;
+import org.apache.airavata.resource.profile.storage.scp.entity.SCPStoGroupPreferenceId;
+import org.springframework.data.repository.CrudRepository;
+
+public interface SCPStoGroupPreferenceRepository extends CrudRepository<SCPStoGroupPreferenceEntity, SCPStoGroupPreferenceId> {
+}
diff --git a/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/scp/repository/SCPStoGroupResourceProfileRepository.java b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/scp/repository/SCPStoGroupResourceProfileRepository.java
new file mode 100644
index 0000000..7049f4d
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/scp/repository/SCPStoGroupResourceProfileRepository.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.airavata.resource.profile.storage.scp.repository;
+
+import org.apache.airavata.resource.profile.storage.scp.entity.SCPStoGroupResourceProfileEntity;
+import org.springframework.data.repository.CrudRepository;
+
+public interface SCPStoGroupResourceProfileRepository extends CrudRepository<SCPStoGroupResourceProfileEntity, String> {
+}
diff --git a/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/scp/repository/SCPStorageRepository.java b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/scp/repository/SCPStorageRepository.java
new file mode 100644
index 0000000..ba82e59
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/src/main/java/org/apache/airavata/resource/profile/storage/scp/repository/SCPStorageRepository.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.airavata.resource.profile.storage.scp.repository;
+
+import org.apache.airavata.resource.profile.storage.scp.entity.SCPStorageEntity;
+import org.springframework.data.repository.CrudRepository;
+
+public interface SCPStorageRepository extends CrudRepository<SCPStorageEntity, String> {
+}
diff --git a/modules/resource-profile/resource-profile-service/src/main/resources/application.properties b/modules/resource-profile/resource-profile-service/src/main/resources/application.properties
new file mode 100644
index 0000000..56db2de
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/src/main/resources/application.properties
@@ -0,0 +1,2 @@
+server.port=18080
+grpc.port=17002
\ No newline at end of file
diff --git a/modules/resource-profile/resource-profile-service/src/main/resources/applicationContext.xml b/modules/resource-profile/resource-profile-service/src/main/resources/applicationContext.xml
new file mode 100644
index 0000000..bb7b7cb
--- /dev/null
+++ b/modules/resource-profile/resource-profile-service/src/main/resources/applicationContext.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans.xsd
+        http://www.springframework.org/schema/context
+        http://www.springframework.org/schema/context/spring-context.xsd">
+
+
+</beans>
\ No newline at end of file
diff --git a/modules/resource-profile/resource-profile-stubs/pom.xml b/modules/resource-profile/resource-profile-stubs/pom.xml
new file mode 100644
index 0000000..0a62f1e
--- /dev/null
+++ b/modules/resource-profile/resource-profile-stubs/pom.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you 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>resource-profile</artifactId>
+        <groupId>org.apache.airavata</groupId>
+        <version>0.21-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>resource-profile-stubs</artifactId>
+
+    <properties>
+        <maven.compiler.source>11</maven.compiler.source>
+        <maven.compiler.target>11</maven.compiler.target>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.google.protobuf</groupId>
+            <artifactId>protobuf-java</artifactId>
+            <version>${protobuf.java}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.grpc</groupId>
+            <artifactId>grpc-services</artifactId>
+            <version>1.35.0</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.google.code.gson</groupId>
+                    <artifactId>gson</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>javax.annotation</groupId>
+            <artifactId>javax.annotation-api</artifactId>
+            <version>${javax.annotation}</version>
+        </dependency>
+    </dependencies>
+    <build>
+        <extensions>
+            <extension>
+                <groupId>kr.motd.maven</groupId>
+                <artifactId>os-maven-plugin</artifactId>
+                <version>${os.maven.plugin}</version>
+            </extension>
+        </extensions>
+        <plugins>
+            <plugin>
+                <groupId>org.xolstice.maven.plugins</groupId>
+                <artifactId>protobuf-maven-plugin</artifactId>
+                <version>${protobuf.maven.plugin}</version>
+                <configuration>
+                    <protocArtifact>com.google.protobuf:protoc:3.0.2:exe:${os.detected.classifier}</protocArtifact>
+                    <pluginId>grpc-java</pluginId>
+                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.0.1:exe:${os.detected.classifier}</pluginArtifact>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>compile</goal>
+                            <goal>compile-custom</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/modules/resource-profile/resource-profile-stubs/src/main/proto/common.proto b/modules/resource-profile/resource-profile-stubs/src/main/proto/common.proto
new file mode 100644
index 0000000..5557d8c
--- /dev/null
+++ b/modules/resource-profile/resource-profile-stubs/src/main/proto/common.proto
@@ -0,0 +1,8 @@
+syntax = "proto3";
+
+option java_multiple_files = true;
+package org.apache.airavata.resource.profile.stubs.common;
+
+message AuthzToken {
+    string authorizationToken = 1;
+}
\ No newline at end of file
diff --git a/modules/resource-profile/resource-profile-stubs/src/main/proto/storage/s3/service.proto b/modules/resource-profile/resource-profile-stubs/src/main/proto/storage/s3/service.proto
new file mode 100644
index 0000000..c6cdafd
--- /dev/null
+++ b/modules/resource-profile/resource-profile-stubs/src/main/proto/storage/s3/service.proto
@@ -0,0 +1,158 @@
+syntax = "proto3";
+
+option java_multiple_files = true;
+package org.apache.airavata.resource.profile.service.s3;
+
+import "google/api/annotations.proto";
+import "google/protobuf/empty.proto";
+import "storage/s3/stubs.proto";
+import "common.proto";
+
+/// S3Storage ///
+
+message S3StorageCreateRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    org.apache.airavata.resource.profile.stubs.s3.S3Storage s3Storage = 2;
+}
+
+message S3StorageCreateResponse {
+    org.apache.airavata.resource.profile.stubs.s3.S3Storage s3Storage = 1;
+}
+
+message S3StorageUpdateRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    org.apache.airavata.resource.profile.stubs.s3.S3Storage s3Storage = 2;
+}
+
+message S3StorageRemoveRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    string s3StorageId = 2;
+}
+
+message S3StorageFetchRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    string s3StorageId = 2;
+}
+
+message S3StorageFetchResponse {
+    org.apache.airavata.resource.profile.stubs.s3.S3Storage s3Storage = 1;
+}
+
+message S3StorageListRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    string filterQuery = 2;
+}
+
+message S3StorageListResponse {
+    repeated org.apache.airavata.resource.profile.stubs.s3.S3Storage s3Storages = 1;
+}
+
+/// S3StoGroupPreference ///
+
+message S3StoGroupPreferenceCreateRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    org.apache.airavata.resource.profile.stubs.s3.S3StoGroupPreference s3StoGroupPreference = 2;
+}
+
+message S3StoGroupPreferenceCreateResponse {
+    org.apache.airavata.resource.profile.stubs.s3.S3StoGroupPreference s3StoGroupPreference = 1;
+}
+
+message S3StoGroupPreferenceUpdateRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    org.apache.airavata.resource.profile.stubs.s3.S3StoGroupPreference s3StoGroupPreference = 2;
+}
+
+message S3StoGroupPreferenceRemoveRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    string s3StorageId = 2;
+    string s3GroupResourceProfileId = 3;
+}
+
+message S3StoGroupPreferenceFetchRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    string s3StorageId = 2;
+    string s3GroupResourceProfileId = 3;
+}
+
+message S3StoGroupPreferenceFetchResponse {
+    org.apache.airavata.resource.profile.stubs.s3.S3StoGroupPreference s3StoGroupPreference = 1;
+}
+
+/// S3StoGroupResourceProfile ///
+
+message S3StoGroupResourceProfileCreateRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    org.apache.airavata.resource.profile.stubs.s3.S3StoGroupResourceProfile s3StoGroupResourceProfile = 2;
+}
+
+message S3StoGroupResourceProfileCreateResponse {
+    org.apache.airavata.resource.profile.stubs.s3.S3StoGroupResourceProfile s3StoGroupResourceProfile = 1;
+}
+
+message S3StoGroupResourceProfileUpdateRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    org.apache.airavata.resource.profile.stubs.s3.S3StoGroupResourceProfile s3StoGroupResourceProfile = 2;
+}
+
+message S3StoGroupResourceProfileRemoveRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    string s3StoGroupResourceProfileId = 2;
+}
+
+message S3StoGroupResourceProfileFetchRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    string s3StoGroupResourceProfileId = 2;
+}
+
+message S3StoGroupResourceProfileFetchResponse {
+    org.apache.airavata.resource.profile.stubs.s3.S3StoGroupResourceProfile s3StoGroupResourceProfile = 1;
+}
+
+message S3StoGroupResourceProfileListRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    string filterQuery = 2;
+}
+
+message S3StoGroupResourceProfileListResponse {
+    repeated org.apache.airavata.resource.profile.stubs.s3.S3StoGroupResourceProfile s3StoGroupResourceProfiles = 1;
+}
+
+service S3StorageService {
+
+    /// S3Storage ///
+
+    rpc createS3Storage (S3StorageCreateRequest) returns (S3StorageCreateResponse) {};
+
+    rpc updateS3Storage (S3StorageUpdateRequest) returns (google.protobuf.Empty) {};
+
+    rpc removeS3Storage (S3StorageRemoveRequest) returns (google.protobuf.Empty) {};
+
+    rpc fetchS3Storage (S3StorageFetchRequest) returns (S3StorageFetchResponse) {};
+
+    rpc listS3Storage (S3StorageListRequest) returns (S3StorageListResponse) {};
+
+    /// S3StoGroupPreference ///
+
+    rpc createS3StoGroupPreference (S3StoGroupPreferenceCreateRequest) returns (S3StoGroupPreferenceCreateResponse) {};
+
+    rpc updateS3StoGroupPreference (S3StoGroupPreferenceUpdateRequest) returns (google.protobuf.Empty) {};
+
+    rpc removeS3StoGroupPreference (S3StoGroupPreferenceRemoveRequest) returns (google.protobuf.Empty) {};
+
+    rpc fetchS3StoGroupPreference (S3StoGroupPreferenceFetchRequest) returns (S3StoGroupPreferenceFetchResponse) {};
+
+    /// S3StoGroupResourceProfile ///
+
+    rpc createS3StoGroupResourceProfile (S3StoGroupResourceProfileCreateRequest) returns (S3StoGroupResourceProfileCreateResponse) {};
+
+    rpc updateS3StoGroupResourceProfile (S3StoGroupResourceProfileUpdateRequest) returns (google.protobuf.Empty) {};
+
+    rpc removeS3StoGroupResourceProfile (S3StoGroupResourceProfileRemoveRequest) returns (google.protobuf.Empty) {};
+
+    rpc fetchS3StoGroupResourceProfile (S3StoGroupResourceProfileFetchRequest) returns (S3StoGroupResourceProfileFetchResponse) {};
+
+    rpc listS3StoGroupResourceProfile (S3StoGroupResourceProfileListRequest) returns (S3StoGroupResourceProfileListResponse) {};
+}
+
+
diff --git a/modules/resource-profile/resource-profile-stubs/src/main/proto/storage/s3/stubs.proto b/modules/resource-profile/resource-profile-stubs/src/main/proto/storage/s3/stubs.proto
new file mode 100644
index 0000000..dfc7ce4
--- /dev/null
+++ b/modules/resource-profile/resource-profile-stubs/src/main/proto/storage/s3/stubs.proto
@@ -0,0 +1,26 @@
+syntax = "proto3";
+
+option java_multiple_files = true;
+package org.apache.airavata.resource.profile.stubs.s3;
+
+message S3Storage {
+    optional string s3StorageId = 1;
+    string region = 2;
+    string bucketName = 3;
+}
+
+message S3StoGroupPreference {
+    string s3StorageId = 1;
+    string s3GroupResourceProfileId = 2;
+    string resourceSpecificCredentialToken = 3;
+}
+
+message S3StoGroupResourceProfile {
+    string s3GroupResourceProfileId = 1;
+    string gatewayId = 2;
+    string s3GroupResourceProfileName = 3;
+    int64 creationTime = 4;
+    int64 updatedTime = 5;
+    string defaultS3CredentialStoreToken = 6;
+    repeated S3StoGroupPreference s3StoragePreferences = 7;
+}
\ No newline at end of file
diff --git a/modules/resource-profile/resource-profile-stubs/src/main/proto/storage/scp/service.proto b/modules/resource-profile/resource-profile-stubs/src/main/proto/storage/scp/service.proto
new file mode 100644
index 0000000..f5b0960
--- /dev/null
+++ b/modules/resource-profile/resource-profile-stubs/src/main/proto/storage/scp/service.proto
@@ -0,0 +1,158 @@
+syntax = "proto3";
+
+option java_multiple_files = true;
+package org.apache.airavata.resource.profile.service.scp;
+
+import "google/api/annotations.proto";
+import "google/protobuf/empty.proto";
+import "storage/scp/stubs.proto";
+import "common.proto";
+
+/// SCPStorage ///
+
+message SCPStorageCreateRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    org.apache.airavata.resource.profile.stubs.scp.SCPStorage scpStorage = 2;
+}
+
+message SCPStorageCreateResponse {
+    org.apache.airavata.resource.profile.stubs.scp.SCPStorage scpStorage = 1;
+}
+
+message SCPStorageUpdateRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    org.apache.airavata.resource.profile.stubs.scp.SCPStorage scpStorage = 2;
+}
+
+message SCPStorageRemoveRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    string scpStorageId = 2;
+}
+
+message SCPStorageFetchRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    string scpStorageId = 2;
+}
+
+message SCPStorageFetchResponse {
+    org.apache.airavata.resource.profile.stubs.scp.SCPStorage scpStorage = 1;
+}
+
+message SCPStorageListRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    string filterQuery = 2;
+}
+
+message SCPStorageListResponse {
+    repeated org.apache.airavata.resource.profile.stubs.scp.SCPStorage scpStorages = 1;
+}
+
+/// SCPStoGroupPreference ///
+
+message SCPStoGroupPreferenceCreateRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    org.apache.airavata.resource.profile.stubs.scp.SCPStoGroupPreference scpStoGroupPreference = 2;
+}
+
+message SCPStoGroupPreferenceCreateResponse {
+    org.apache.airavata.resource.profile.stubs.scp.SCPStoGroupPreference scpStoGroupPreference = 1;
+}
+
+message SCPStoGroupPreferenceUpdateRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    org.apache.airavata.resource.profile.stubs.scp.SCPStoGroupPreference scpStoGroupPreference = 2;
+}
+
+message SCPStoGroupPreferenceRemoveRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    string scpStorageId = 2;
+    string scpGroupResourceProfileId = 3;
+}
+
+message SCPStoGroupPreferenceFetchRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    string scpStorageId = 2;
+    string scpGroupResourceProfileId = 3;
+}
+
+message SCPStoGroupPreferenceFetchResponse {
+    org.apache.airavata.resource.profile.stubs.scp.SCPStoGroupPreference scpStoGroupPreference = 1;
+}
+
+/// SCPStoGroupResourceProfile ///
+
+message SCPStoGroupResourceProfileCreateRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    org.apache.airavata.resource.profile.stubs.scp.SCPStoGroupResourceProfile scpStoGroupResourceProfile = 2;
+}
+
+message SCPStoGroupResourceProfileCreateResponse {
+    org.apache.airavata.resource.profile.stubs.scp.SCPStoGroupResourceProfile scpStoGroupResourceProfile = 1;
+}
+
+message SCPStoGroupResourceProfileUpdateRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    org.apache.airavata.resource.profile.stubs.scp.SCPStoGroupResourceProfile scpStoGroupResourceProfile = 2;
+}
+
+message SCPStoGroupResourceProfileRemoveRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    string scpStoGroupResourceProfileId = 2;
+}
+
+message SCPStoGroupResourceProfileFetchRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    string scpStoGroupResourceProfileId = 2;
+}
+
+message SCPStoGroupResourceProfileFetchResponse {
+    org.apache.airavata.resource.profile.stubs.scp.SCPStoGroupResourceProfile scpStoGroupResourceProfile = 1;
+}
+
+message SCPStoGroupResourceProfileListRequest {
+    org.apache.airavata.resource.profile.stubs.common.AuthzToken authzToken = 1;
+    string filterQuery = 2;
+}
+
+message SCPStoGroupResourceProfileListResponse {
+    repeated org.apache.airavata.resource.profile.stubs.scp.SCPStoGroupResourceProfile scpStoGroupResourceProfiles = 1;
+}
+
+service SCPStorageService {
+
+    /// SCPStorage ///
+
+    rpc createSCPStorage (SCPStorageCreateRequest) returns (SCPStorageCreateResponse) {};
+
+    rpc updateSCPStorage (SCPStorageUpdateRequest) returns (google.protobuf.Empty) {};
+
+    rpc removeSCPStorage (SCPStorageRemoveRequest) returns (google.protobuf.Empty) {};
+
+    rpc fetchSCPStorage (SCPStorageFetchRequest) returns (SCPStorageFetchResponse) {};
+
+    rpc listSCPStorage (SCPStorageListRequest) returns (SCPStorageListResponse) {};
+
+    /// SCPStoGroupPreference ///
+
+    rpc createSCPStoGroupPreference (SCPStoGroupPreferenceCreateRequest) returns (SCPStoGroupPreferenceCreateResponse) {};
+
+    rpc updateSCPStoGroupPreference (SCPStoGroupPreferenceUpdateRequest) returns (google.protobuf.Empty) {};
+
+    rpc removeSCPStoGroupPreference (SCPStoGroupPreferenceRemoveRequest) returns (google.protobuf.Empty) {};
+
+    rpc fetchSCPStoGroupPreference (SCPStoGroupPreferenceFetchRequest) returns (SCPStoGroupPreferenceFetchResponse) {};
+
+    /// SCPStoGroupResourceProfile ///
+
+    rpc createSCPStoGroupResourceProfile (SCPStoGroupResourceProfileCreateRequest) returns (SCPStoGroupResourceProfileCreateResponse) {};
+
+    rpc updateSCPStoGroupResourceProfile (SCPStoGroupResourceProfileUpdateRequest) returns (google.protobuf.Empty) {};
+
+    rpc removeSCPStoGroupResourceProfile (SCPStoGroupResourceProfileRemoveRequest) returns (google.protobuf.Empty) {};
+
+    rpc fetchSCPStoGroupResourceProfile (SCPStoGroupResourceProfileFetchRequest) returns (SCPStoGroupResourceProfileFetchResponse) {};
+
+    rpc listSCPStoGroupResourceProfile (SCPStoGroupResourceProfileListRequest) returns (SCPStoGroupResourceProfileListResponse) {};
+}
+
+
diff --git a/modules/resource-profile/resource-profile-stubs/src/main/proto/storage/scp/stubs.proto b/modules/resource-profile/resource-profile-stubs/src/main/proto/storage/scp/stubs.proto
new file mode 100644
index 0000000..b8cc0ad
--- /dev/null
+++ b/modules/resource-profile/resource-profile-stubs/src/main/proto/storage/scp/stubs.proto
@@ -0,0 +1,27 @@
+syntax = "proto3";
+
+option java_multiple_files = true;
+package org.apache.airavata.resource.profile.stubs.scp;
+
+message SCPStorage {
+    string scpStorageId = 1;
+    string hostName = 2;
+    int32 port = 3;
+}
+
+message SCPStoGroupPreference {
+    string scpStorageId = 1;
+    string scpGroupResourceProfileId = 2;
+    string loginUserName = 3;
+    string resourceSpecificCredentialToken = 4;
+}
+
+message SCPStoGroupResourceProfile {
+    string scpGroupResourceProfileId = 1;
+    string gatewayId = 2;
+    string scpGroupResourceProfileName = 3;
+    int64 creationTime = 4;
+    int64 updatedTime = 5;
+    string defaultSCPCredentialStoreToken = 6;
+    repeated SCPStoGroupPreference scpStoragePreferences = 7;
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 1979fef..5f017be 100644
--- a/pom.xml
+++ b/pom.xml
@@ -590,13 +590,7 @@
                             </execution>
                         </executions>
                     </plugin>
-		    <plugin>
-		       <groupId>org.apache.maven.plugins</groupId>
-		       <artifactId>maven-jar-plugins</artifactId>
-		       <version>${openjpa.version}</version>
-		    </plugin>
-		    
-		    <plugin>
+		            <plugin>
                         <groupId>com.lukegb.mojo</groupId>
                         <artifactId>gitdescribe-maven-plugin</artifactId>
                         <version>3.0</version>
@@ -784,6 +778,7 @@
                 <module>modules/compute-account-provisioning</module>
                 <module>modules/job-monitor</module>
                 <module>modules/platform-monitoring</module>
+                <module>modules/resource-profile</module>
                 <module>modules/distribution</module>
                 <module>tools</module>
                 <module>modules/ide-integration</module>