Skip to content

Commit 6149ad0

Browse files
committed
iam: implement substrate neutral policy document model
1 parent 5a56444 commit 6149ad0

File tree

92 files changed

+4612
-633
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

92 files changed

+4612
-633
lines changed

examples/pom.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,16 @@
8181
<artifactId>docstore-aws</artifactId>
8282
<version>${project.version}</version>
8383
</dependency>
84+
<dependency>
85+
<groupId>com.salesforce.multicloudj</groupId>
86+
<artifactId>iam-aws</artifactId>
87+
<version>${project.version}</version>
88+
</dependency>
89+
<dependency>
90+
<groupId>com.salesforce.multicloudj</groupId>
91+
<artifactId>iam-gcp</artifactId>
92+
<version>${project.version}</version>
93+
</dependency>
8494
<dependency>
8595
<groupId>com.salesforce.multicloudj</groupId>
8696
<artifactId>dbbackuprestore-aws</artifactId>

examples/src/main/java/com/salesforce/multicloudj/iam/Main.java

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
import com.salesforce.multicloudj.iam.client.IamClient;
55
import com.salesforce.multicloudj.iam.model.AttachInlinePolicyRequest;
66
import com.salesforce.multicloudj.iam.model.CreateOptions;
7+
import com.salesforce.multicloudj.iam.model.Effect;
78
import com.salesforce.multicloudj.iam.model.GetAttachedPoliciesRequest;
89
import com.salesforce.multicloudj.iam.model.GetInlinePolicyDetailsRequest;
910
import com.salesforce.multicloudj.iam.model.PolicyDocument;
1011
import com.salesforce.multicloudj.iam.model.Statement;
12+
import com.salesforce.multicloudj.iam.model.StorageActions;
1113
import com.salesforce.multicloudj.iam.model.TrustConfiguration;
1214
import java.io.BufferedReader;
1315
import java.io.IOException;
@@ -275,7 +277,7 @@ private void demonstratePolicyManagement() {
275277
"Press Enter to remove the storage policy (check cloud console before proceeding)...");
276278
showInfo("Removing storage policy...");
277279
try {
278-
removePolicy("roles/storage.admin");
280+
removePolicy("storage-policy");
279281
showSuccess("Successfully removed storage policy");
280282
} catch (Exception e) {
281283
showError("Failed to remove policy: " + e.getMessage());
@@ -374,20 +376,37 @@ private void deleteIdentity(String identityName) throws Exception {
374376
}
375377

376378
/**
377-
* Attach a storage policy using a single comprehensive GCP IAM role. Using roles/storage.admin
378-
* which provides full storage permissions.
379+
* Attach a storage policy using substrate-neutral actions. These actions will be translated to
380+
* cloud-specific formats: - AWS: storage:GetObject → s3:GetObject, storage:* → s3:* - GCP:
381+
* storage:GetObject → roles/storage.objectViewer, storage:* → roles/storage.admin
379382
*/
380383
private void attachStoragePolicy() throws Exception {
381384
try (IamClient iamClient = initializeClient()) {
382-
// Create a policy document using a single comprehensive GCP IAM role
385+
// Create a comprehensive policy document using substrate-neutral actions
383386
PolicyDocument policyDocument =
384387
PolicyDocument.builder()
385388
.version("2024-01-01")
389+
.statement(
390+
Statement.builder()
391+
.sid("StorageReadAccess")
392+
.effect(Effect.ALLOW)
393+
.action(StorageActions.GET_OBJECT)
394+
.action(StorageActions.LIST_BUCKET)
395+
.resource("storage://demo-bucket/*")
396+
.build())
397+
.statement(
398+
Statement.builder()
399+
.sid("StorageWriteAccess")
400+
.effect(Effect.ALLOW)
401+
.action(StorageActions.PUT_OBJECT)
402+
.action(StorageActions.DELETE_OBJECT)
403+
.resource("storage://demo-bucket/*")
404+
.build())
386405
.statement(
387406
Statement.builder()
388407
.sid("StorageFullAccess")
389-
.effect("Allow")
390-
.action("roles/storage.admin")
408+
.effect(Effect.ALLOW)
409+
.action(StorageActions.ALL)
391410
.resource("storage://demo-bucket/*")
392411
.build())
393412
.build();

iam/iam-aws/src/main/java/com/salesforce/multicloudj/iam/aws/AwsIam.java

Lines changed: 3 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.salesforce.multicloudj.iam.aws;
22

3+
import static com.salesforce.multicloudj.iam.aws.AwsIamPolicyTranslator.translateToAwsPolicy;
4+
35
import com.fasterxml.jackson.core.JsonProcessingException;
46
import com.fasterxml.jackson.databind.JsonNode;
57
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -355,7 +357,7 @@ protected void doAttachInlinePolicy(AttachInlinePolicyRequest request) {
355357
}
356358

357359
String roleName = request.getIdentityName();
358-
String policyDocumentJson = buildInlinePolicyDocumentJson(request.getPolicyDocument());
360+
String policyDocumentJson = translateToAwsPolicy(request.getPolicyDocument());
359361

360362
PutRolePolicyRequest awsRequest =
361363
PutRolePolicyRequest.builder()
@@ -367,47 +369,6 @@ protected void doAttachInlinePolicy(AttachInlinePolicyRequest request) {
367369
this.iamClient.putRolePolicy(awsRequest);
368370
}
369371

370-
private static String buildInlinePolicyDocumentJson(PolicyDocument policyDocument) {
371-
String version = policyDocument.getVersion();
372-
if (StringUtils.isBlank(version)) {
373-
version = POLICY_VERSION;
374-
}
375-
Map<String, Object> doc = new LinkedHashMap<>();
376-
doc.put("Version", version);
377-
378-
List<Map<String, Object>> awsStatements = new ArrayList<>();
379-
for (Statement stmt : policyDocument.getStatements()) {
380-
Map<String, Object> awsStmt = new LinkedHashMap<>();
381-
awsStmt.put("Effect", stmt.getEffect());
382-
383-
List<String> actions = stmt.getActions();
384-
if (actions != null && !actions.isEmpty()) {
385-
awsStmt.put("Action", actions);
386-
}
387-
if (StringUtils.isNotBlank(stmt.getSid())) {
388-
awsStmt.put("Sid", stmt.getSid());
389-
}
390-
if (stmt.getResources() != null && !stmt.getResources().isEmpty()) {
391-
awsStmt.put("Resource", stmt.getResources());
392-
}
393-
if (stmt.getConditions() != null && !stmt.getConditions().isEmpty()) {
394-
awsStmt.put("Condition", stmt.getConditions());
395-
}
396-
if (stmt.getPrincipals() != null && !stmt.getPrincipals().isEmpty()) {
397-
awsStmt.put("Principal", stmt.getPrincipals());
398-
}
399-
400-
awsStatements.add(awsStmt);
401-
}
402-
doc.put("Statement", awsStatements);
403-
404-
try {
405-
return OBJECT_MAPPER.writeValueAsString(doc);
406-
} catch (JsonProcessingException e) {
407-
throw new InvalidArgumentException("Failed to serialize inline policy document", e);
408-
}
409-
}
410-
411372
/**
412373
* Get inline policy document attached to an IAM role.
413374
*

0 commit comments

Comments
 (0)