diff --git a/examples/pom.xml b/examples/pom.xml index 3ea9a8a08..2ba6d4d2a 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -81,6 +81,16 @@ docstore-aws ${project.version} + + com.salesforce.multicloudj + iam-aws + ${project.version} + + + com.salesforce.multicloudj + iam-gcp + ${project.version} + com.salesforce.multicloudj dbbackuprestore-aws diff --git a/examples/src/main/java/com/salesforce/multicloudj/iam/Main.java b/examples/src/main/java/com/salesforce/multicloudj/iam/Main.java index bf57d290e..8e4dc7741 100644 --- a/examples/src/main/java/com/salesforce/multicloudj/iam/Main.java +++ b/examples/src/main/java/com/salesforce/multicloudj/iam/Main.java @@ -4,10 +4,12 @@ import com.salesforce.multicloudj.iam.client.IamClient; import com.salesforce.multicloudj.iam.model.AttachInlinePolicyRequest; import com.salesforce.multicloudj.iam.model.CreateOptions; +import com.salesforce.multicloudj.iam.model.Effect; import com.salesforce.multicloudj.iam.model.GetAttachedPoliciesRequest; import com.salesforce.multicloudj.iam.model.GetInlinePolicyDetailsRequest; import com.salesforce.multicloudj.iam.model.PolicyDocument; import com.salesforce.multicloudj.iam.model.Statement; +import com.salesforce.multicloudj.iam.model.StorageActions; import com.salesforce.multicloudj.iam.model.TrustConfiguration; import java.io.BufferedReader; import java.io.IOException; @@ -275,7 +277,7 @@ private void demonstratePolicyManagement() { "Press Enter to remove the storage policy (check cloud console before proceeding)..."); showInfo("Removing storage policy..."); try { - removePolicy("roles/storage.admin"); + removePolicy("storage-policy"); showSuccess("Successfully removed storage policy"); } catch (Exception e) { showError("Failed to remove policy: " + e.getMessage()); @@ -374,20 +376,37 @@ private void deleteIdentity(String identityName) throws Exception { } /** - * Attach a storage policy using a single comprehensive GCP IAM role. Using roles/storage.admin - * which provides full storage permissions. + * Attach a storage policy using substrate-neutral actions. These actions will be translated to + * cloud-specific formats: - AWS: storage:GetObject → s3:GetObject, storage:* → s3:* - GCP: + * storage:GetObject → roles/storage.objectViewer, storage:* → roles/storage.admin */ private void attachStoragePolicy() throws Exception { try (IamClient iamClient = initializeClient()) { - // Create a policy document using a single comprehensive GCP IAM role + // Create a comprehensive policy document using substrate-neutral actions PolicyDocument policyDocument = PolicyDocument.builder() .version("2024-01-01") + .statement( + Statement.builder() + .sid("StorageReadAccess") + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .action(StorageActions.LIST_BUCKET) + .resource("storage://demo-bucket/*") + .build()) + .statement( + Statement.builder() + .sid("StorageWriteAccess") + .effect(Effect.ALLOW) + .action(StorageActions.PUT_OBJECT) + .action(StorageActions.DELETE_OBJECT) + .resource("storage://demo-bucket/*") + .build()) .statement( Statement.builder() .sid("StorageFullAccess") - .effect("Allow") - .action("roles/storage.admin") + .effect(Effect.ALLOW) + .action(StorageActions.ALL) .resource("storage://demo-bucket/*") .build()) .build(); diff --git a/iam/iam-aws/src/main/java/com/salesforce/multicloudj/iam/aws/AwsIam.java b/iam/iam-aws/src/main/java/com/salesforce/multicloudj/iam/aws/AwsIam.java index fc849d76a..63e948022 100644 --- a/iam/iam-aws/src/main/java/com/salesforce/multicloudj/iam/aws/AwsIam.java +++ b/iam/iam-aws/src/main/java/com/salesforce/multicloudj/iam/aws/AwsIam.java @@ -1,5 +1,7 @@ package com.salesforce.multicloudj.iam.aws; +import static com.salesforce.multicloudj.iam.aws.AwsIamPolicyTranslator.translateToAwsPolicy; + import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -355,7 +357,7 @@ protected void doAttachInlinePolicy(AttachInlinePolicyRequest request) { } String roleName = request.getIdentityName(); - String policyDocumentJson = buildInlinePolicyDocumentJson(request.getPolicyDocument()); + String policyDocumentJson = translateToAwsPolicy(request.getPolicyDocument()); PutRolePolicyRequest awsRequest = PutRolePolicyRequest.builder() @@ -367,47 +369,6 @@ protected void doAttachInlinePolicy(AttachInlinePolicyRequest request) { this.iamClient.putRolePolicy(awsRequest); } - private static String buildInlinePolicyDocumentJson(PolicyDocument policyDocument) { - String version = policyDocument.getVersion(); - if (StringUtils.isBlank(version)) { - version = POLICY_VERSION; - } - Map doc = new LinkedHashMap<>(); - doc.put("Version", version); - - List> awsStatements = new ArrayList<>(); - for (Statement stmt : policyDocument.getStatements()) { - Map awsStmt = new LinkedHashMap<>(); - awsStmt.put("Effect", stmt.getEffect()); - - List actions = stmt.getActions(); - if (actions != null && !actions.isEmpty()) { - awsStmt.put("Action", actions); - } - if (StringUtils.isNotBlank(stmt.getSid())) { - awsStmt.put("Sid", stmt.getSid()); - } - if (stmt.getResources() != null && !stmt.getResources().isEmpty()) { - awsStmt.put("Resource", stmt.getResources()); - } - if (stmt.getConditions() != null && !stmt.getConditions().isEmpty()) { - awsStmt.put("Condition", stmt.getConditions()); - } - if (stmt.getPrincipals() != null && !stmt.getPrincipals().isEmpty()) { - awsStmt.put("Principal", stmt.getPrincipals()); - } - - awsStatements.add(awsStmt); - } - doc.put("Statement", awsStatements); - - try { - return OBJECT_MAPPER.writeValueAsString(doc); - } catch (JsonProcessingException e) { - throw new InvalidArgumentException("Failed to serialize inline policy document", e); - } - } - /** * Get inline policy document attached to an IAM role. * diff --git a/iam/iam-aws/src/main/java/com/salesforce/multicloudj/iam/aws/AwsIamPolicyTranslator.java b/iam/iam-aws/src/main/java/com/salesforce/multicloudj/iam/aws/AwsIamPolicyTranslator.java new file mode 100644 index 000000000..d91604de2 --- /dev/null +++ b/iam/iam-aws/src/main/java/com/salesforce/multicloudj/iam/aws/AwsIamPolicyTranslator.java @@ -0,0 +1,324 @@ +package com.salesforce.multicloudj.iam.aws; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.salesforce.multicloudj.common.exceptions.InvalidArgumentException; +import com.salesforce.multicloudj.common.exceptions.SubstrateSdkException; +import com.salesforce.multicloudj.iam.model.Action; +import com.salesforce.multicloudj.iam.model.ComputeActions; +import com.salesforce.multicloudj.iam.model.ConditionOperator; +import com.salesforce.multicloudj.iam.model.IamActions; +import com.salesforce.multicloudj.iam.model.PolicyDocument; +import com.salesforce.multicloudj.iam.model.Statement; +import com.salesforce.multicloudj.iam.model.StorageActions; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.apache.commons.lang3.StringUtils; + +/** + * Translates substrate-neutral PolicyDocument to AWS IAM policy format. + * + *

This translator converts substrate-neutral actions, resources, and conditions to AWS-specific + * IAM policy JSON format according to the translation rules defined in PolicyDocument + * documentation. + * + *

Translation rules: + * + *

    + *
  • Actions: storage:GetObject → s3:GetObject, compute:CreateInstance → ec2:RunInstances + *
  • Resources: storage://bucket-name/* → arn:aws:s3:::bucket-name/* + *
  • Conditions: stringEquals → StringEquals (capitalize first letter) + *
  • Principals: Wrap in {"AWS": "principal"} or {"Service": "principal"} + *
+ */ +public class AwsIamPolicyTranslator { + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + private static final String SERVICE_PRINCIPAL_SUFFIX = ".amazonaws.com"; + + // Action mappings: substrate-neutral → AWS + private static final Map ACTION_MAPPINGS = + Map.ofEntries( + // Storage actions + Map.entry(StorageActions.GET_OBJECT, "s3:GetObject"), + Map.entry(StorageActions.PUT_OBJECT, "s3:PutObject"), + Map.entry(StorageActions.DELETE_OBJECT, "s3:DeleteObject"), + Map.entry(StorageActions.LIST_BUCKET, "s3:ListBucket"), + Map.entry(StorageActions.GET_BUCKET_LOCATION, "s3:GetBucketLocation"), + Map.entry(StorageActions.CREATE_BUCKET, "s3:CreateBucket"), + Map.entry(StorageActions.DELETE_BUCKET, "s3:DeleteBucket"), + + // Compute actions + Map.entry(ComputeActions.CREATE_INSTANCE, "ec2:RunInstances"), + Map.entry(ComputeActions.DELETE_INSTANCE, "ec2:TerminateInstances"), + Map.entry(ComputeActions.START_INSTANCE, "ec2:StartInstances"), + Map.entry(ComputeActions.STOP_INSTANCE, "ec2:StopInstances"), + Map.entry(ComputeActions.DESCRIBE_INSTANCES, "ec2:DescribeInstances"), + Map.entry(ComputeActions.GET_INSTANCE, "ec2:DescribeInstances"), + + // IAM actions + Map.entry(IamActions.ASSUME_ROLE, "sts:AssumeRole"), + Map.entry(IamActions.CREATE_ROLE, "iam:CreateRole"), + Map.entry(IamActions.DELETE_ROLE, "iam:DeleteRole"), + Map.entry(IamActions.GET_ROLE, "iam:GetRole"), + Map.entry(IamActions.ATTACH_ROLE_POLICY, "iam:AttachRolePolicy"), + Map.entry(IamActions.DETACH_ROLE_POLICY, "iam:DetachRolePolicy"), + Map.entry(IamActions.PUT_ROLE_POLICY, "iam:PutRolePolicy"), + Map.entry(IamActions.GET_ROLE_POLICY, "iam:GetRolePolicy")); + + // Condition operator mappings: substrate-neutral → AWS + private static final Map CONDITION_MAPPINGS = + Map.ofEntries( + Map.entry(ConditionOperator.STRING_EQUALS, "StringEquals"), + Map.entry(ConditionOperator.STRING_NOT_EQUALS, "StringNotEquals"), + Map.entry(ConditionOperator.STRING_LIKE, "StringLike"), + Map.entry(ConditionOperator.STRING_NOT_LIKE, "StringNotLike"), + Map.entry(ConditionOperator.NUMERIC_EQUALS, "NumericEquals"), + Map.entry(ConditionOperator.NUMERIC_NOT_EQUALS, "NumericNotEquals"), + Map.entry(ConditionOperator.NUMERIC_LESS_THAN, "NumericLessThan"), + Map.entry(ConditionOperator.NUMERIC_LESS_THAN_EQUALS, "NumericLessThanEquals"), + Map.entry(ConditionOperator.NUMERIC_GREATER_THAN, "NumericGreaterThan"), + Map.entry(ConditionOperator.NUMERIC_GREATER_THAN_EQUALS, "NumericGreaterThanEquals"), + Map.entry(ConditionOperator.DATE_EQUALS, "DateEquals"), + Map.entry(ConditionOperator.DATE_NOT_EQUALS, "DateNotEquals"), + Map.entry(ConditionOperator.DATE_LESS_THAN, "DateLessThan"), + Map.entry(ConditionOperator.DATE_LESS_THAN_EQUALS, "DateLessThanEquals"), + Map.entry(ConditionOperator.DATE_GREATER_THAN, "DateGreaterThan"), + Map.entry(ConditionOperator.DATE_GREATER_THAN_EQUALS, "DateGreaterThanEquals"), + Map.entry(ConditionOperator.BOOL, "Bool"), + Map.entry(ConditionOperator.IP_ADDRESS, "IpAddress"), + Map.entry(ConditionOperator.NOT_IP_ADDRESS, "NotIpAddress")); + public static final String DEFAULT_VERSION = "2012-10-17"; + + /** + * Translates a substrate-neutral PolicyDocument to AWS IAM policy JSON string. + * + * @param policyDocument the substrate-neutral policy document + * @return AWS IAM policy JSON string + * @throws SubstrateSdkException if translation fails + */ + public static String translateToAwsPolicy(PolicyDocument policyDocument) { + Map awsPolicy = new LinkedHashMap<>(); + // Default to AWS IAM policy version if not provided + String version = + StringUtils.isNotBlank(policyDocument.getVersion()) + ? policyDocument.getVersion() + : DEFAULT_VERSION; + awsPolicy.put("Version", version); + + List> awsStatements = new ArrayList<>(); + for (Statement statement : policyDocument.getStatements()) { + awsStatements.add(translateStatement(statement)); + } + awsPolicy.put("Statement", awsStatements); + + try { + return OBJECT_MAPPER.writeValueAsString(awsPolicy); + } catch (JsonProcessingException e) { + throw new SubstrateSdkException("Failed to serialize AWS IAM policy to JSON", e); + } + } + + /** + * Translates a single statement from substrate-neutral to AWS format. + * + * @param statement the substrate-neutral statement + * @return AWS IAM statement as a map + * @throws SubstrateSdkException if translation fails + */ + private static Map translateStatement(Statement statement) { + if (statement.getEffect() == null) { + throw new InvalidArgumentException("Effect is required for AWS IAM policy statement"); + } + + Map awsStatement = new LinkedHashMap<>(); + + // Add Sid if present + String sid = statement.getSid(); + if (StringUtils.isNotBlank(sid)) { + awsStatement.put("Sid", sid); + } + + // Add Effect + awsStatement.put("Effect", statement.getEffect().getValue()); + + // Translate and add Principals if present + List principals = statement.getPrincipals(); + if (principals != null && !principals.isEmpty()) { + awsStatement.put("Principal", translatePrincipals(principals)); + } + + // Translate and add Actions + List awsActions = + statement.getActions().stream() + .map(AwsIamPolicyTranslator::translateAction) + .collect(Collectors.toList()); + + if (awsActions.size() == 1) { + awsStatement.put("Action", awsActions.get(0)); + } else { + awsStatement.put("Action", awsActions); + } + + // Translate and add Resources if present + if (statement.getResources() != null && !statement.getResources().isEmpty()) { + List awsResources = + statement.getResources().stream() + .map(AwsIamPolicyTranslator::translateResource) + .collect(Collectors.toList()); + + if (awsResources.size() == 1) { + awsStatement.put("Resource", awsResources.get(0)); + } else { + awsStatement.put("Resource", awsResources); + } + } + + // Translate and add Conditions if present + if (statement.getConditions() != null && !statement.getConditions().isEmpty()) { + awsStatement.put("Condition", translateConditions(statement.getConditions())); + } + + return awsStatement; + } + + /** + * Translates substrate-neutral action to AWS action. Supports wildcard actions like storage:*, + * compute:*, iam:*. + * + * @param action the substrate-neutral action + * @return AWS action + * @throws SubstrateSdkException if action is unknown + */ + private static String translateAction(Action action) { + // Handle wildcard actions (e.g., storage:*, compute:*, iam:*) + if (action.isWildcard()) { + String service = action.getService(); + switch (service) { + case "storage": + return "s3:*"; + case "compute": + return "ec2:*"; + case "iam": + return "iam:*"; + default: + throw new InvalidArgumentException( + "Unknown substrate-neutral service for wildcard action: " + + action.toActionString() + + ". " + + "Supported wildcard services: storage:*, compute:*, iam:*"); + } + } + + // Handle specific actions + String awsAction = ACTION_MAPPINGS.get(action); + if (awsAction == null) { + throw new InvalidArgumentException( + "Unknown substrate-neutral action: " + + action.toActionString() + + ". " + + "Supported actions: " + + ACTION_MAPPINGS.keySet().stream() + .map(Action::toActionString) + .collect(Collectors.joining(", ")) + + ", or wildcard actions: storage:*, compute:*, iam:*"); + } + return awsAction; + } + + /** + * Translates substrate-neutral resource URI to AWS ARN. + * + * @param resource the substrate-neutral resource URI + * @return AWS ARN + * @throws SubstrateSdkException if resource format is invalid + */ + private static String translateResource(String resource) { + // Handle wildcard + if ("*".equals(resource)) { + return "*"; + } + + // Handle storage:// URIs + if (resource.startsWith("storage://")) { + String path = resource.substring("storage://".length()); + return "arn:aws:s3:::" + path; + } + + // If already an ARN, return as-is + if (resource.startsWith("arn:")) { + return resource; + } + + throw new InvalidArgumentException( + "Unknown resource format: " + + resource + + ". " + + "Supported formats: storage://bucket/key, arn:aws:..., or *"); + } + + /** + * Translates substrate-neutral principals to AWS principal format. + * + * @param principals list of substrate-neutral principals + * @return AWS principal object + */ + private static Map translatePrincipals(List principals) { + Map principalMap = new LinkedHashMap<>(); + List awsPrincipals = new ArrayList<>(); + List servicePrincipals = new ArrayList<>(); + + for (String principal : principals) { + if (principal.endsWith(SERVICE_PRINCIPAL_SUFFIX)) { + servicePrincipals.add(principal); + } else { + awsPrincipals.add(principal); + } + } + + if (!awsPrincipals.isEmpty()) { + principalMap.put("AWS", awsPrincipals.size() == 1 ? awsPrincipals.get(0) : awsPrincipals); + } + if (!servicePrincipals.isEmpty()) { + principalMap.put( + "Service", servicePrincipals.size() == 1 ? servicePrincipals.get(0) : servicePrincipals); + } + + return principalMap; + } + + /** + * Translates substrate-neutral conditions to AWS condition format. + * + * @param conditions substrate-neutral conditions + * @return AWS conditions + * @throws SubstrateSdkException if condition operator is unsupported + */ + private static Map> translateConditions( + Map> conditions) { + Map> awsConditions = new LinkedHashMap<>(); + + for (Map.Entry> entry : conditions.entrySet()) { + ConditionOperator operator = entry.getKey(); + String awsOperator = CONDITION_MAPPINGS.get(operator); + + if (awsOperator == null) { + throw new InvalidArgumentException( + "Unsupported condition operator: " + + operator.getValue() + + ". " + + "Supported operators: " + + CONDITION_MAPPINGS.keySet().stream() + .map(ConditionOperator::getValue) + .collect(Collectors.joining(", "))); + } + + awsConditions.put(awsOperator, entry.getValue()); + } + + return awsConditions; + } +} diff --git a/iam/iam-aws/src/test/java/com/salesforce/multicloudj/iam/aws/AwsIamIT.java b/iam/iam-aws/src/test/java/com/salesforce/multicloudj/iam/aws/AwsIamIT.java index cf115f78d..5efdeb9d8 100644 --- a/iam/iam-aws/src/test/java/com/salesforce/multicloudj/iam/aws/AwsIamIT.java +++ b/iam/iam-aws/src/test/java/com/salesforce/multicloudj/iam/aws/AwsIamIT.java @@ -107,7 +107,7 @@ public String getTestPolicyEffect() { @Override public List getTestPolicyActions() { - return List.of("s3:GetObject", "s3:PutObject"); + return List.of("storage:GetObject", "storage:PutObject"); } @Override diff --git a/iam/iam-aws/src/test/java/com/salesforce/multicloudj/iam/aws/AwsIamPolicyTranslatorTest.java b/iam/iam-aws/src/test/java/com/salesforce/multicloudj/iam/aws/AwsIamPolicyTranslatorTest.java new file mode 100644 index 000000000..252c63a71 --- /dev/null +++ b/iam/iam-aws/src/test/java/com/salesforce/multicloudj/iam/aws/AwsIamPolicyTranslatorTest.java @@ -0,0 +1,647 @@ +package com.salesforce.multicloudj.iam.aws; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.salesforce.multicloudj.common.exceptions.InvalidArgumentException; +import com.salesforce.multicloudj.common.exceptions.SubstrateSdkException; +import com.salesforce.multicloudj.iam.model.Action; +import com.salesforce.multicloudj.iam.model.ComputeActions; +import com.salesforce.multicloudj.iam.model.ConditionOperator; +import com.salesforce.multicloudj.iam.model.Effect; +import com.salesforce.multicloudj.iam.model.IamActions; +import com.salesforce.multicloudj.iam.model.PolicyDocument; +import com.salesforce.multicloudj.iam.model.Statement; +import com.salesforce.multicloudj.iam.model.StorageActions; +import org.junit.jupiter.api.Test; + +public class AwsIamPolicyTranslatorTest { + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + @Test + void testTranslateStorageActions() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement( + Statement.builder() + .sid("StorageAccess") + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .action(StorageActions.PUT_OBJECT) + .resource("storage://my-bucket/*") + .build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + assertEquals("2012-10-17", policyJson.get("Version").asText()); + JsonNode statement = policyJson.get("Statement").get(0); + assertEquals("StorageAccess", statement.get("Sid").asText()); + assertEquals("Allow", statement.get("Effect").asText()); + + JsonNode actions = statement.get("Action"); + assertTrue(actions.isArray()); + assertEquals(2, actions.size()); + assertEquals("s3:GetObject", actions.get(0).asText()); + assertEquals("s3:PutObject", actions.get(1).asText()); + + assertEquals("arn:aws:s3:::my-bucket/*", statement.get("Resource").asText()); + } + + @Test + void testTranslateComputeActions() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement( + Statement.builder() + .effect(Effect.ALLOW) + .action(ComputeActions.CREATE_INSTANCE) + .action(ComputeActions.DELETE_INSTANCE) + .build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + JsonNode actions = policyJson.get("Statement").get(0).get("Action"); + assertTrue(actions.isArray()); + assertEquals("ec2:RunInstances", actions.get(0).asText()); + assertEquals("ec2:TerminateInstances", actions.get(1).asText()); + } + + @Test + void testTranslateIamActions() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement( + Statement.builder() + .effect(Effect.ALLOW) + .action(IamActions.ASSUME_ROLE) + .action(IamActions.CREATE_ROLE) + .build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + JsonNode actions = policyJson.get("Statement").get(0).get("Action"); + assertTrue(actions.isArray()); + assertEquals("sts:AssumeRole", actions.get(0).asText()); + assertEquals("iam:CreateRole", actions.get(1).asText()); + } + + @Test + void testTranslateSingleAction() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement( + Statement.builder().effect(Effect.ALLOW).action(StorageActions.GET_OBJECT).build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + JsonNode action = policyJson.get("Statement").get(0).get("Action"); + assertFalse(action.isArray()); + assertEquals("s3:GetObject", action.asText()); + } + + @Test + void testTranslateResourceWildcard() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement( + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .resource("*") + .build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + assertEquals("*", policyJson.get("Statement").get(0).get("Resource").asText()); + } + + @Test + void testTranslateResourceArn() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement( + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .resource("arn:aws:s3:::my-bucket/*") + .build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + assertEquals( + "arn:aws:s3:::my-bucket/*", policyJson.get("Statement").get(0).get("Resource").asText()); + } + + @Test + void testTranslateMultipleResources() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement( + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .resource("storage://bucket1/*") + .resource("storage://bucket2/*") + .build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + JsonNode resources = policyJson.get("Statement").get(0).get("Resource"); + assertTrue(resources.isArray()); + assertEquals(2, resources.size()); + assertEquals("arn:aws:s3:::bucket1/*", resources.get(0).asText()); + assertEquals("arn:aws:s3:::bucket2/*", resources.get(1).asText()); + } + + @Test + void testTranslatePrincipalsAwsOnly() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement( + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .principal("arn:aws:iam::123456789012:user/TestUser") + .principal("arn:aws:iam::123456789012:role/TestRole") + .build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + JsonNode principal = policyJson.get("Statement").get(0).get("Principal"); + JsonNode awsPrincipals = principal.get("AWS"); + assertTrue(awsPrincipals.isArray()); + assertEquals(2, awsPrincipals.size()); + assertEquals("arn:aws:iam::123456789012:user/TestUser", awsPrincipals.get(0).asText()); + assertEquals("arn:aws:iam::123456789012:role/TestRole", awsPrincipals.get(1).asText()); + } + + @Test + void testTranslatePrincipalsServiceOnly() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement( + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .principal("ec2.amazonaws.com") + .principal("lambda.amazonaws.com") + .build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + JsonNode principal = policyJson.get("Statement").get(0).get("Principal"); + JsonNode servicePrincipals = principal.get("Service"); + assertTrue(servicePrincipals.isArray()); + assertEquals(2, servicePrincipals.size()); + assertEquals("ec2.amazonaws.com", servicePrincipals.get(0).asText()); + assertEquals("lambda.amazonaws.com", servicePrincipals.get(1).asText()); + } + + @Test + void testTranslatePrincipalsMixed() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement( + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .principal("arn:aws:iam::123456789012:user/TestUser") + .principal("ec2.amazonaws.com") + .build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + JsonNode principal = policyJson.get("Statement").get(0).get("Principal"); + assertEquals("arn:aws:iam::123456789012:user/TestUser", principal.get("AWS").asText()); + assertEquals("ec2.amazonaws.com", principal.get("Service").asText()); + } + + @Test + void testTranslateConditions() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement( + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .condition(ConditionOperator.STRING_EQUALS, "aws:RequestedRegion", "us-west-2") + .condition(ConditionOperator.NUMERIC_LESS_THAN, "s3:max-keys", 100) + .build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + JsonNode condition = policyJson.get("Statement").get(0).get("Condition"); + assertNotNull(condition); + assertEquals("us-west-2", condition.get("StringEquals").get("aws:RequestedRegion").asText()); + assertEquals(100, condition.get("NumericLessThan").get("s3:max-keys").asInt()); + } + + @Test + void testTranslateMultipleStatements() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement( + Statement.builder() + .sid("StorageRead") + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .build()) + .statement( + Statement.builder() + .sid("StorageWrite") + .effect(Effect.ALLOW) + .action(StorageActions.PUT_OBJECT) + .build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + JsonNode statements = policyJson.get("Statement"); + assertEquals(2, statements.size()); + assertEquals("StorageRead", statements.get(0).get("Sid").asText()); + assertEquals("s3:GetObject", statements.get(0).get("Action").asText()); + assertEquals("StorageWrite", statements.get(1).get("Sid").asText()); + assertEquals("s3:PutObject", statements.get(1).get("Action").asText()); + } + + @Test + void testTranslateUnknownActionThrowsException() { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement( + Statement.builder() + .effect(Effect.ALLOW) + .action(Action.of("unknown:Action")) + .build()) + .build(); + + InvalidArgumentException exception = + assertThrows( + InvalidArgumentException.class, + () -> { + AwsIamPolicyTranslator.translateToAwsPolicy(policy); + }); + + assertTrue(exception.getMessage().contains("Unknown substrate-neutral action: unknown:Action")); + } + + @Test + void testTranslateInvalidResourceFormatThrowsException() { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement( + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .resource("invalid://resource") + .build()) + .build(); + + InvalidArgumentException exception = + assertThrows( + InvalidArgumentException.class, + () -> { + AwsIamPolicyTranslator.translateToAwsPolicy(policy); + }); + + assertTrue(exception.getMessage().contains("Unknown resource format: invalid://resource")); + } + + @Test + void testTranslateStatementWithoutSid() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement( + Statement.builder().effect(Effect.ALLOW).action(StorageActions.GET_OBJECT).build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + JsonNode statement = policyJson.get("Statement").get(0); + assertNull(statement.get("Sid")); + } + + @Test + void testTranslateStatementWithoutPrincipals() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement( + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .resource("storage://my-bucket/*") + .build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + JsonNode statement = policyJson.get("Statement").get(0); + assertNull(statement.get("Principal")); + } + + @Test + void testTranslateStatementWithoutResources() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement( + Statement.builder().effect(Effect.ALLOW).action(StorageActions.GET_OBJECT).build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + JsonNode statement = policyJson.get("Statement").get(0); + assertNull(statement.get("Resource")); + } + + @Test + void testTranslateStatementWithoutConditions() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement( + Statement.builder().effect(Effect.ALLOW).action(StorageActions.GET_OBJECT).build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + JsonNode statement = policyJson.get("Statement").get(0); + assertNull(statement.get("Condition")); + } + + @Test + void testTranslateAllConditionOperators() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement( + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .condition(ConditionOperator.STRING_EQUALS, "key1", "value1") + .condition(ConditionOperator.STRING_NOT_EQUALS, "key2", "value2") + .condition(ConditionOperator.STRING_LIKE, "key3", "value3") + .condition(ConditionOperator.NUMERIC_LESS_THAN, "key4", 100) + .condition(ConditionOperator.DATE_GREATER_THAN, "key5", "2024-01-01") + .condition(ConditionOperator.BOOL, "key6", true) + .condition(ConditionOperator.IP_ADDRESS, "key7", "192.168.1.0/24") + .build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + JsonNode condition = policyJson.get("Statement").get(0).get("Condition"); + assertNotNull(condition.get("StringEquals")); + assertNotNull(condition.get("StringNotEquals")); + assertNotNull(condition.get("StringLike")); + assertNotNull(condition.get("NumericLessThan")); + assertNotNull(condition.get("DateGreaterThan")); + assertNotNull(condition.get("Bool")); + assertNotNull(condition.get("IpAddress")); + } + + @Test + void testTranslateWildcardStorageAction() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement( + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.ALL) + .resource("storage://my-bucket/*") + .build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + assertEquals("s3:*", policyJson.get("Statement").get(0).get("Action").asText()); + } + + @Test + void testTranslateWildcardComputeAction() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement(Statement.builder().effect(Effect.ALLOW).action(ComputeActions.ALL).build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + assertEquals("ec2:*", policyJson.get("Statement").get(0).get("Action").asText()); + } + + @Test + void testTranslateWildcardIamAction() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement(Statement.builder().effect(Effect.ALLOW).action(IamActions.ALL).build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + assertEquals("iam:*", policyJson.get("Statement").get(0).get("Action").asText()); + } + + @Test + void testTranslateMixedWildcardAndSpecificActions() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement( + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.ALL) + .action(ComputeActions.CREATE_INSTANCE) + .action(IamActions.GET_ROLE) + .build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + JsonNode actions = policyJson.get("Statement").get(0).get("Action"); + assertTrue(actions.isArray()); + assertEquals(3, actions.size()); + assertEquals("s3:*", actions.get(0).asText()); + assertEquals("ec2:RunInstances", actions.get(1).asText()); + assertEquals("iam:GetRole", actions.get(2).asText()); + } + + @Test + void testTranslateUnknownWildcardServiceThrowsException() { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement( + Statement.builder() + .effect(Effect.ALLOW) + .action(Action.of("unknown:*")) + .build()) + .build(); + + InvalidArgumentException exception = + assertThrows( + InvalidArgumentException.class, + () -> { + AwsIamPolicyTranslator.translateToAwsPolicy(policy); + }); + + assertTrue( + exception + .getMessage() + .contains("Unknown substrate-neutral service for wildcard action: unknown:*")); + assertTrue( + exception + .getMessage() + .contains("Supported wildcard services: storage:*, compute:*, iam:*")); + } + + @Test + void testTranslateMultipleWildcardActions() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("2012-10-17") + .statement( + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.ALL) + .action(ComputeActions.ALL) + .action(IamActions.ALL) + .build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + JsonNode actions = policyJson.get("Statement").get(0).get("Action"); + assertTrue(actions.isArray()); + assertEquals(3, actions.size()); + assertEquals("s3:*", actions.get(0).asText()); + assertEquals("ec2:*", actions.get(1).asText()); + assertEquals("iam:*", actions.get(2).asText()); + } + + @Test + void testTranslateWithNullVersionDefaultsToAwsVersion() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .statement( + Statement.builder().effect(Effect.ALLOW).action(StorageActions.GET_OBJECT).build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + assertEquals("2012-10-17", policyJson.get("Version").asText()); + } + + @Test + void testTranslateWithBlankVersionDefaultsToAwsVersion() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("") + .statement( + Statement.builder().effect(Effect.ALLOW).action(StorageActions.GET_OBJECT).build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + assertEquals("2012-10-17", policyJson.get("Version").asText()); + } + + @Test + void testTranslateWithCustomVersionPreservesIt() throws Exception { + PolicyDocument policy = + PolicyDocument.builder() + .version("2008-10-17") + .statement( + Statement.builder().effect(Effect.ALLOW).action(StorageActions.GET_OBJECT).build()) + .build(); + + String awsPolicy = AwsIamPolicyTranslator.translateToAwsPolicy(policy); + JsonNode policyJson = OBJECT_MAPPER.readTree(awsPolicy); + + assertEquals("2008-10-17", policyJson.get("Version").asText()); + } + + @Test + void testTranslateNullEffectThrowsException() { + Statement mockStatement = mock(Statement.class); + when(mockStatement.getEffect()).thenReturn(null); + when(mockStatement.getActions()) + .thenReturn(java.util.Collections.singletonList(StorageActions.GET_OBJECT)); + + PolicyDocument policy = + PolicyDocument.builder() + .statement(mockStatement) + .build(); + + InvalidArgumentException exception = + assertThrows( + InvalidArgumentException.class, + () -> { + AwsIamPolicyTranslator.translateToAwsPolicy(policy); + }); + + assertEquals("Effect is required for AWS IAM policy statement", exception.getMessage()); + } +} diff --git a/iam/iam-aws/src/test/java/com/salesforce/multicloudj/iam/aws/AwsIamTest.java b/iam/iam-aws/src/test/java/com/salesforce/multicloudj/iam/aws/AwsIamTest.java index 83d23dc8d..43318ef40 100644 --- a/iam/iam-aws/src/test/java/com/salesforce/multicloudj/iam/aws/AwsIamTest.java +++ b/iam/iam-aws/src/test/java/com/salesforce/multicloudj/iam/aws/AwsIamTest.java @@ -14,9 +14,15 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.salesforce.multicloudj.iam.model.AttachInlinePolicyRequest; +import com.salesforce.multicloudj.iam.model.ConditionOperator; import com.salesforce.multicloudj.iam.model.CreateOptions; +import com.salesforce.multicloudj.iam.model.Effect; import com.salesforce.multicloudj.iam.model.GetAttachedPoliciesRequest; import com.salesforce.multicloudj.iam.model.GetInlinePolicyDetailsRequest; +import com.salesforce.multicloudj.iam.model.PolicyDocument; +import com.salesforce.multicloudj.iam.model.Statement; +import com.salesforce.multicloudj.iam.model.StorageActions; import com.salesforce.multicloudj.iam.model.TrustConfiguration; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; @@ -44,6 +50,8 @@ import software.amazon.awssdk.services.iam.model.GetRoleRequest; import software.amazon.awssdk.services.iam.model.GetRoleResponse; import software.amazon.awssdk.services.iam.model.NoSuchEntityException; +import software.amazon.awssdk.services.iam.model.PutRolePolicyRequest; +import software.amazon.awssdk.services.iam.model.PutRolePolicyResponse; import software.amazon.awssdk.services.iam.model.Role; import software.amazon.awssdk.services.iam.model.UpdateAssumeRolePolicyRequest; import software.amazon.awssdk.services.iam.model.UpdateAssumeRolePolicyResponse; @@ -754,4 +762,120 @@ void testRemovePolicyThrowsException() { NoSuchEntityException.class, () -> awsIam.removePolicy(TEST_ROLE_NAME, TEST_POLICY_NAME, TEST_TENANT_ID, TEST_REGION)); } + + @Test + void testAttachInlinePolicyTranslatesActionsResourcesAndConditions() throws Exception { + // Setup + when(mockIamClient.putRolePolicy(any(PutRolePolicyRequest.class))) + .thenReturn(PutRolePolicyResponse.builder().build()); + + // Create a policy with substrate-neutral actions, resources, and conditions + PolicyDocument policyDocument = + PolicyDocument.builder() + .name("TestPolicy") + .version("2012-10-17") + .statement( + Statement.builder() + .sid("TestStatement") + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .action(StorageActions.PUT_OBJECT) + .resource("storage://my-bucket/*") + .condition(ConditionOperator.STRING_EQUALS, "aws:RequestedRegion", "us-west-2") + .principal("arn:aws:iam::123456789012:user/TestUser") + .build()) + .build(); + + // Execute + awsIam.attachInlinePolicy( + AttachInlinePolicyRequest.builder() + .policyDocument(policyDocument) + .identityName(TEST_ROLE_NAME) + .tenantId(TEST_TENANT_ID) + .region(TEST_REGION) + .build()); + + // Verify the policy was attached with proper translations + ArgumentCaptor captor = + ArgumentCaptor.forClass(PutRolePolicyRequest.class); + verify(mockIamClient, times(1)).putRolePolicy(captor.capture()); + + PutRolePolicyRequest request = captor.getValue(); + assertEquals(TEST_ROLE_NAME, request.roleName()); + assertEquals("TestPolicy", request.policyName()); + + // Parse the policy document JSON to verify translations + ObjectMapper mapper = new ObjectMapper(); + JsonNode policyJson = mapper.readTree(request.policyDocument()); + + // Verify version + assertEquals("2012-10-17", policyJson.get("Version").asText()); + + // Verify statement structure + JsonNode statements = policyJson.get("Statement"); + assertEquals(1, statements.size()); + + JsonNode statement = statements.get(0); + + // Verify SID + assertEquals("TestStatement", statement.get("Sid").asText()); + + // Verify Effect + assertEquals("Allow", statement.get("Effect").asText()); + + // Verify actions are translated: storage:GetObject → s3:GetObject + JsonNode actions = statement.get("Action"); + assertTrue(actions.isArray()); + assertEquals(2, actions.size()); + assertEquals("s3:GetObject", actions.get(0).asText()); + assertEquals("s3:PutObject", actions.get(1).asText()); + + // Verify resource is translated: storage://my-bucket/* → arn:aws:s3:::my-bucket/* + String resource = statement.get("Resource").asText(); + assertEquals("arn:aws:s3:::my-bucket/*", resource); + + // Verify condition operator is translated: stringEquals → StringEquals + JsonNode condition = statement.get("Condition"); + assertTrue(condition.has("StringEquals")); + assertEquals("us-west-2", condition.get("StringEquals").get("aws:RequestedRegion").asText()); + + // Verify principal is wrapped correctly + JsonNode principal = statement.get("Principal"); + assertTrue(principal.has("AWS")); + assertEquals("arn:aws:iam::123456789012:user/TestUser", principal.get("AWS").asText()); + } + + @Test + void testAttachInlinePolicyWithNullVersionDefaultsToAwsVersion() throws Exception { + // Setup + when(mockIamClient.putRolePolicy(any(PutRolePolicyRequest.class))) + .thenReturn(PutRolePolicyResponse.builder().build()); + + // Create a policy without version + PolicyDocument policyDocument = + PolicyDocument.builder() + .name("TestPolicy") + .statement( + Statement.builder().effect(Effect.ALLOW).action(StorageActions.GET_OBJECT).build()) + .build(); + + // Execute + awsIam.attachInlinePolicy( + AttachInlinePolicyRequest.builder() + .policyDocument(policyDocument) + .identityName(TEST_ROLE_NAME) + .tenantId(TEST_TENANT_ID) + .region(TEST_REGION) + .build()); + + // Verify the version defaults to "2012-10-17" + ArgumentCaptor captor = + ArgumentCaptor.forClass(PutRolePolicyRequest.class); + verify(mockIamClient, times(1)).putRolePolicy(captor.capture()); + + ObjectMapper mapper = new ObjectMapper(); + JsonNode policyJson = mapper.readTree(captor.getValue().policyDocument()); + + assertEquals("2012-10-17", policyJson.get("Version").asText()); + } } diff --git a/iam/iam-aws/src/test/resources/mappings/post-3uk1re9u8b.json b/iam/iam-aws/src/test/resources/mappings/awsiamit_testattachinlinepolicy-post-0.json similarity index 59% rename from iam/iam-aws/src/test/resources/mappings/post-3uk1re9u8b.json rename to iam/iam-aws/src/test/resources/mappings/awsiamit_testattachinlinepolicy-post-0.json index 6c7aa29d1..e7f479b83 100644 --- a/iam/iam-aws/src/test/resources/mappings/post-3uk1re9u8b.json +++ b/iam/iam-aws/src/test/resources/mappings/awsiamit_testattachinlinepolicy-post-0.json @@ -1,24 +1,24 @@ { - "id" : "444eb433-71e4-442e-8eca-93cbb80210ad", - "name" : "", + "id" : "a016781b-0605-476d-b505-c9d9196b351c", + "name" : "AwsIamIT_testAttachInlinePolicy-POST-0", "request" : { "url" : "/", "method" : "POST", "bodyPatterns" : [ { - "equalTo" : "Action=PutRolePolicy&Version=2010-05-08&RoleName=testSa&PolicyName=TestPolicy&PolicyDocument=%7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%5B%22s3%3AGetObject%22%2C%22s3%3APutObject%22%5D%2C%22Resource%22%3A%5B%22arn%3Aaws%3As3%3A%3A%3Amulticloudj-iam-it-test-bucket%2F*%22%5D%7D%5D%7D", + "equalTo" : "Action=PutRolePolicy&Version=2010-05-08&RoleName=testSa&PolicyName=TestPolicy&PolicyDocument=%7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%5B%22s3%3AGetObject%22%2C%22s3%3APutObject%22%5D%2C%22Resource%22%3A%22arn%3Aaws%3As3%3A%3A%3Amulticloudj-iam-it-test-bucket%2F*%22%7D%5D%7D", "caseInsensitive" : false } ] }, "response" : { "status" : 200, - "body" : "\n \n 58100288-efa5-4fc6-a2df-78c9216d7e23\n \n\n", + "body" : "\n \n c58dc3e6-0686-4b3e-ae5e-85a9c582bc19\n \n\n", "headers" : { - "x-amzn-RequestId" : "58100288-efa5-4fc6-a2df-78c9216d7e23", - "Date" : "Thu, 26 Feb 2026 22:33:58 GMT", + "x-amzn-RequestId" : "c58dc3e6-0686-4b3e-ae5e-85a9c582bc19", + "Date" : "Tue, 10 Mar 2026 06:16:32 GMT", "Content-Type" : "text/xml" } }, - "uuid" : "444eb433-71e4-442e-8eca-93cbb80210ad", + "uuid" : "a016781b-0605-476d-b505-c9d9196b351c", "persistent" : true, - "insertionIndex" : 31 + "insertionIndex" : 54 } \ No newline at end of file diff --git a/iam/iam-aws/src/test/resources/mappings/post-shtghnxgnn.json b/iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithnulldescription-post-0.json similarity index 50% rename from iam/iam-aws/src/test/resources/mappings/post-shtghnxgnn.json rename to iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithnulldescription-post-0.json index b11540bb1..1114cb95b 100644 --- a/iam/iam-aws/src/test/resources/mappings/post-shtghnxgnn.json +++ b/iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithnulldescription-post-0.json @@ -1,6 +1,6 @@ { - "id" : "96125ec2-e82b-43c4-9552-ea1b12cc3fab", - "name" : "", + "id" : "fd0a0059-de9d-412a-82c4-ad9f4959ab84", + "name" : "AwsIamIT_testCreateIdentityWithNullDescription-POST-0", "request" : { "url" : "/", "method" : "POST", @@ -11,14 +11,14 @@ }, "response" : { "status" : 200, - "body" : "\n \n e5035dc1-501a-455b-80da-3e22edd8a003\n \n\n", + "body" : "\n \n 1b915702-49c4-4e0c-a599-319bdf5b6016\n \n\n", "headers" : { - "x-amzn-RequestId" : "e5035dc1-501a-455b-80da-3e22edd8a003", - "Date" : "Thu, 26 Feb 2026 22:33:50 GMT", + "x-amzn-RequestId" : "1b915702-49c4-4e0c-a599-319bdf5b6016", + "Date" : "Tue, 10 Mar 2026 06:16:27 GMT", "Content-Type" : "text/xml" } }, - "uuid" : "96125ec2-e82b-43c4-9552-ea1b12cc3fab", + "uuid" : "fd0a0059-de9d-412a-82c4-ad9f4959ab84", "persistent" : true, - "insertionIndex" : 22 + "insertionIndex" : 45 } \ No newline at end of file diff --git a/iam/iam-aws/src/test/resources/mappings/post-d3ipjuqiix.json b/iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithnulldescription-post-1.json similarity index 64% rename from iam/iam-aws/src/test/resources/mappings/post-d3ipjuqiix.json rename to iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithnulldescription-post-1.json index 4eef47b16..56b0baabc 100644 --- a/iam/iam-aws/src/test/resources/mappings/post-d3ipjuqiix.json +++ b/iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithnulldescription-post-1.json @@ -1,6 +1,6 @@ { - "id" : "58c2ef1d-53f4-4924-8b2d-a73ac7fbfdb3", - "name" : "", + "id" : "157e70d7-9510-4ea2-8626-62da5740dcf9", + "name" : "AwsIamIT_testCreateIdentityWithNullDescription-POST-1", "request" : { "url" : "/", "method" : "POST", @@ -11,14 +11,14 @@ }, "response" : { "status" : 200, - "body" : "\n \n \n /\n %7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%22sts%3AAssumeRole%22%2C%22Principal%22%3A%7B%22AWS%22%3A%5B%22arn%3Aaws%3Aiam%3A%3A654654370895%3Aroot%22%5D%7D%7D%5D%7D\n AROAZQ3DQ6RH3WGXPRHHF\n MultiCloudJTestRoleNoDesc\n arn:aws:iam::654654370895:role/MultiCloudJTestRoleNoDesc\n 2026-02-26T22:33:48Z\n \n \n \n 2de1e4c8-d865-4630-a05f-45cadfc046fa\n \n\n", + "body" : "\n \n \n /\n %7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%22sts%3AAssumeRole%22%2C%22Principal%22%3A%7B%22AWS%22%3A%5B%22arn%3Aaws%3Aiam%3A%3A654654370895%3Aroot%22%5D%7D%7D%5D%7D\n AROAZQ3DQ6RHXHA7TUIIL\n MultiCloudJTestRoleNoDesc\n arn:aws:iam::654654370895:role/MultiCloudJTestRoleNoDesc\n 2026-03-10T06:16:26Z\n \n \n \n 87a070e8-6588-4bb9-b92e-4a1f381628d5\n \n\n", "headers" : { - "x-amzn-RequestId" : "2de1e4c8-d865-4630-a05f-45cadfc046fa", - "Date" : "Thu, 26 Feb 2026 22:33:48 GMT", + "x-amzn-RequestId" : "87a070e8-6588-4bb9-b92e-4a1f381628d5", + "Date" : "Tue, 10 Mar 2026 06:16:26 GMT", "Content-Type" : "text/xml" } }, - "uuid" : "58c2ef1d-53f4-4924-8b2d-a73ac7fbfdb3", + "uuid" : "157e70d7-9510-4ea2-8626-62da5740dcf9", "persistent" : true, - "insertionIndex" : 23 + "insertionIndex" : 46 } \ No newline at end of file diff --git a/iam/iam-aws/src/test/resources/mappings/post-pgbebhvrk4.json b/iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithoptions-post-0.json similarity index 51% rename from iam/iam-aws/src/test/resources/mappings/post-pgbebhvrk4.json rename to iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithoptions-post-0.json index 193bb5af6..9f5f718f5 100644 --- a/iam/iam-aws/src/test/resources/mappings/post-pgbebhvrk4.json +++ b/iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithoptions-post-0.json @@ -1,6 +1,6 @@ { - "id" : "0afc7b00-6ab2-4a17-a7da-43321184fdbb", - "name" : "", + "id" : "7eafdabd-6f00-4233-a7cc-320919bb1244", + "name" : "AwsIamIT_testCreateIdentityWithOptions-POST-0", "request" : { "url" : "/", "method" : "POST", @@ -11,14 +11,14 @@ }, "response" : { "status" : 200, - "body" : "\n \n 75b1a74f-55b0-4f3c-b68a-2c8d1f6b1daa\n \n\n", + "body" : "\n \n fec41540-1b8c-4694-9483-c217930d206b\n \n\n", "headers" : { - "x-amzn-RequestId" : "75b1a74f-55b0-4f3c-b68a-2c8d1f6b1daa", - "Date" : "Thu, 26 Feb 2026 22:33:41 GMT", + "x-amzn-RequestId" : "fec41540-1b8c-4694-9483-c217930d206b", + "Date" : "Tue, 10 Mar 2026 06:16:22 GMT", "Content-Type" : "text/xml" } }, - "uuid" : "0afc7b00-6ab2-4a17-a7da-43321184fdbb", + "uuid" : "7eafdabd-6f00-4233-a7cc-320919bb1244", "persistent" : true, - "insertionIndex" : 13 + "insertionIndex" : 36 } \ No newline at end of file diff --git a/iam/iam-aws/src/test/resources/mappings/post-4pcfetqzcl.json b/iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithoptions-post-1.json similarity index 65% rename from iam/iam-aws/src/test/resources/mappings/post-4pcfetqzcl.json rename to iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithoptions-post-1.json index 4f19af7a8..ac10e1a6b 100644 --- a/iam/iam-aws/src/test/resources/mappings/post-4pcfetqzcl.json +++ b/iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithoptions-post-1.json @@ -1,6 +1,6 @@ { - "id" : "0a380abe-17a2-4d3c-a911-4ff5cd11c0ac", - "name" : "", + "id" : "20e524f8-e485-4565-8e57-1faf02b6b9be", + "name" : "AwsIamIT_testCreateIdentityWithOptions-POST-1", "request" : { "url" : "/", "method" : "POST", @@ -11,14 +11,14 @@ }, "response" : { "status" : 200, - "body" : "\n \n \n /\n %7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%22sts%3AAssumeRole%22%2C%22Principal%22%3A%7B%22AWS%22%3A%5B%22arn%3Aaws%3Aiam%3A%3A654654370895%3Aroot%22%5D%7D%7D%5D%7D\n AROAZQ3DQ6RH33DRLNZ2I\n MultiCloudJTestRoleOptions\n arn:aws:iam::654654370895:role/MultiCloudJTestRoleOptions\n 2026-02-26T22:33:39Z\n \n \n \n d91d3643-48c1-4169-867c-2a788b3548a8\n \n\n", + "body" : "\n \n \n /\n %7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%22sts%3AAssumeRole%22%2C%22Principal%22%3A%7B%22AWS%22%3A%5B%22arn%3Aaws%3Aiam%3A%3A654654370895%3Aroot%22%5D%7D%7D%5D%7D\n AROAZQ3DQ6RHZAME7UUX3\n MultiCloudJTestRoleOptions\n arn:aws:iam::654654370895:role/MultiCloudJTestRoleOptions\n 2026-03-10T06:16:21Z\n \n \n \n 6c7c1242-e392-4f0f-8649-c8cfe3025dc3\n \n\n", "headers" : { - "x-amzn-RequestId" : "d91d3643-48c1-4169-867c-2a788b3548a8", - "Date" : "Thu, 26 Feb 2026 22:33:39 GMT", + "x-amzn-RequestId" : "6c7c1242-e392-4f0f-8649-c8cfe3025dc3", + "Date" : "Tue, 10 Mar 2026 06:16:21 GMT", "Content-Type" : "text/xml" } }, - "uuid" : "0a380abe-17a2-4d3c-a911-4ff5cd11c0ac", + "uuid" : "20e524f8-e485-4565-8e57-1faf02b6b9be", "persistent" : true, - "insertionIndex" : 14 + "insertionIndex" : 37 } \ No newline at end of file diff --git a/iam/iam-aws/src/test/resources/mappings/post-wy9up0jelp.json b/iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithouttrustconfig-post-0.json similarity index 50% rename from iam/iam-aws/src/test/resources/mappings/post-wy9up0jelp.json rename to iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithouttrustconfig-post-0.json index 7d55b5acf..d6a7c3abe 100644 --- a/iam/iam-aws/src/test/resources/mappings/post-wy9up0jelp.json +++ b/iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithouttrustconfig-post-0.json @@ -1,6 +1,6 @@ { - "id" : "738e45b5-07b1-4f68-8d4b-746c320a0f51", - "name" : "", + "id" : "0e4c65a4-36fa-4caa-bd10-44e5c359cd57", + "name" : "AwsIamIT_testCreateIdentityWithoutTrustConfig-POST-0", "request" : { "url" : "/", "method" : "POST", @@ -11,14 +11,14 @@ }, "response" : { "status" : 200, - "body" : "\n \n 2fef4fff-d4c9-49aa-84f5-1353d929c4de\n \n\n", + "body" : "\n \n 318a2eb6-4950-48c9-bcee-cfd56dce9784\n \n\n", "headers" : { - "x-amzn-RequestId" : "2fef4fff-d4c9-49aa-84f5-1353d929c4de", - "Date" : "Thu, 26 Feb 2026 22:33:32 GMT", + "x-amzn-RequestId" : "318a2eb6-4950-48c9-bcee-cfd56dce9784", + "Date" : "Tue, 10 Mar 2026 06:16:16 GMT", "Content-Type" : "text/xml" } }, - "uuid" : "738e45b5-07b1-4f68-8d4b-746c320a0f51", + "uuid" : "0e4c65a4-36fa-4caa-bd10-44e5c359cd57", "persistent" : true, - "insertionIndex" : 4 + "insertionIndex" : 27 } \ No newline at end of file diff --git a/iam/iam-aws/src/test/resources/mappings/post-lckn0weylz.json b/iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithouttrustconfig-post-1.json similarity index 72% rename from iam/iam-aws/src/test/resources/mappings/post-lckn0weylz.json rename to iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithouttrustconfig-post-1.json index 72f5f7cc1..0638aba90 100644 --- a/iam/iam-aws/src/test/resources/mappings/post-lckn0weylz.json +++ b/iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithouttrustconfig-post-1.json @@ -1,6 +1,6 @@ { - "id" : "f305d37b-d5a9-4730-93a2-2c4d53af07b8", - "name" : "", + "id" : "75d9b3d6-4776-4059-92d3-578b1f42b9bc", + "name" : "AwsIamIT_testCreateIdentityWithoutTrustConfig-POST-1", "request" : { "url" : "/", "method" : "POST", @@ -11,14 +11,14 @@ }, "response" : { "status" : 200, - "body" : "\n \n \n /\n %7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%22sts%3AAssumeRole%22%2C%22Principal%22%3A%7B%22AWS%22%3A%5B%22arn%3Aaws%3Aiam%3A%3A654654370895%3Aroot%22%5D%7D%7D%5D%7D\n AROAZQ3DQ6RHXHFWPF4OM\n MultiCloudJTestRole\n arn:aws:iam::654654370895:role/MultiCloudJTestRole\n 2026-02-26T22:33:30Z\n \n \n \n ddf31c59-9330-475f-9f3a-ed3ef1f5cf88\n \n\n", + "body" : "\n \n \n /\n %7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%22sts%3AAssumeRole%22%2C%22Principal%22%3A%7B%22AWS%22%3A%5B%22arn%3Aaws%3Aiam%3A%3A654654370895%3Aroot%22%5D%7D%7D%5D%7D\n AROAZQ3DQ6RH4KJGAWOSB\n MultiCloudJTestRole\n arn:aws:iam::654654370895:role/MultiCloudJTestRole\n 2026-03-10T06:16:15Z\n \n \n \n e5abe3c5-2e9f-4ebf-a3ee-1bda2b25095c\n \n\n", "headers" : { - "x-amzn-RequestId" : "ddf31c59-9330-475f-9f3a-ed3ef1f5cf88", - "Date" : "Thu, 26 Feb 2026 22:33:30 GMT", + "x-amzn-RequestId" : "e5abe3c5-2e9f-4ebf-a3ee-1bda2b25095c", + "Date" : "Tue, 10 Mar 2026 06:16:15 GMT", "Content-Type" : "text/xml" } }, - "uuid" : "f305d37b-d5a9-4730-93a2-2c4d53af07b8", + "uuid" : "75d9b3d6-4776-4059-92d3-578b1f42b9bc", "persistent" : true, - "insertionIndex" : 5 + "insertionIndex" : 28 } \ No newline at end of file diff --git a/iam/iam-aws/src/test/resources/mappings/post-ueonbvztyh.json b/iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithtrustconfig-post-0.json similarity index 50% rename from iam/iam-aws/src/test/resources/mappings/post-ueonbvztyh.json rename to iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithtrustconfig-post-0.json index 35c0d082a..4a34f1c4d 100644 --- a/iam/iam-aws/src/test/resources/mappings/post-ueonbvztyh.json +++ b/iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithtrustconfig-post-0.json @@ -1,6 +1,6 @@ { - "id" : "b47eb438-69b2-46b8-9490-20a1d0fdbf42", - "name" : "", + "id" : "5cb79b94-4002-4bde-a0db-c06cd42fa2b8", + "name" : "AwsIamIT_testCreateIdentityWithTrustConfig-POST-0", "request" : { "url" : "/", "method" : "POST", @@ -11,14 +11,14 @@ }, "response" : { "status" : 200, - "body" : "\n \n ac001531-b758-43bd-9086-98c73c6a7a67\n \n\n", + "body" : "\n \n 528c82b7-acbc-4b2b-a12f-57f51301497f\n \n\n", "headers" : { - "x-amzn-RequestId" : "ac001531-b758-43bd-9086-98c73c6a7a67", - "Date" : "Thu, 26 Feb 2026 22:33:56 GMT", + "x-amzn-RequestId" : "528c82b7-acbc-4b2b-a12f-57f51301497f", + "Date" : "Tue, 10 Mar 2026 06:16:31 GMT", "Content-Type" : "text/xml" } }, - "uuid" : "b47eb438-69b2-46b8-9490-20a1d0fdbf42", + "uuid" : "5cb79b94-4002-4bde-a0db-c06cd42fa2b8", "persistent" : true, - "insertionIndex" : 28 + "insertionIndex" : 51 } \ No newline at end of file diff --git a/iam/iam-aws/src/test/resources/mappings/post-kqiji5pwfk.json b/iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithtrustconfig-post-1.json similarity index 69% rename from iam/iam-aws/src/test/resources/mappings/post-kqiji5pwfk.json rename to iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithtrustconfig-post-1.json index 7b987a3ee..de88b7eb1 100644 --- a/iam/iam-aws/src/test/resources/mappings/post-kqiji5pwfk.json +++ b/iam/iam-aws/src/test/resources/mappings/awsiamit_testcreateidentitywithtrustconfig-post-1.json @@ -1,6 +1,6 @@ { - "id" : "cd49c8a6-1526-44c2-acac-820fca128fc2", - "name" : "", + "id" : "5a49fb9f-f83d-46c2-bfce-c2a5346a38ec", + "name" : "AwsIamIT_testCreateIdentityWithTrustConfig-POST-1", "request" : { "url" : "/", "method" : "POST", @@ -11,14 +11,14 @@ }, "response" : { "status" : 200, - "body" : "\n \n \n /\n %7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%22sts%3AAssumeRole%22%2C%22Principal%22%3A%7B%22AWS%22%3A%5B%22arn%3Aaws%3Aiam%3A%3A654654370895%3Arole%2Fchameleon-jcloud-test%22%5D%7D%7D%5D%7D\n AROAZQ3DQ6RHUGD6GCA6D\n MultiCloudJTestRoleTrusted\n arn:aws:iam::654654370895:role/MultiCloudJTestRoleTrusted\n 2026-02-26T22:33:55Z\n \n \n \n 24113172-1beb-47a0-a5c8-04c3057f1e62\n \n\n", + "body" : "\n \n \n /\n %7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%22sts%3AAssumeRole%22%2C%22Principal%22%3A%7B%22AWS%22%3A%5B%22arn%3Aaws%3Aiam%3A%3A654654370895%3Arole%2Fchameleon-jcloud-test%22%5D%7D%7D%5D%7D\n AROAZQ3DQ6RHU5EE3ZMFR\n MultiCloudJTestRoleTrusted\n arn:aws:iam::654654370895:role/MultiCloudJTestRoleTrusted\n 2026-03-10T06:16:30Z\n \n \n \n 4e36fdab-7e05-48d8-8230-2f88afa461fd\n \n\n", "headers" : { - "x-amzn-RequestId" : "24113172-1beb-47a0-a5c8-04c3057f1e62", - "Date" : "Thu, 26 Feb 2026 22:33:55 GMT", + "x-amzn-RequestId" : "4e36fdab-7e05-48d8-8230-2f88afa461fd", + "Date" : "Tue, 10 Mar 2026 06:16:30 GMT", "Content-Type" : "text/xml" } }, - "uuid" : "cd49c8a6-1526-44c2-acac-820fca128fc2", + "uuid" : "5a49fb9f-f83d-46c2-bfce-c2a5346a38ec", "persistent" : true, - "insertionIndex" : 29 + "insertionIndex" : 52 } \ No newline at end of file diff --git a/iam/iam-aws/src/test/resources/mappings/post-s35ydojueb.json b/iam/iam-aws/src/test/resources/mappings/awsiamit_testdeleteidentity-post-0.json similarity index 51% rename from iam/iam-aws/src/test/resources/mappings/post-s35ydojueb.json rename to iam/iam-aws/src/test/resources/mappings/awsiamit_testdeleteidentity-post-0.json index 1487ecdb2..80c19e55b 100644 --- a/iam/iam-aws/src/test/resources/mappings/post-s35ydojueb.json +++ b/iam/iam-aws/src/test/resources/mappings/awsiamit_testdeleteidentity-post-0.json @@ -1,6 +1,6 @@ { - "id" : "badfabfa-0c2a-4a7a-a822-f4a84867d917", - "name" : "", + "id" : "a4504967-76ac-4f6b-ba2d-37a170a40677", + "name" : "AwsIamIT_testDeleteIdentity-POST-0", "request" : { "url" : "/", "method" : "POST", @@ -11,14 +11,14 @@ }, "response" : { "status" : 200, - "body" : "\n \n 8d2aee3b-fb77-487e-a73e-1b6042f574c3\n \n\n", + "body" : "\n \n 00523902-188a-4a1c-9438-c89ad9a62544\n \n\n", "headers" : { - "x-amzn-RequestId" : "8d2aee3b-fb77-487e-a73e-1b6042f574c3", - "Date" : "Thu, 26 Feb 2026 22:33:53 GMT", + "x-amzn-RequestId" : "00523902-188a-4a1c-9438-c89ad9a62544", + "Date" : "Tue, 10 Mar 2026 06:16:29 GMT", "Content-Type" : "text/xml" } }, - "uuid" : "badfabfa-0c2a-4a7a-a822-f4a84867d917", + "uuid" : "a4504967-76ac-4f6b-ba2d-37a170a40677", "persistent" : true, - "insertionIndex" : 25 + "insertionIndex" : 48 } \ No newline at end of file diff --git a/iam/iam-aws/src/test/resources/mappings/post-xt4vygkxrw.json b/iam/iam-aws/src/test/resources/mappings/awsiamit_testdeleteidentity-post-1.json similarity index 65% rename from iam/iam-aws/src/test/resources/mappings/post-xt4vygkxrw.json rename to iam/iam-aws/src/test/resources/mappings/awsiamit_testdeleteidentity-post-1.json index 81efcffa5..8dc69fee9 100644 --- a/iam/iam-aws/src/test/resources/mappings/post-xt4vygkxrw.json +++ b/iam/iam-aws/src/test/resources/mappings/awsiamit_testdeleteidentity-post-1.json @@ -1,6 +1,6 @@ { - "id" : "00725e40-2358-42df-86db-ad6642487aa1", - "name" : "", + "id" : "21e4fab3-3b32-434f-96fb-cb9829068361", + "name" : "AwsIamIT_testDeleteIdentity-POST-1", "request" : { "url" : "/", "method" : "POST", @@ -11,14 +11,14 @@ }, "response" : { "status" : 200, - "body" : "\n \n \n /\n %7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%22sts%3AAssumeRole%22%2C%22Principal%22%3A%7B%22AWS%22%3A%5B%22arn%3Aaws%3Aiam%3A%3A654654370895%3Aroot%22%5D%7D%7D%5D%7D\n AROAZQ3DQ6RH5WEVPCQLT\n MultiCloudJTestRoleDelete\n arn:aws:iam::654654370895:role/MultiCloudJTestRoleDelete\n 2026-02-26T22:33:52Z\n \n \n \n 6b66d1e9-a605-499c-a2f5-5b3fd0f9ddd4\n \n\n", + "body" : "\n \n \n /\n %7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%22sts%3AAssumeRole%22%2C%22Principal%22%3A%7B%22AWS%22%3A%5B%22arn%3Aaws%3Aiam%3A%3A654654370895%3Aroot%22%5D%7D%7D%5D%7D\n AROAZQ3DQ6RHUGIOKZLB2\n MultiCloudJTestRoleDelete\n arn:aws:iam::654654370895:role/MultiCloudJTestRoleDelete\n 2026-03-10T06:16:28Z\n \n \n \n c91c5d56-17bd-4270-b0dd-ad4f64234ac0\n \n\n", "headers" : { - "x-amzn-RequestId" : "6b66d1e9-a605-499c-a2f5-5b3fd0f9ddd4", - "Date" : "Thu, 26 Feb 2026 22:33:52 GMT", + "x-amzn-RequestId" : "c91c5d56-17bd-4270-b0dd-ad4f64234ac0", + "Date" : "Tue, 10 Mar 2026 06:16:28 GMT", "Content-Type" : "text/xml" } }, - "uuid" : "00725e40-2358-42df-86db-ad6642487aa1", + "uuid" : "21e4fab3-3b32-434f-96fb-cb9829068361", "persistent" : true, - "insertionIndex" : 26 + "insertionIndex" : 49 } \ No newline at end of file diff --git a/iam/iam-aws/src/test/resources/mappings/post-z9bo4kwyaj.json b/iam/iam-aws/src/test/resources/mappings/awsiamit_testgetattachedpolicies-post-0.json similarity index 66% rename from iam/iam-aws/src/test/resources/mappings/post-z9bo4kwyaj.json rename to iam/iam-aws/src/test/resources/mappings/awsiamit_testgetattachedpolicies-post-0.json index 48362a4c8..cc884b233 100644 --- a/iam/iam-aws/src/test/resources/mappings/post-z9bo4kwyaj.json +++ b/iam/iam-aws/src/test/resources/mappings/awsiamit_testgetattachedpolicies-post-0.json @@ -1,6 +1,6 @@ { - "id" : "388e77f3-213f-41f4-9ed4-775df98cab8d", - "name" : "", + "id" : "acf574d4-618b-420d-b18a-25e33e78c38f", + "name" : "AwsIamIT_testGetAttachedPolicies-POST-0", "request" : { "url" : "/", "method" : "POST", @@ -11,14 +11,14 @@ }, "response" : { "status" : 200, - "body" : "\n \n false\n \n InlinePolicy\n TestPolicy\n \n \n \n 5f794cfa-e956-45ff-b3ee-f7afab9fc536\n \n\n", + "body" : "\n \n false\n \n InlinePolicy\n TestPolicy\n \n \n \n e4b3f364-58d2-47aa-bc4b-fb8026d11013\n \n\n", "headers" : { - "x-amzn-RequestId" : "5f794cfa-e956-45ff-b3ee-f7afab9fc536", - "Date" : "Thu, 26 Feb 2026 22:33:47 GMT", + "x-amzn-RequestId" : "e4b3f364-58d2-47aa-bc4b-fb8026d11013", + "Date" : "Tue, 10 Mar 2026 06:16:25 GMT", "Content-Type" : "text/xml" } }, - "uuid" : "388e77f3-213f-41f4-9ed4-775df98cab8d", + "uuid" : "acf574d4-618b-420d-b18a-25e33e78c38f", "persistent" : true, - "insertionIndex" : 19 + "insertionIndex" : 42 } \ No newline at end of file diff --git a/iam/iam-aws/src/test/resources/mappings/post-q6nbakg20f.json b/iam/iam-aws/src/test/resources/mappings/awsiamit_testgetattachedpolicies-post-1.json similarity index 59% rename from iam/iam-aws/src/test/resources/mappings/post-q6nbakg20f.json rename to iam/iam-aws/src/test/resources/mappings/awsiamit_testgetattachedpolicies-post-1.json index a24bcf336..13bce3ced 100644 --- a/iam/iam-aws/src/test/resources/mappings/post-q6nbakg20f.json +++ b/iam/iam-aws/src/test/resources/mappings/awsiamit_testgetattachedpolicies-post-1.json @@ -1,24 +1,24 @@ { - "id" : "9ef6cb13-936f-429c-bfaf-ac63f51bd3a9", - "name" : "", + "id" : "0ca23f11-c023-470f-bcd9-1d301d404251", + "name" : "AwsIamIT_testGetAttachedPolicies-POST-1", "request" : { "url" : "/", "method" : "POST", "bodyPatterns" : [ { - "equalTo" : "Action=PutRolePolicy&Version=2010-05-08&RoleName=testSa&PolicyName=TestPolicy&PolicyDocument=%7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%5B%22s3%3AGetObject%22%2C%22s3%3APutObject%22%5D%2C%22Resource%22%3A%5B%22arn%3Aaws%3As3%3A%3A%3Amulticloudj-iam-it-test-bucket%2F*%22%5D%7D%5D%7D", + "equalTo" : "Action=PutRolePolicy&Version=2010-05-08&RoleName=testSa&PolicyName=TestPolicy&PolicyDocument=%7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%5B%22s3%3AGetObject%22%2C%22s3%3APutObject%22%5D%2C%22Resource%22%3A%22arn%3Aaws%3As3%3A%3A%3Amulticloudj-iam-it-test-bucket%2F*%22%7D%5D%7D", "caseInsensitive" : false } ] }, "response" : { "status" : 200, - "body" : "\n \n b7607604-b68e-4eb8-a93c-4eaaf496fc89\n \n\n", + "body" : "\n \n 58ad38ce-588a-4040-b4de-b78807c8d66c\n \n\n", "headers" : { - "x-amzn-RequestId" : "b7607604-b68e-4eb8-a93c-4eaaf496fc89", - "Date" : "Thu, 26 Feb 2026 22:33:42 GMT", + "x-amzn-RequestId" : "58ad38ce-588a-4040-b4de-b78807c8d66c", + "Date" : "Tue, 10 Mar 2026 06:16:25 GMT", "Content-Type" : "text/xml" } }, - "uuid" : "9ef6cb13-936f-429c-bfaf-ac63f51bd3a9", + "uuid" : "0ca23f11-c023-470f-bcd9-1d301d404251", "persistent" : true, - "insertionIndex" : 17 + "insertionIndex" : 43 } \ No newline at end of file diff --git a/iam/iam-aws/src/test/resources/mappings/post-jrs8mipqyl.json b/iam/iam-aws/src/test/resources/mappings/awsiamit_testgetidentity-post-0.json similarity index 51% rename from iam/iam-aws/src/test/resources/mappings/post-jrs8mipqyl.json rename to iam/iam-aws/src/test/resources/mappings/awsiamit_testgetidentity-post-0.json index 5f41a82de..161e2e892 100644 --- a/iam/iam-aws/src/test/resources/mappings/post-jrs8mipqyl.json +++ b/iam/iam-aws/src/test/resources/mappings/awsiamit_testgetidentity-post-0.json @@ -1,6 +1,6 @@ { - "id" : "b19f5305-aa30-4b19-9d4b-e6022f83a855", - "name" : "", + "id" : "5f3009ed-a5e7-41b6-b42b-ab475f8b5577", + "name" : "AwsIamIT_testGetIdentity-POST-0", "request" : { "url" : "/", "method" : "POST", @@ -11,14 +11,14 @@ }, "response" : { "status" : 200, - "body" : "\n \n 71f97543-dd5f-406e-bf08-996bb08a4a0b\n \n\n", + "body" : "\n \n dd63ad10-85c4-4e65-8677-3a75ebc412a0\n \n\n", "headers" : { - "x-amzn-RequestId" : "71f97543-dd5f-406e-bf08-996bb08a4a0b", - "Date" : "Thu, 26 Feb 2026 22:34:04 GMT", + "x-amzn-RequestId" : "dd63ad10-85c4-4e65-8677-3a75ebc412a0", + "Date" : "Tue, 10 Mar 2026 06:16:36 GMT", "Content-Type" : "text/xml" } }, - "uuid" : "b19f5305-aa30-4b19-9d4b-e6022f83a855", + "uuid" : "5f3009ed-a5e7-41b6-b42b-ab475f8b5577", "persistent" : true, - "insertionIndex" : 33 + "insertionIndex" : 56 } \ No newline at end of file diff --git a/iam/iam-aws/src/test/resources/mappings/post-nfhw0g2fkf.json b/iam/iam-aws/src/test/resources/mappings/awsiamit_testgetidentity-post-1.json similarity index 65% rename from iam/iam-aws/src/test/resources/mappings/post-nfhw0g2fkf.json rename to iam/iam-aws/src/test/resources/mappings/awsiamit_testgetidentity-post-1.json index 46643f823..d4ec46f37 100644 --- a/iam/iam-aws/src/test/resources/mappings/post-nfhw0g2fkf.json +++ b/iam/iam-aws/src/test/resources/mappings/awsiamit_testgetidentity-post-1.json @@ -1,6 +1,6 @@ { - "id" : "d427d9c2-17e0-4b96-a7a0-f1224a207a9f", - "name" : "", + "id" : "a9be9342-31d9-4d59-b7d1-fe3c125d57e3", + "name" : "AwsIamIT_testGetIdentity-POST-1", "request" : { "url" : "/", "method" : "POST", @@ -11,14 +11,14 @@ }, "response" : { "status" : 200, - "body" : "\n \n \n /\n %7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Principal%22%3A%7B%22AWS%22%3A%22arn%3Aaws%3Aiam%3A%3A654654370895%3Aroot%22%7D%2C%22Action%22%3A%22sts%3AAssumeRole%22%7D%5D%7D\n 3600\n AROAZQ3DQ6RH6I4XU37DY\n \n MultiCloudJTestRoleGet\n Test identity for get operation\n arn:aws:iam::654654370895:role/MultiCloudJTestRoleGet\n 2026-02-26T22:34:00Z\n \n \n \n 6a4ce09c-1882-40d9-8928-7ebb29ac829c\n \n\n", + "body" : "\n \n \n /\n %7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Principal%22%3A%7B%22AWS%22%3A%22arn%3Aaws%3Aiam%3A%3A654654370895%3Aroot%22%7D%2C%22Action%22%3A%22sts%3AAssumeRole%22%7D%5D%7D\n 3600\n AROAZQ3DQ6RH7WGSXBZ2K\n \n MultiCloudJTestRoleGet\n Test identity for get operation\n arn:aws:iam::654654370895:role/MultiCloudJTestRoleGet\n 2026-03-10T06:16:33Z\n \n \n \n 4bec33b5-eca7-4f54-b6d7-9c73886e0611\n \n\n", "headers" : { - "x-amzn-RequestId" : "6a4ce09c-1882-40d9-8928-7ebb29ac829c", - "Date" : "Thu, 26 Feb 2026 22:34:02 GMT", + "x-amzn-RequestId" : "4bec33b5-eca7-4f54-b6d7-9c73886e0611", + "Date" : "Tue, 10 Mar 2026 06:16:35 GMT", "Content-Type" : "text/xml" } }, - "uuid" : "d427d9c2-17e0-4b96-a7a0-f1224a207a9f", + "uuid" : "a9be9342-31d9-4d59-b7d1-fe3c125d57e3", "persistent" : true, - "insertionIndex" : 34 + "insertionIndex" : 57 } \ No newline at end of file diff --git a/iam/iam-aws/src/test/resources/mappings/post-dksda62eby.json b/iam/iam-aws/src/test/resources/mappings/awsiamit_testgetidentity-post-2.json similarity index 72% rename from iam/iam-aws/src/test/resources/mappings/post-dksda62eby.json rename to iam/iam-aws/src/test/resources/mappings/awsiamit_testgetidentity-post-2.json index 1895b3e61..ce04a7975 100644 --- a/iam/iam-aws/src/test/resources/mappings/post-dksda62eby.json +++ b/iam/iam-aws/src/test/resources/mappings/awsiamit_testgetidentity-post-2.json @@ -1,6 +1,6 @@ { - "id" : "f1a6d455-2dec-4c28-ba63-622df999f6fc", - "name" : "", + "id" : "b50aa415-bb15-4d1c-b96c-1a4b97a13163", + "name" : "AwsIamIT_testGetIdentity-POST-2", "request" : { "url" : "/", "method" : "POST", @@ -11,14 +11,14 @@ }, "response" : { "status" : 200, - "body" : "\n \n \n /\n %7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%22sts%3AAssumeRole%22%2C%22Principal%22%3A%7B%22AWS%22%3A%5B%22arn%3Aaws%3Aiam%3A%3A654654370895%3Aroot%22%5D%7D%7D%5D%7D\n AROAZQ3DQ6RH6I4XU37DY\n MultiCloudJTestRoleGet\n arn:aws:iam::654654370895:role/MultiCloudJTestRoleGet\n 2026-02-26T22:34:00Z\n \n \n \n e2b05914-4b06-4723-8e3b-8fba415668be\n \n\n", + "body" : "\n \n \n /\n %7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%22sts%3AAssumeRole%22%2C%22Principal%22%3A%7B%22AWS%22%3A%5B%22arn%3Aaws%3Aiam%3A%3A654654370895%3Aroot%22%5D%7D%7D%5D%7D\n AROAZQ3DQ6RH7WGSXBZ2K\n MultiCloudJTestRoleGet\n arn:aws:iam::654654370895:role/MultiCloudJTestRoleGet\n 2026-03-10T06:16:33Z\n \n \n \n 1c8a9ba5-829a-4143-922f-0ce123215b66\n \n\n", "headers" : { - "x-amzn-RequestId" : "e2b05914-4b06-4723-8e3b-8fba415668be", - "Date" : "Thu, 26 Feb 2026 22:34:00 GMT", + "x-amzn-RequestId" : "1c8a9ba5-829a-4143-922f-0ce123215b66", + "Date" : "Tue, 10 Mar 2026 06:16:33 GMT", "Content-Type" : "text/xml" } }, - "uuid" : "f1a6d455-2dec-4c28-ba63-622df999f6fc", + "uuid" : "b50aa415-bb15-4d1c-b96c-1a4b97a13163", "persistent" : true, - "insertionIndex" : 35 + "insertionIndex" : 58 } \ No newline at end of file diff --git a/iam/iam-aws/src/test/resources/mappings/awsiamit_testgetinlinepolicydetails-post-0.json b/iam/iam-aws/src/test/resources/mappings/awsiamit_testgetinlinepolicydetails-post-0.json new file mode 100644 index 000000000..4fb560001 --- /dev/null +++ b/iam/iam-aws/src/test/resources/mappings/awsiamit_testgetinlinepolicydetails-post-0.json @@ -0,0 +1,24 @@ +{ + "id" : "526a8d77-eec8-49dc-abf0-b50ba151d70b", + "name" : "AwsIamIT_testGetInlinePolicyDetails-POST-0", + "request" : { + "url" : "/", + "method" : "POST", + "bodyPatterns" : [ { + "equalTo" : "Action=GetRolePolicy&Version=2010-05-08&RoleName=testSa&PolicyName=TestPolicy", + "caseInsensitive" : false + } ] + }, + "response" : { + "status" : 200, + "body" : "\n \n %7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%22s3%3AGetObject%22%2C%22Resource%22%3A%22arn%3Aaws%3As3%3A%3A%3Amulticloudj-iam-it-test-bucket%2F%2A%22%7D%5D%7D\n TestPolicy\n testSa\n \n \n 3068eec0-9180-4b25-9e49-86eeb168fae1\n \n\n", + "headers" : { + "x-amzn-RequestId" : "3068eec0-9180-4b25-9e49-86eeb168fae1", + "Date" : "Tue, 10 Mar 2026 06:16:14 GMT", + "Content-Type" : "text/xml" + } + }, + "uuid" : "526a8d77-eec8-49dc-abf0-b50ba151d70b", + "persistent" : true, + "insertionIndex" : 24 +} \ No newline at end of file diff --git a/iam/iam-aws/src/test/resources/mappings/post-wquhvbft3u.json b/iam/iam-aws/src/test/resources/mappings/awsiamit_testgetinlinepolicydetails-post-1.json similarity index 55% rename from iam/iam-aws/src/test/resources/mappings/post-wquhvbft3u.json rename to iam/iam-aws/src/test/resources/mappings/awsiamit_testgetinlinepolicydetails-post-1.json index 1d74b6ac5..a9ea0543b 100644 --- a/iam/iam-aws/src/test/resources/mappings/post-wquhvbft3u.json +++ b/iam/iam-aws/src/test/resources/mappings/awsiamit_testgetinlinepolicydetails-post-1.json @@ -1,24 +1,24 @@ { - "id" : "32adbab9-537f-4a9d-932e-77042386428d", - "name" : "", + "id" : "b609e007-8ebb-4fb1-ab72-f5632dbc0d27", + "name" : "AwsIamIT_testGetInlinePolicyDetails-POST-1", "request" : { "url" : "/", "method" : "POST", "bodyPatterns" : [ { - "equalTo" : "Action=PutRolePolicy&Version=2010-05-08&RoleName=testSa&PolicyName=TestPolicy&PolicyDocument=%7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%5B%22s3%3AGetObject%22%2C%22s3%3APutObject%22%5D%2C%22Resource%22%3A%5B%22arn%3Aaws%3As3%3A%3A%3Amulticloudj-iam-it-test-bucket%2F*%22%5D%7D%5D%7D", + "equalTo" : "Action=PutRolePolicy&Version=2010-05-08&RoleName=testSa&PolicyName=TestPolicy&PolicyDocument=%7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%22s3%3AGetObject%22%2C%22Resource%22%3A%22arn%3Aaws%3As3%3A%3A%3Amulticloudj-iam-it-test-bucket%2F*%22%7D%5D%7D", "caseInsensitive" : false } ] }, "response" : { "status" : 200, - "body" : "\n \n 5d2b3b54-1b48-4b8f-be3f-c888b7ff62bc\n \n\n", + "body" : "\n \n c4e11db4-c70f-47a3-a8e0-6f8f4136ab90\n \n\n", "headers" : { - "x-amzn-RequestId" : "5d2b3b54-1b48-4b8f-be3f-c888b7ff62bc", - "Date" : "Thu, 26 Feb 2026 22:33:45 GMT", + "x-amzn-RequestId" : "c4e11db4-c70f-47a3-a8e0-6f8f4136ab90", + "Date" : "Tue, 10 Mar 2026 06:16:13 GMT", "Content-Type" : "text/xml" } }, - "uuid" : "32adbab9-537f-4a9d-932e-77042386428d", + "uuid" : "b609e007-8ebb-4fb1-ab72-f5632dbc0d27", "persistent" : true, - "insertionIndex" : 20 + "insertionIndex" : 25 } \ No newline at end of file diff --git a/iam/iam-aws/src/test/resources/mappings/post-xg4blurbjw.json b/iam/iam-aws/src/test/resources/mappings/awsiamit_testidentitylifecycle-post-0.json similarity index 51% rename from iam/iam-aws/src/test/resources/mappings/post-xg4blurbjw.json rename to iam/iam-aws/src/test/resources/mappings/awsiamit_testidentitylifecycle-post-0.json index 04053b689..bf1803dbd 100644 --- a/iam/iam-aws/src/test/resources/mappings/post-xg4blurbjw.json +++ b/iam/iam-aws/src/test/resources/mappings/awsiamit_testidentitylifecycle-post-0.json @@ -1,6 +1,6 @@ { - "id" : "ec5c481a-564d-437b-918b-dc7f8ae61d84", - "name" : "", + "id" : "9d9f5588-2831-4d37-badb-990ff7281a0c", + "name" : "AwsIamIT_testIdentityLifecycle-POST-0", "request" : { "url" : "/", "method" : "POST", @@ -11,14 +11,14 @@ }, "response" : { "status" : 200, - "body" : "\n \n 5b1d6ade-9a99-4fc9-b3ee-3275d70d0774\n \n\n", + "body" : "\n \n 609bbfa7-35bb-454a-879e-c7e236e2e15d\n \n\n", "headers" : { - "x-amzn-RequestId" : "5b1d6ade-9a99-4fc9-b3ee-3275d70d0774", - "Date" : "Thu, 26 Feb 2026 22:33:37 GMT", + "x-amzn-RequestId" : "609bbfa7-35bb-454a-879e-c7e236e2e15d", + "Date" : "Tue, 10 Mar 2026 06:16:20 GMT", "Content-Type" : "text/xml" } }, - "uuid" : "ec5c481a-564d-437b-918b-dc7f8ae61d84", + "uuid" : "9d9f5588-2831-4d37-badb-990ff7281a0c", "persistent" : true, - "insertionIndex" : 7 + "insertionIndex" : 30 } \ No newline at end of file diff --git a/iam/iam-aws/src/test/resources/mappings/post-bdn3i0sqqv.json b/iam/iam-aws/src/test/resources/mappings/awsiamit_testidentitylifecycle-post-1.json similarity index 66% rename from iam/iam-aws/src/test/resources/mappings/post-bdn3i0sqqv.json rename to iam/iam-aws/src/test/resources/mappings/awsiamit_testidentitylifecycle-post-1.json index 58b9f1263..b007c6525 100644 --- a/iam/iam-aws/src/test/resources/mappings/post-bdn3i0sqqv.json +++ b/iam/iam-aws/src/test/resources/mappings/awsiamit_testidentitylifecycle-post-1.json @@ -1,6 +1,6 @@ { - "id" : "bb996a64-e3ba-42db-866d-7a0bf4938d1e", - "name" : "", + "id" : "ff620ba6-af45-4fa0-9b62-55a8ac590494", + "name" : "AwsIamIT_testIdentityLifecycle-POST-1", "request" : { "url" : "/", "method" : "POST", @@ -11,14 +11,14 @@ }, "response" : { "status" : 200, - "body" : "\n \n \n /\n %7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Principal%22%3A%7B%22AWS%22%3A%22arn%3Aaws%3Aiam%3A%3A654654370895%3Aroot%22%7D%2C%22Action%22%3A%22sts%3AAssumeRole%22%7D%5D%7D\n 3600\n AROAZQ3DQ6RHW3D5YSFCM\n \n MultiCloudJTestRoleLifeCycle\n Test identity for lifecycle test\n arn:aws:iam::654654370895:role/MultiCloudJTestRoleLifeCycle\n 2026-02-26T22:33:33Z\n \n \n \n 0e978bb1-e425-4f22-837b-b05eeb6da0db\n \n\n", + "body" : "\n \n \n /\n %7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Principal%22%3A%7B%22AWS%22%3A%22arn%3Aaws%3Aiam%3A%3A654654370895%3Aroot%22%7D%2C%22Action%22%3A%22sts%3AAssumeRole%22%7D%5D%7D\n 3600\n AROAZQ3DQ6RHUQ3VPZU7X\n \n MultiCloudJTestRoleLifeCycle\n Test identity for lifecycle test\n arn:aws:iam::654654370895:role/MultiCloudJTestRoleLifeCycle\n 2026-03-10T06:16:17Z\n \n \n \n 7bbefcbf-465c-4a2e-baac-d5bb7cadbf26\n \n\n", "headers" : { - "x-amzn-RequestId" : "0e978bb1-e425-4f22-837b-b05eeb6da0db", - "Date" : "Thu, 26 Feb 2026 22:33:36 GMT", + "x-amzn-RequestId" : "7bbefcbf-465c-4a2e-baac-d5bb7cadbf26", + "Date" : "Tue, 10 Mar 2026 06:16:19 GMT", "Content-Type" : "text/xml" } }, - "uuid" : "bb996a64-e3ba-42db-866d-7a0bf4938d1e", + "uuid" : "ff620ba6-af45-4fa0-9b62-55a8ac590494", "persistent" : true, - "insertionIndex" : 8 + "insertionIndex" : 31 } \ No newline at end of file diff --git a/iam/iam-aws/src/test/resources/mappings/post-fcmgsogo3z.json b/iam/iam-aws/src/test/resources/mappings/awsiamit_testidentitylifecycle-post-2.json similarity index 65% rename from iam/iam-aws/src/test/resources/mappings/post-fcmgsogo3z.json rename to iam/iam-aws/src/test/resources/mappings/awsiamit_testidentitylifecycle-post-2.json index c1dece656..5a27e9cea 100644 --- a/iam/iam-aws/src/test/resources/mappings/post-fcmgsogo3z.json +++ b/iam/iam-aws/src/test/resources/mappings/awsiamit_testidentitylifecycle-post-2.json @@ -1,6 +1,6 @@ { - "id" : "113f417b-8d08-4ca5-8d1b-a9f99f0a30cc", - "name" : "", + "id" : "4263f922-9cb4-4d8a-bcdf-243ee01b46f5", + "name" : "AwsIamIT_testIdentityLifecycle-POST-2", "request" : { "url" : "/", "method" : "POST", @@ -11,14 +11,14 @@ }, "response" : { "status" : 200, - "body" : "\n \n \n /\n %7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%22sts%3AAssumeRole%22%2C%22Principal%22%3A%7B%22AWS%22%3A%5B%22arn%3Aaws%3Aiam%3A%3A654654370895%3Aroot%22%5D%7D%7D%5D%7D\n AROAZQ3DQ6RHW3D5YSFCM\n MultiCloudJTestRoleLifeCycle\n arn:aws:iam::654654370895:role/MultiCloudJTestRoleLifeCycle\n 2026-02-26T22:33:33Z\n \n \n \n 08361a8c-21b0-4005-ac18-049ce8ef8a40\n \n\n", + "body" : "\n \n \n /\n %7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%22sts%3AAssumeRole%22%2C%22Principal%22%3A%7B%22AWS%22%3A%5B%22arn%3Aaws%3Aiam%3A%3A654654370895%3Aroot%22%5D%7D%7D%5D%7D\n AROAZQ3DQ6RHUQ3VPZU7X\n MultiCloudJTestRoleLifeCycle\n arn:aws:iam::654654370895:role/MultiCloudJTestRoleLifeCycle\n 2026-03-10T06:16:17Z\n \n \n \n 15fb3022-3c3b-4763-982c-452752ff30b0\n \n\n", "headers" : { - "x-amzn-RequestId" : "08361a8c-21b0-4005-ac18-049ce8ef8a40", - "Date" : "Thu, 26 Feb 2026 22:33:33 GMT", + "x-amzn-RequestId" : "15fb3022-3c3b-4763-982c-452752ff30b0", + "Date" : "Tue, 10 Mar 2026 06:16:17 GMT", "Content-Type" : "text/xml" } }, - "uuid" : "113f417b-8d08-4ca5-8d1b-a9f99f0a30cc", + "uuid" : "4263f922-9cb4-4d8a-bcdf-243ee01b46f5", "persistent" : true, - "insertionIndex" : 9 + "insertionIndex" : 32 } \ No newline at end of file diff --git a/iam/iam-aws/src/test/resources/mappings/post-drbdsqpgqi.json b/iam/iam-aws/src/test/resources/mappings/awsiamit_testremovepolicy-post-0.json similarity index 60% rename from iam/iam-aws/src/test/resources/mappings/post-drbdsqpgqi.json rename to iam/iam-aws/src/test/resources/mappings/awsiamit_testremovepolicy-post-0.json index 39736f4ef..d9b95d322 100644 --- a/iam/iam-aws/src/test/resources/mappings/post-drbdsqpgqi.json +++ b/iam/iam-aws/src/test/resources/mappings/awsiamit_testremovepolicy-post-0.json @@ -1,6 +1,6 @@ { - "id" : "8a70e007-0a27-4398-af28-7e744deec661", - "name" : "", + "id" : "8d976856-2bd4-4661-80ea-b06d3a497e80", + "name" : "AwsIamIT_testRemovePolicy-POST-0", "request" : { "url" : "/", "method" : "POST", @@ -11,14 +11,14 @@ }, "response" : { "status" : 200, - "body" : "\n \n 4492993d-6b35-4df5-a12a-764a8b4e25b6\n \n\n", + "body" : "\n \n 0d604f03-03ec-44a8-8e13-2b24d6040029\n \n\n", "headers" : { - "x-amzn-RequestId" : "4492993d-6b35-4df5-a12a-764a8b4e25b6", - "Date" : "Thu, 26 Feb 2026 22:33:44 GMT", + "x-amzn-RequestId" : "0d604f03-03ec-44a8-8e13-2b24d6040029", + "Date" : "Tue, 10 Mar 2026 06:16:24 GMT", "Content-Type" : "text/xml" } }, - "uuid" : "8a70e007-0a27-4398-af28-7e744deec661", + "uuid" : "8d976856-2bd4-4661-80ea-b06d3a497e80", "persistent" : true, - "insertionIndex" : 16 + "insertionIndex" : 39 } \ No newline at end of file diff --git a/iam/iam-aws/src/test/resources/mappings/post-ru6chj0znq.json b/iam/iam-aws/src/test/resources/mappings/awsiamit_testremovepolicy-post-1.json similarity index 55% rename from iam/iam-aws/src/test/resources/mappings/post-ru6chj0znq.json rename to iam/iam-aws/src/test/resources/mappings/awsiamit_testremovepolicy-post-1.json index e6fe6afc6..8d491f6b8 100644 --- a/iam/iam-aws/src/test/resources/mappings/post-ru6chj0znq.json +++ b/iam/iam-aws/src/test/resources/mappings/awsiamit_testremovepolicy-post-1.json @@ -1,24 +1,24 @@ { - "id" : "22797706-bc57-4d29-a379-7a2ccb31b212", - "name" : "", + "id" : "f14e1623-007d-419b-a2b4-4221292303ef", + "name" : "AwsIamIT_testRemovePolicy-POST-1", "request" : { "url" : "/", "method" : "POST", "bodyPatterns" : [ { - "equalTo" : "Action=PutRolePolicy&Version=2010-05-08&RoleName=testSa&PolicyName=TestPolicy&PolicyDocument=%7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%5B%22s3%3AGetObject%22%2C%22s3%3APutObject%22%5D%2C%22Resource%22%3A%5B%22arn%3Aaws%3As3%3A%3A%3Amulticloudj-iam-it-test-bucket%2F*%22%5D%7D%5D%7D", + "equalTo" : "Action=PutRolePolicy&Version=2010-05-08&RoleName=testSa&PolicyName=TestPolicy&PolicyDocument=%7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%22s3%3AGetObject%22%2C%22Resource%22%3A%22arn%3Aaws%3As3%3A%3A%3Amulticloudj-iam-it-test-bucket%2F*%22%7D%5D%7D", "caseInsensitive" : false } ] }, "response" : { "status" : 200, - "body" : "\n \n 96b06a8c-c84f-43e1-9536-5aa3b5476542\n \n\n", + "body" : "\n \n 13b00b87-6ccc-42b7-a0f7-8a144aa2262f\n \n\n", "headers" : { - "x-amzn-RequestId" : "96b06a8c-c84f-43e1-9536-5aa3b5476542", - "Date" : "Thu, 26 Feb 2026 22:33:27 GMT", + "x-amzn-RequestId" : "13b00b87-6ccc-42b7-a0f7-8a144aa2262f", + "Date" : "Tue, 10 Mar 2026 06:16:23 GMT", "Content-Type" : "text/xml" } }, - "uuid" : "22797706-bc57-4d29-a379-7a2ccb31b212", + "uuid" : "f14e1623-007d-419b-a2b4-4221292303ef", "persistent" : true, - "insertionIndex" : 2 + "insertionIndex" : 40 } \ No newline at end of file diff --git a/iam/iam-aws/src/test/resources/mappings/post-bzrkjjeoqm.json b/iam/iam-aws/src/test/resources/mappings/post-bzrkjjeoqm.json deleted file mode 100644 index 4c8e26903..000000000 --- a/iam/iam-aws/src/test/resources/mappings/post-bzrkjjeoqm.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "id" : "40a6ca24-a9bb-448b-92e9-9561c250a2be", - "name" : "", - "request" : { - "url" : "/", - "method" : "POST", - "bodyPatterns" : [ { - "equalTo" : "Action=GetRolePolicy&Version=2010-05-08&RoleName=testSa&PolicyName=TestPolicy", - "caseInsensitive" : false - } ] - }, - "response" : { - "status" : 200, - "body" : "\n \n %7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Action%22%3A%5B%22s3%3AGetObject%22%2C%22s3%3APutObject%22%5D%2C%22Resource%22%3A%5B%22arn%3Aaws%3As3%3A%3A%3Amulticloudj-iam-it-test-bucket%2F%2A%22%5D%7D%5D%7D\n TestPolicy\n testSa\n \n \n e3784cee-baad-4ae1-a534-6d6b3bd10fc2\n \n\n", - "headers" : { - "x-amzn-RequestId" : "e3784cee-baad-4ae1-a534-6d6b3bd10fc2", - "Date" : "Thu, 26 Feb 2026 22:33:28 GMT", - "Content-Type" : "text/xml" - } - }, - "uuid" : "40a6ca24-a9bb-448b-92e9-9561c250a2be", - "persistent" : true, - "insertionIndex" : 1 -} \ No newline at end of file diff --git a/iam/iam-client/pom.xml b/iam/iam-client/pom.xml index 4fd70a283..8a227e5f7 100644 --- a/iam/iam-client/pom.xml +++ b/iam/iam-client/pom.xml @@ -32,6 +32,13 @@ provided
+ + + com.fasterxml.jackson.core + jackson-annotations + 2.18.2 + + org.mockito diff --git a/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/Action.java b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/Action.java new file mode 100644 index 000000000..066a60ff3 --- /dev/null +++ b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/Action.java @@ -0,0 +1,148 @@ +package com.salesforce.multicloudj.iam.model; + +import com.fasterxml.jackson.annotation.JsonValue; +import com.salesforce.multicloudj.common.exceptions.InvalidArgumentException; +import java.util.Objects; + +/** + * Represents a substrate-neutral IAM action. + * + *

Actions follow the format {@code service:operation}, where: + * + *

+ * + *

Use pre-defined constants from {@link StorageActions}, {@link ComputeActions}, and {@link + * IamActions} for common actions, or create custom actions using {@link Action#of(String)}. + * + *

Example usage: + * + *

+ * // Using pre-defined constants (recommended)
+ * Action action1 = StorageActions.GET_OBJECT;
+ *
+ * // Using wildcard
+ * Action action2 = StorageActions.ALL; // storage:*
+ *
+ * // Creating custom action
+ * Action action3 = Action.of("customService:CustomOperation");
+ * 
+ */ +public final class Action { + private final String service; + private final String operation; + + private Action(String service, String operation) { + if (service == null || service.trim().isEmpty()) { + throw new InvalidArgumentException("Action service cannot be null or empty"); + } + if (operation == null || operation.trim().isEmpty()) { + throw new InvalidArgumentException("Action operation cannot be null or empty"); + } + this.service = service.trim(); + this.operation = operation.trim(); + } + + /** + * Creates an Action from a string representation. + * + * @param action the action string in format "service:operation" (e.g., "storage:GetObject") + * @return the Action object + * @throws InvalidArgumentException if the action format is invalid + */ + public static Action of(String action) { + if (action == null || action.trim().isEmpty()) { + throw new InvalidArgumentException("Action string cannot be null or empty"); + } + + String trimmed = action.trim(); + int colonIndex = trimmed.indexOf(':'); + + if (colonIndex <= 0 || colonIndex == trimmed.length() - 1) { + throw new InvalidArgumentException( + "Invalid action format: '" + action + "'. Expected format: 'service:operation'"); + } + + // Check for multiple colons + if (trimmed.indexOf(':', colonIndex + 1) != -1) { + throw new InvalidArgumentException( + "Invalid action format: '" + action + "'. Expected format: 'service:operation'"); + } + + String service = trimmed.substring(0, colonIndex); + String operation = trimmed.substring(colonIndex + 1); + + return new Action(service, operation); + } + + /** + * Creates a wildcard action for the specified service. + * + * @param service the service name + * @return an Action representing all operations for the service + */ + static Action wildcard(String service) { + return new Action(service, "*"); + } + + /** + * Returns the service component of this action. + * + * @return the service name + */ + public String getService() { + return service; + } + + /** + * Returns the operation component of this action. + * + * @return the operation name + */ + public String getOperation() { + return operation; + } + + /** + * Checks if this is a wildcard action (operation = "*"). + * + * @return true if this is a wildcard action + */ + public boolean isWildcard() { + return "*".equals(operation); + } + + /** + * Returns the string representation in format "service:operation". + * + * @return the action string + */ + @JsonValue + public String toActionString() { + return service + ":" + operation; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Action action = (Action) o; + return service.equals(action.service) && operation.equals(action.operation); + } + + @Override + public int hashCode() { + return Objects.hash(service, operation); + } + + @Override + public String toString() { + return toActionString(); + } +} diff --git a/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/ComputeActions.java b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/ComputeActions.java new file mode 100644 index 000000000..20fce222f --- /dev/null +++ b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/ComputeActions.java @@ -0,0 +1,34 @@ +package com.salesforce.multicloudj.iam.model; + +/** + * Pre-defined compute service actions for IAM policies. + * + *

These constants represent common compute operations that can be used in policy statements + * across AWS EC2, GCP Compute Engine, and other cloud providers. + */ +public final class ComputeActions { + private ComputeActions() { + // Prevent instantiation + } + + /** Action to create/launch a new compute instance */ + public static final Action CREATE_INSTANCE = Action.of("compute:CreateInstance"); + + /** Action to delete/terminate a compute instance */ + public static final Action DELETE_INSTANCE = Action.of("compute:DeleteInstance"); + + /** Action to start a stopped compute instance */ + public static final Action START_INSTANCE = Action.of("compute:StartInstance"); + + /** Action to stop a running compute instance */ + public static final Action STOP_INSTANCE = Action.of("compute:StopInstance"); + + /** Action to list/describe compute instances */ + public static final Action DESCRIBE_INSTANCES = Action.of("compute:DescribeInstances"); + + /** Action to get details of a specific compute instance */ + public static final Action GET_INSTANCE = Action.of("compute:GetInstance"); + + /** Wildcard action representing all compute operations */ + public static final Action ALL = Action.wildcard("compute"); +} diff --git a/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/ConditionOperator.java b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/ConditionOperator.java new file mode 100644 index 000000000..963979919 --- /dev/null +++ b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/ConditionOperator.java @@ -0,0 +1,90 @@ +package com.salesforce.multicloudj.iam.model; + +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Condition operators for IAM policy conditions. + * + *

These operators are used to define conditions under which a policy statement applies. They + * follow substrate-neutral naming conventions and are translated to provider-specific formats + * (e.g., "stringEquals" → "StringEquals" in AWS). + */ +public enum ConditionOperator { + /** String equality comparison */ + STRING_EQUALS("stringEquals"), + + /** String inequality comparison */ + STRING_NOT_EQUALS("stringNotEquals"), + + /** String pattern matching (supports wildcards) */ + STRING_LIKE("stringLike"), + + /** Negated string pattern matching */ + STRING_NOT_LIKE("stringNotLike"), + + /** Numeric equality comparison */ + NUMERIC_EQUALS("numericEquals"), + + /** Numeric inequality comparison */ + NUMERIC_NOT_EQUALS("numericNotEquals"), + + /** Numeric less-than comparison */ + NUMERIC_LESS_THAN("numericLessThan"), + + /** Numeric less-than-or-equal comparison */ + NUMERIC_LESS_THAN_EQUALS("numericLessThanEquals"), + + /** Numeric greater-than comparison */ + NUMERIC_GREATER_THAN("numericGreaterThan"), + + /** Numeric greater-than-or-equal comparison */ + NUMERIC_GREATER_THAN_EQUALS("numericGreaterThanEquals"), + + /** Date equality comparison */ + DATE_EQUALS("dateEquals"), + + /** Date inequality comparison */ + DATE_NOT_EQUALS("dateNotEquals"), + + /** Date less-than (before) comparison */ + DATE_LESS_THAN("dateLessThan"), + + /** Date less-than-or-equal comparison */ + DATE_LESS_THAN_EQUALS("dateLessThanEquals"), + + /** Date greater-than (after) comparison */ + DATE_GREATER_THAN("dateGreaterThan"), + + /** Date greater-than-or-equal comparison */ + DATE_GREATER_THAN_EQUALS("dateGreaterThanEquals"), + + /** Boolean comparison */ + BOOL("bool"), + + /** IP address matching */ + IP_ADDRESS("ipAddress"), + + /** Negated IP address matching */ + NOT_IP_ADDRESS("notIpAddress"); + + private final String value; + + ConditionOperator(String value) { + this.value = value; + } + + /** + * Returns the string representation used in policy documents. + * + * @return the operator value + */ + @JsonValue + public String getValue() { + return value; + } + + @Override + public String toString() { + return value; + } +} diff --git a/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/Effect.java b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/Effect.java new file mode 100644 index 000000000..ff274d26f --- /dev/null +++ b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/Effect.java @@ -0,0 +1,37 @@ +package com.salesforce.multicloudj.iam.model; + +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Represents the effect of a policy statement. + * + *

Effect determines whether the statement allows or denies access. + */ +public enum Effect { + /** Grants access to the specified actions */ + ALLOW("Allow"), + + /** Explicitly denies access to the specified actions */ + DENY("Deny"); + + private final String value; + + Effect(String value) { + this.value = value; + } + + /** + * Returns the string representation used in policy documents. + * + * @return the effect value + */ + @JsonValue + public String getValue() { + return value; + } + + @Override + public String toString() { + return value; + } +} diff --git a/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/IamActions.java b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/IamActions.java new file mode 100644 index 000000000..6e4d61abe --- /dev/null +++ b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/IamActions.java @@ -0,0 +1,40 @@ +package com.salesforce.multicloudj.iam.model; + +/** + * Pre-defined IAM service actions for IAM policies. + * + *

These constants represent common IAM operations that can be used in policy statements across + * AWS IAM, GCP IAM, and other cloud providers. + */ +public final class IamActions { + private IamActions() { + // Prevent instantiation + } + + /** Action to assume a role (for cross-account or service access) */ + public static final Action ASSUME_ROLE = Action.of("iam:AssumeRole"); + + /** Action to create a new IAM role */ + public static final Action CREATE_ROLE = Action.of("iam:CreateRole"); + + /** Action to delete an IAM role */ + public static final Action DELETE_ROLE = Action.of("iam:DeleteRole"); + + /** Action to get details of an IAM role */ + public static final Action GET_ROLE = Action.of("iam:GetRole"); + + /** Action to attach a policy to a role */ + public static final Action ATTACH_ROLE_POLICY = Action.of("iam:AttachRolePolicy"); + + /** Action to detach a policy from a role */ + public static final Action DETACH_ROLE_POLICY = Action.of("iam:DetachRolePolicy"); + + /** Action to create/update an inline role policy */ + public static final Action PUT_ROLE_POLICY = Action.of("iam:PutRolePolicy"); + + /** Action to get an inline role policy */ + public static final Action GET_ROLE_POLICY = Action.of("iam:GetRolePolicy"); + + /** Wildcard action representing all IAM operations */ + public static final Action ALL = Action.wildcard("iam"); +} diff --git a/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/PolicyDocument.java b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/PolicyDocument.java index 42d59e42c..6d56f7205 100644 --- a/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/PolicyDocument.java +++ b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/PolicyDocument.java @@ -20,12 +20,12 @@ * PolicyDocument policy = PolicyDocument.builder() * .statement(Statement.builder() * .sid("StorageAccess") - * .effect("Allow") - * .action("storage:GetObject") - * .action("storage:PutObject") + * .effect(Effect.ALLOW) + * .action(StorageActions.GET_OBJECT) + * .action(StorageActions.PUT_OBJECT) * .principal("arn:aws:iam::123456789012:user/ExampleUser") * .resource("storage://my-bucket/*") - * .condition("StringEquals", "aws:RequestedRegion", "us-west-2") + * .condition(ConditionOperator.STRING_EQUALS, "aws:RequestedRegion", "us-west-2") * .build()) * .build(); * diff --git a/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/Statement.java b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/Statement.java index 733603f9d..11ea20769 100644 --- a/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/Statement.java +++ b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/Statement.java @@ -3,6 +3,8 @@ import com.salesforce.multicloudj.common.exceptions.InvalidArgumentException; import java.util.List; import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; import lombok.Builder; import lombok.Getter; import lombok.Singular; @@ -18,45 +20,50 @@ *

  * Statement statement = Statement.builder()
  *     .sid("StorageAccess")
- *     .effect("Allow")
- *     .action("storage:GetObject")
- *     .action("storage:PutObject")
+ *     .effect(Effect.ALLOW)
+ *     .action(StorageActions.GET_OBJECT)
+ *     .action(StorageActions.PUT_OBJECT)
  *     .principal("arn:aws:iam::123456789012:user/ExampleUser")
  *     .resource("storage://my-bucket/*")
- *     .condition("StringEquals", "aws:RequestedRegion", "us-west-2")
+ *     .condition(ConditionOperator.STRING_EQUALS, "aws:RequestedRegion", "us-west-2")
  *     .build();
  * 
*/ @Getter public class Statement { private final String sid; - private final String effect; + private final Effect effect; private final List principals; - private final List actions; + private final List actions; private final List resources; - private final Map> conditions; + private final Map> conditions; @Builder private Statement( String sid, - String effect, + Effect effect, @Singular List principals, - @Singular List actions, + @Singular List actions, @Singular List resources, - Map> conditions) { + Map> conditions) { + // Validate effect - if (effect == null || effect.trim().isEmpty()) { - throw new InvalidArgumentException("Effect is required and cannot be empty"); + if (effect == null) { + throw new InvalidArgumentException("Effect is required and cannot be null"); } - // Filter out null/empty/whitespace values and validate actions + // Filter out null/empty/whitespace values this.sid = sid; this.effect = effect; this.principals = filterValidStrings(principals); - this.actions = filterValidStrings(actions); this.resources = filterValidStrings(resources); - // Validate that at least one action exists after filtering + // Filter and validate actions + if (actions == null || actions.isEmpty()) { + throw new InvalidArgumentException("At least one action is required"); + } + this.actions = actions.stream().filter(Objects::nonNull).collect(Collectors.toList()); + if (this.actions.isEmpty()) { throw new InvalidArgumentException("At least one action is required"); } @@ -70,7 +77,26 @@ private static List filterValidStrings(List input) { } return input.stream() .filter(s -> s != null && !s.trim().isEmpty()) - .collect(java.util.stream.Collectors.toList()); + .collect(Collectors.toList()); + } + + /** + * Returns actions as strings for internal use by translators. + * + * @return list of action strings in format "service:operation" + */ + public List getActionsAsStrings() { + return actions.stream().map(Action::toActionString).collect(Collectors.toList()); + } + + /** + * Returns conditions with string keys for internal use by translators. + * + * @return map of condition operator strings to condition maps + */ + public Map> getConditionsAsStrings() { + return conditions.entrySet().stream() + .collect(Collectors.toMap(e -> e.getKey().getValue(), Map.Entry::getValue)); } /** Custom builder for Statement to handle conditions. */ @@ -83,7 +109,7 @@ public static class StatementBuilder { * @param value the condition value * @return this builder */ - public StatementBuilder condition(String operator, String key, Object value) { + public StatementBuilder condition(ConditionOperator operator, String key, Object value) { if (operator != null && key != null && value != null) { if (this.conditions == null) { this.conditions = new java.util.HashMap<>(); diff --git a/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/StorageActions.java b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/StorageActions.java new file mode 100644 index 000000000..b891e39e2 --- /dev/null +++ b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/StorageActions.java @@ -0,0 +1,37 @@ +package com.salesforce.multicloudj.iam.model; + +/** + * Pre-defined storage service actions for IAM policies. + * + *

These constants represent common storage operations that can be used in policy statements + * across AWS S3, GCP Cloud Storage, and other cloud providers. + */ +public final class StorageActions { + private StorageActions() { + // Prevent instantiation + } + + /** Action to read objects from storage */ + public static final Action GET_OBJECT = Action.of("storage:GetObject"); + + /** Action to write/upload objects to storage */ + public static final Action PUT_OBJECT = Action.of("storage:PutObject"); + + /** Action to delete objects from storage */ + public static final Action DELETE_OBJECT = Action.of("storage:DeleteObject"); + + /** Action to list objects in a bucket/container */ + public static final Action LIST_BUCKET = Action.of("storage:ListBucket"); + + /** Action to get bucket location/metadata */ + public static final Action GET_BUCKET_LOCATION = Action.of("storage:GetBucketLocation"); + + /** Action to create a new bucket/container */ + public static final Action CREATE_BUCKET = Action.of("storage:CreateBucket"); + + /** Action to delete a bucket/container */ + public static final Action DELETE_BUCKET = Action.of("storage:DeleteBucket"); + + /** Wildcard action representing all storage operations */ + public static final Action ALL = Action.wildcard("storage"); +} diff --git a/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/client/AbstractIamIT.java b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/client/AbstractIamIT.java index fe8481795..5e1c05eb4 100644 --- a/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/client/AbstractIamIT.java +++ b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/client/AbstractIamIT.java @@ -2,8 +2,10 @@ import com.salesforce.multicloudj.common.util.common.TestsUtil; import com.salesforce.multicloudj.iam.driver.AbstractIam; +import com.salesforce.multicloudj.iam.model.Action; import com.salesforce.multicloudj.iam.model.AttachInlinePolicyRequest; import com.salesforce.multicloudj.iam.model.CreateOptions; +import com.salesforce.multicloudj.iam.model.Effect; import com.salesforce.multicloudj.iam.model.GetAttachedPoliciesRequest; import com.salesforce.multicloudj.iam.model.GetInlinePolicyDetailsRequest; import com.salesforce.multicloudj.iam.model.PolicyDocument; @@ -54,6 +56,10 @@ default String getPolicyVersion() { String getTestPolicyName(); + default String getTestAction() { + return "storage:GetObject"; + } + /** * Role name for getInlinePolicyDetails (and similar) when the API requires it. Unused for AWS * (identity is used); required for GCP (e.g. "roles/storage.objectViewer"). @@ -114,13 +120,12 @@ public void cleanupTestEnvironment() throws Exception { @Test public void testAttachInlinePolicy() { - Statement.StatementBuilder statementBuilder = - Statement.builder().effect(harness.getTestPolicyEffect()); + Statement.StatementBuilder statementBuilder = Statement.builder().effect(Effect.ALLOW); if (StringUtils.isNotBlank(harness.getTestPolicyResource())) { statementBuilder.resource(harness.getTestPolicyResource()); } for (String action : harness.getTestPolicyActions()) { - statementBuilder.action(action); + statementBuilder.action(Action.of(action)); } PolicyDocument policyDocument = @@ -141,19 +146,23 @@ public void testAttachInlinePolicy() { @Test public void testGetInlinePolicyDetails() { - Statement.StatementBuilder statementBuilder = - Statement.builder().effect(harness.getTestPolicyEffect()); + Statement.StatementBuilder statementBuilder = Statement.builder().effect(Effect.ALLOW); if (StringUtils.isNotBlank(harness.getTestPolicyResource())) { statementBuilder.resource(harness.getTestPolicyResource()); } for (String action : harness.getTestPolicyActions()) { - statementBuilder.action(action); + statementBuilder.action(Action.of(action)); } PolicyDocument policyDocument = PolicyDocument.builder() .name(harness.getTestPolicyName()) .version(harness.getPolicyVersion()) - .statement(statementBuilder.build()) + .statement( + Statement.builder() + .effect(Effect.ALLOW) + .action(Action.of(harness.getTestAction())) + .resource(harness.getTestPolicyResource()) + .build()) .build(); iamClient.attachInlinePolicy( @@ -179,13 +188,12 @@ public void testGetInlinePolicyDetails() { @Test public void testGetAttachedPolicies() { - Statement.StatementBuilder statementBuilder = - Statement.builder().effect(harness.getTestPolicyEffect()); + Statement.StatementBuilder statementBuilder = Statement.builder().effect(Effect.ALLOW); if (StringUtils.isNotBlank(harness.getTestPolicyResource())) { statementBuilder.resource(harness.getTestPolicyResource()); } for (String action : harness.getTestPolicyActions()) { - statementBuilder.action(action); + statementBuilder.action(Action.of(action)); } PolicyDocument policyDocument = @@ -217,19 +225,23 @@ public void testGetAttachedPolicies() { @Test public void testRemovePolicy() { - Statement.StatementBuilder statementBuilder = - Statement.builder().effect(harness.getTestPolicyEffect()); + Statement.StatementBuilder statementBuilder = Statement.builder().effect(Effect.ALLOW); if (StringUtils.isNotBlank(harness.getTestPolicyResource())) { statementBuilder.resource(harness.getTestPolicyResource()); } for (String action : harness.getTestPolicyActions()) { - statementBuilder.action(action); + statementBuilder.action(Action.of(action)); } PolicyDocument policyDocument = PolicyDocument.builder() .name(harness.getTestPolicyName()) .version(harness.getPolicyVersion()) - .statement(statementBuilder.build()) + .statement( + Statement.builder() + .effect(Effect.ALLOW) + .action(Action.of(harness.getTestAction())) + .resource(harness.getTestPolicyResource()) + .build()) .build(); iamClient.attachInlinePolicy( diff --git a/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/client/IamClientTest.java b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/client/IamClientTest.java index 1b943df57..0edf6232d 100644 --- a/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/client/IamClientTest.java +++ b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/client/IamClientTest.java @@ -17,10 +17,12 @@ import com.salesforce.multicloudj.common.exceptions.UnAuthorizedException; import com.salesforce.multicloudj.iam.driver.AbstractIam; import com.salesforce.multicloudj.iam.model.AttachInlinePolicyRequest; +import com.salesforce.multicloudj.iam.model.Effect; import com.salesforce.multicloudj.iam.model.GetAttachedPoliciesRequest; import com.salesforce.multicloudj.iam.model.GetInlinePolicyDetailsRequest; import com.salesforce.multicloudj.iam.model.PolicyDocument; import com.salesforce.multicloudj.iam.model.Statement; +import com.salesforce.multicloudj.iam.model.StorageActions; import com.salesforce.multicloudj.sts.model.CredentialsOverrider; import java.net.URI; import java.util.Arrays; @@ -138,8 +140,8 @@ void testAttachInlinePolicy() { .statement( Statement.builder() .sid("TestPolicy") - .effect("Allow") - .action("storage:GetObject") + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) .build()) .build(); AttachInlinePolicyRequest request = @@ -165,8 +167,8 @@ void testAttachInlinePolicyThrowsException() { .statement( Statement.builder() .sid("TestPolicy") - .effect("Allow") - .action("storage:GetObject") + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) .build()) .build(); AttachInlinePolicyRequest request = diff --git a/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/driver/AbstractIamTest.java b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/driver/AbstractIamTest.java index b4195eb94..a978e6149 100644 --- a/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/driver/AbstractIamTest.java +++ b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/driver/AbstractIamTest.java @@ -16,7 +16,9 @@ import com.salesforce.multicloudj.common.exceptions.InvalidArgumentException; import com.salesforce.multicloudj.iam.client.TestIam; +import com.salesforce.multicloudj.iam.model.Action; import com.salesforce.multicloudj.iam.model.AttachInlinePolicyRequest; +import com.salesforce.multicloudj.iam.model.Effect; import com.salesforce.multicloudj.iam.model.GetAttachedPoliciesRequest; import com.salesforce.multicloudj.iam.model.GetInlinePolicyDetailsRequest; import com.salesforce.multicloudj.iam.model.PolicyDocument; @@ -274,7 +276,8 @@ void testValidationThrowsInvalidArgumentException() { PolicyDocument policy = PolicyDocument.builder() .version("2012-10-17") - .statement(Statement.builder().effect("Allow").action("s3:GetObject").build()) + .statement( + Statement.builder().effect(Effect.ALLOW).action(Action.of("s3:GetObject")).build()) .build(); // createIdentity diff --git a/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/ActionTest.java b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/ActionTest.java new file mode 100644 index 000000000..587bcfa4b --- /dev/null +++ b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/ActionTest.java @@ -0,0 +1,89 @@ +package com.salesforce.multicloudj.iam.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.salesforce.multicloudj.common.exceptions.InvalidArgumentException; +import org.junit.jupiter.api.Test; + +public class ActionTest { + + @Test + public void testValidActionParsing() { + Action action = Action.of("storage:GetObject"); + assertEquals("storage", action.getService()); + assertEquals("GetObject", action.getOperation()); + assertEquals("storage:GetObject", action.toActionString()); + assertFalse(action.isWildcard()); + } + + @Test + public void testWildcardAction() { + Action action = Action.of("storage:*"); + assertEquals("storage", action.getService()); + assertEquals("*", action.getOperation()); + assertEquals("storage:*", action.toActionString()); + assertTrue(action.isWildcard()); + } + + @Test + public void testInvalidFormatNoColon() { + assertThrows(InvalidArgumentException.class, () -> Action.of("invalid")); + } + + @Test + public void testInvalidFormatMultipleColons() { + assertThrows(InvalidArgumentException.class, () -> Action.of("too:many:parts")); + } + + @Test + public void testInvalidFormatEmptyService() { + assertThrows(InvalidArgumentException.class, () -> Action.of(":GetObject")); + } + + @Test + public void testInvalidFormatEmptyOperation() { + assertThrows(InvalidArgumentException.class, () -> Action.of("storage:")); + } + + @Test + public void testNullAction() { + assertThrows(InvalidArgumentException.class, () -> Action.of(null)); + } + + @Test + public void testEmptyAction() { + assertThrows(InvalidArgumentException.class, () -> Action.of("")); + } + + @Test + public void testWhitespaceAction() { + assertThrows(InvalidArgumentException.class, () -> Action.of(" ")); + } + + @Test + public void testActionWithWhitespace() { + Action action = Action.of(" storage : GetObject "); + assertEquals("storage", action.getService()); + assertEquals("GetObject", action.getOperation()); + } + + @Test + public void testActionEquality() { + Action action1 = Action.of("storage:GetObject"); + Action action2 = Action.of("storage:GetObject"); + Action action3 = Action.of("storage:PutObject"); + + assertEquals(action1, action2); + assertEquals(action1.hashCode(), action2.hashCode()); + assertFalse(action1.equals(action3)); + } + + @Test + public void testActionToString() { + Action action = Action.of("compute:CreateInstance"); + assertEquals("compute:CreateInstance", action.toString()); + } +} diff --git a/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/ComputeActionsTest.java b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/ComputeActionsTest.java new file mode 100644 index 000000000..bf428b964 --- /dev/null +++ b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/ComputeActionsTest.java @@ -0,0 +1,45 @@ +package com.salesforce.multicloudj.iam.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +public class ComputeActionsTest { + + @Test + public void testCreateInstance() { + assertEquals("compute:CreateInstance", ComputeActions.CREATE_INSTANCE.toActionString()); + } + + @Test + public void testDeleteInstance() { + assertEquals("compute:DeleteInstance", ComputeActions.DELETE_INSTANCE.toActionString()); + } + + @Test + public void testStartInstance() { + assertEquals("compute:StartInstance", ComputeActions.START_INSTANCE.toActionString()); + } + + @Test + public void testStopInstance() { + assertEquals("compute:StopInstance", ComputeActions.STOP_INSTANCE.toActionString()); + } + + @Test + public void testDescribeInstances() { + assertEquals("compute:DescribeInstances", ComputeActions.DESCRIBE_INSTANCES.toActionString()); + } + + @Test + public void testGetInstance() { + assertEquals("compute:GetInstance", ComputeActions.GET_INSTANCE.toActionString()); + } + + @Test + public void testWildcard() { + assertEquals("compute:*", ComputeActions.ALL.toActionString()); + assertTrue(ComputeActions.ALL.isWildcard()); + } +} diff --git a/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/ConditionOperatorTest.java b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/ConditionOperatorTest.java new file mode 100644 index 000000000..100f9f0f2 --- /dev/null +++ b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/ConditionOperatorTest.java @@ -0,0 +1,42 @@ +package com.salesforce.multicloudj.iam.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +public class ConditionOperatorTest { + + @Test + public void testStringOperators() { + assertEquals("stringEquals", ConditionOperator.STRING_EQUALS.getValue()); + assertEquals("stringNotEquals", ConditionOperator.STRING_NOT_EQUALS.getValue()); + assertEquals("stringLike", ConditionOperator.STRING_LIKE.getValue()); + assertEquals("stringNotLike", ConditionOperator.STRING_NOT_LIKE.getValue()); + } + + @Test + public void testNumericOperators() { + assertEquals("numericEquals", ConditionOperator.NUMERIC_EQUALS.getValue()); + assertEquals("numericLessThan", ConditionOperator.NUMERIC_LESS_THAN.getValue()); + assertEquals("numericGreaterThan", ConditionOperator.NUMERIC_GREATER_THAN.getValue()); + } + + @Test + public void testDateOperators() { + assertEquals("dateEquals", ConditionOperator.DATE_EQUALS.getValue()); + assertEquals("dateLessThan", ConditionOperator.DATE_LESS_THAN.getValue()); + assertEquals("dateGreaterThan", ConditionOperator.DATE_GREATER_THAN.getValue()); + } + + @Test + public void testOtherOperators() { + assertEquals("bool", ConditionOperator.BOOL.getValue()); + assertEquals("ipAddress", ConditionOperator.IP_ADDRESS.getValue()); + assertEquals("notIpAddress", ConditionOperator.NOT_IP_ADDRESS.getValue()); + } + + @Test + public void testToString() { + assertEquals("stringEquals", ConditionOperator.STRING_EQUALS.toString()); + } +} diff --git a/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/EffectTest.java b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/EffectTest.java new file mode 100644 index 000000000..45ed4e87a --- /dev/null +++ b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/EffectTest.java @@ -0,0 +1,26 @@ +package com.salesforce.multicloudj.iam.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +public class EffectTest { + + @Test + public void testAllowEffect() { + assertEquals("Allow", Effect.ALLOW.getValue()); + assertEquals("Allow", Effect.ALLOW.toString()); + } + + @Test + public void testDenyEffect() { + assertEquals("Deny", Effect.DENY.getValue()); + assertEquals("Deny", Effect.DENY.toString()); + } + + @Test + public void testEnumValues() { + Effect[] effects = Effect.values(); + assertEquals(2, effects.length); + } +} diff --git a/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/IamActionsTest.java b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/IamActionsTest.java new file mode 100644 index 000000000..f4227c3f6 --- /dev/null +++ b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/IamActionsTest.java @@ -0,0 +1,55 @@ +package com.salesforce.multicloudj.iam.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +public class IamActionsTest { + + @Test + public void testAssumeRole() { + assertEquals("iam:AssumeRole", IamActions.ASSUME_ROLE.toActionString()); + } + + @Test + public void testCreateRole() { + assertEquals("iam:CreateRole", IamActions.CREATE_ROLE.toActionString()); + } + + @Test + public void testDeleteRole() { + assertEquals("iam:DeleteRole", IamActions.DELETE_ROLE.toActionString()); + } + + @Test + public void testGetRole() { + assertEquals("iam:GetRole", IamActions.GET_ROLE.toActionString()); + } + + @Test + public void testAttachRolePolicy() { + assertEquals("iam:AttachRolePolicy", IamActions.ATTACH_ROLE_POLICY.toActionString()); + } + + @Test + public void testDetachRolePolicy() { + assertEquals("iam:DetachRolePolicy", IamActions.DETACH_ROLE_POLICY.toActionString()); + } + + @Test + public void testPutRolePolicy() { + assertEquals("iam:PutRolePolicy", IamActions.PUT_ROLE_POLICY.toActionString()); + } + + @Test + public void testGetRolePolicy() { + assertEquals("iam:GetRolePolicy", IamActions.GET_ROLE_POLICY.toActionString()); + } + + @Test + public void testWildcard() { + assertEquals("iam:*", IamActions.ALL.toActionString()); + assertTrue(IamActions.ALL.isWildcard()); + } +} diff --git a/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/PolicyDocumentTest.java b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/PolicyDocumentTest.java index c2bfbdc42..61609950b 100644 --- a/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/PolicyDocumentTest.java +++ b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/PolicyDocumentTest.java @@ -24,12 +24,12 @@ public void testPolicyDocumentBuilder() { .statement( Statement.builder() .sid("StorageAccess") - .effect("Allow") - .action("storage:GetObject") - .action("storage:PutObject") + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .action(StorageActions.PUT_OBJECT) .principal("arn:aws:iam::123456789012:user/ExampleUser") .resource("storage://my-bucket/*") - .condition("StringEquals", "aws:RequestedRegion", "us-west-2") + .condition(ConditionOperator.STRING_EQUALS, "aws:RequestedRegion", "us-west-2") .build()) .build(); @@ -38,15 +38,18 @@ public void testPolicyDocumentBuilder() { Statement statement = policy.getStatements().get(0); assertEquals("StorageAccess", statement.getSid()); - assertEquals("Allow", statement.getEffect()); - assertEquals(Arrays.asList("storage:GetObject", "storage:PutObject"), statement.getActions()); + assertEquals(Effect.ALLOW, statement.getEffect()); + assertEquals(2, statement.getActions().size()); + assertEquals(StorageActions.GET_OBJECT, statement.getActions().get(0)); + assertEquals(StorageActions.PUT_OBJECT, statement.getActions().get(1)); assertEquals( Arrays.asList("arn:aws:iam::123456789012:user/ExampleUser"), statement.getPrincipals()); assertEquals(Arrays.asList("storage://my-bucket/*"), statement.getResources()); - assertTrue(statement.getConditions().containsKey("StringEquals")); + assertTrue(statement.getConditions().containsKey(ConditionOperator.STRING_EQUALS)); assertEquals( - "us-west-2", statement.getConditions().get("StringEquals").get("aws:RequestedRegion")); + "us-west-2", + statement.getConditions().get(ConditionOperator.STRING_EQUALS).get("aws:RequestedRegion")); } @Test @@ -58,15 +61,15 @@ public void testMultipleStatements() { .statement( Statement.builder() .sid("ReadAccess") - .effect("Allow") - .action("storage:GetObject") + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) .resource("storage://my-bucket/*") .build()) .statement( Statement.builder() .sid("WriteAccess") - .effect("Allow") - .action("storage:PutObject") + .effect(Effect.ALLOW) + .action(StorageActions.PUT_OBJECT) .resource("storage://my-bucket/*") .build()) .build(); @@ -93,8 +96,8 @@ public void testOptionalVersionBuildsSuccessfully() { .statement( Statement.builder() .sid("TestStatement") - .effect("Allow") - .action("storage:GetObject") + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) .resource("storage://test-bucket/*") .build()) .build(); @@ -111,7 +114,10 @@ public void testStatementWithoutEffectThrowsException() { .name("TestPolicy") .version(TEST_VERSION) .statement( - Statement.builder().sid("TestStatement").action("storage:GetObject").build()) + Statement.builder() + .sid("TestStatement") + .action(StorageActions.GET_OBJECT) + .build()) .build(); }); } @@ -124,7 +130,7 @@ public void testStatementWithoutActionsThrowsException() { PolicyDocument.builder() .name("TestPolicy") .version(TEST_VERSION) - .statement(Statement.builder().sid("TestStatement").effect("Allow").build()) + .statement(Statement.builder().sid("TestStatement").effect(Effect.ALLOW).build()) .build(); }); } @@ -138,11 +144,11 @@ public void testBuilderMethodsWithMultipleValues() { .statement( Statement.builder() .sid("TestStatement") - .effect("Allow") - .action("storage:GetObject") - .action("storage:PutObject") - .action("storage:DeleteObject") - .action("storage:ListObjects") + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .action(StorageActions.PUT_OBJECT) + .action(StorageActions.DELETE_OBJECT) + .action(StorageActions.LIST_BUCKET) .resource("storage://bucket1/*") .resource("storage://bucket2/*") .resource("storage://bucket3/*") @@ -151,8 +157,11 @@ public void testBuilderMethodsWithMultipleValues() { .principal("principal2") .principal("principal3") .principal("principal4") - .condition("StringEquals", "aws:RequestedRegion", "us-west-2") - .condition("DateGreaterThan", "aws:CurrentTime", "2024-01-01T00:00:00Z") + .condition(ConditionOperator.STRING_EQUALS, "aws:RequestedRegion", "us-west-2") + .condition( + ConditionOperator.DATE_GREATER_THAN, + "aws:CurrentTime", + "2024-01-01T00:00:00Z") .build()) .build(); @@ -160,10 +169,10 @@ public void testBuilderMethodsWithMultipleValues() { // Test actions assertEquals(4, statement.getActions().size()); - assertTrue(statement.getActions().contains("storage:GetObject")); - assertTrue(statement.getActions().contains("storage:PutObject")); - assertTrue(statement.getActions().contains("storage:DeleteObject")); - assertTrue(statement.getActions().contains("storage:ListObjects")); + assertTrue(statement.getActions().contains(StorageActions.GET_OBJECT)); + assertTrue(statement.getActions().contains(StorageActions.PUT_OBJECT)); + assertTrue(statement.getActions().contains(StorageActions.DELETE_OBJECT)); + assertTrue(statement.getActions().contains(StorageActions.LIST_BUCKET)); // Test resources assertEquals(4, statement.getResources().size()); @@ -180,8 +189,8 @@ public void testBuilderMethodsWithMultipleValues() { assertTrue(statement.getPrincipals().contains("principal4")); // Test conditions - assertTrue(statement.getConditions().containsKey("StringEquals")); - assertTrue(statement.getConditions().containsKey("DateGreaterThan")); + assertTrue(statement.getConditions().containsKey(ConditionOperator.STRING_EQUALS)); + assertTrue(statement.getConditions().containsKey(ConditionOperator.DATE_GREATER_THAN)); } @Test @@ -194,8 +203,8 @@ public void testAddNullStatement() { .statement( Statement.builder() .sid("ValidStatement") - .effect("Allow") - .action("storage:GetObject") + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) .resource("storage://test-bucket/*") .build()) .build(); diff --git a/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/StatementTest.java b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/StatementTest.java index 160f163e6..808eeb4b3 100644 --- a/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/StatementTest.java +++ b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/StatementTest.java @@ -18,24 +18,27 @@ public void testStatementBuilder() { Statement statement = Statement.builder() .sid("TestStatement") - .effect("Allow") - .action("storage:GetObject") - .action("storage:PutObject") + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .action(StorageActions.PUT_OBJECT) .resource("storage://my-bucket/*") .principal("arn:aws:iam::123456789012:user/TestUser") - .condition("StringEquals", "aws:RequestedRegion", "us-west-2") + .condition(ConditionOperator.STRING_EQUALS, "aws:RequestedRegion", "us-west-2") .build(); assertEquals("TestStatement", statement.getSid()); - assertEquals("Allow", statement.getEffect()); - assertEquals(Arrays.asList("storage:GetObject", "storage:PutObject"), statement.getActions()); + assertEquals(Effect.ALLOW, statement.getEffect()); + assertEquals(2, statement.getActions().size()); + assertEquals(StorageActions.GET_OBJECT, statement.getActions().get(0)); + assertEquals(StorageActions.PUT_OBJECT, statement.getActions().get(1)); assertEquals(Arrays.asList("storage://my-bucket/*"), statement.getResources()); assertEquals( Arrays.asList("arn:aws:iam::123456789012:user/TestUser"), statement.getPrincipals()); - assertTrue(statement.getConditions().containsKey("StringEquals")); + assertTrue(statement.getConditions().containsKey(ConditionOperator.STRING_EQUALS)); assertEquals( - "us-west-2", statement.getConditions().get("StringEquals").get("aws:RequestedRegion")); + "us-west-2", + statement.getConditions().get(ConditionOperator.STRING_EQUALS).get("aws:RequestedRegion")); } @Test @@ -43,14 +46,15 @@ public void testStatementBuilderMinimal() { Statement statement = Statement.builder() .sid("MinimalStatement") - .effect("Deny") - .action("storage:DeleteObject") + .effect(Effect.DENY) + .action(StorageActions.DELETE_OBJECT) .resource("storage://sensitive-bucket/*") .build(); assertEquals("MinimalStatement", statement.getSid()); - assertEquals("Deny", statement.getEffect()); - assertEquals(Arrays.asList("storage:DeleteObject"), statement.getActions()); + assertEquals(Effect.DENY, statement.getEffect()); + assertEquals(1, statement.getActions().size()); + assertEquals(StorageActions.DELETE_OBJECT, statement.getActions().get(0)); assertEquals(Arrays.asList("storage://sensitive-bucket/*"), statement.getResources()); assertTrue(statement.getPrincipals().isEmpty()); assertTrue(statement.getConditions().isEmpty()); @@ -63,8 +67,8 @@ public void testStatementBuilderMultipleResources() { Statement statement = Statement.builder() .sid("MultiResourceStatement") - .effect("Allow") - .action("storage:GetObject") + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) .resource("storage://bucket1/*") .resource("storage://bucket2/*") .build(); @@ -81,8 +85,8 @@ public void testStatementBuilderMultiplePrincipals() { Statement statement = Statement.builder() .sid("MultiPrincipalStatement") - .effect("Allow") - .action("storage:GetObject") + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) .resource("storage://shared-bucket/*") .principal("arn:aws:iam::123456789012:user/User1") .principal("arn:aws:iam::123456789012:user/User2") @@ -96,33 +100,35 @@ public void testStatementBuilderMultipleConditions() { Statement statement = Statement.builder() .sid("MultiConditionStatement") - .effect("Allow") - .action("storage:GetObject") + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) .resource("storage://conditional-bucket/*") - .condition("StringEquals", "aws:RequestedRegion", "us-west-2") - .condition("DateGreaterThan", "aws:CurrentTime", "2024-01-01T00:00:00Z") + .condition(ConditionOperator.STRING_EQUALS, "aws:RequestedRegion", "us-west-2") + .condition( + ConditionOperator.DATE_GREATER_THAN, "aws:CurrentTime", "2024-01-01T00:00:00Z") .build(); - assertTrue(statement.getConditions().containsKey("StringEquals")); - assertTrue(statement.getConditions().containsKey("DateGreaterThan")); + assertTrue(statement.getConditions().containsKey(ConditionOperator.STRING_EQUALS)); + assertTrue(statement.getConditions().containsKey(ConditionOperator.DATE_GREATER_THAN)); assertEquals( - "us-west-2", statement.getConditions().get("StringEquals").get("aws:RequestedRegion")); + "us-west-2", + statement.getConditions().get(ConditionOperator.STRING_EQUALS).get("aws:RequestedRegion")); assertEquals( "2024-01-01T00:00:00Z", - statement.getConditions().get("DateGreaterThan").get("aws:CurrentTime")); + statement.getConditions().get(ConditionOperator.DATE_GREATER_THAN).get("aws:CurrentTime")); } @Test public void testStatementWithoutSid() { Statement statement = Statement.builder() - .effect("Allow") - .action("storage:GetObject") + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) .resource("storage://no-sid-bucket/*") .build(); assertNull(statement.getSid()); - assertEquals("Allow", statement.getEffect()); + assertEquals(Effect.ALLOW, statement.getEffect()); } @Test @@ -141,7 +147,7 @@ public void testStatementWithoutEffectThrowsException() { () -> { Statement.builder() .sid("NoEffectStatement") - .action("storage:GetObject") + .action(StorageActions.GET_OBJECT) .resource("storage://test-bucket/*") .build(); }); @@ -154,34 +160,21 @@ public void testStatementWithoutActionsThrowsException() { () -> { Statement.builder() .sid("NoActionsStatement") - .effect("Allow") + .effect(Effect.ALLOW) .resource("storage://test-bucket/*") .build(); }); } @Test - public void testStatementWithEmptyEffect() { - assertThrows( - InvalidArgumentException.class, - () -> { - Statement.builder() - .sid("EmptyEffectStatement") - .effect("") - .action("storage:GetObject") - .build(); - }); - } - - @Test - public void testStatementWithWhitespaceEffect() { + public void testStatementWithNullAction() { assertThrows( InvalidArgumentException.class, () -> { Statement.builder() - .sid("WhitespaceEffectStatement") - .effect(" ") - .action("storage:GetObject") + .sid("NullActionStatement") + .effect(Effect.ALLOW) + .action((Action) null) .build(); }); } @@ -190,11 +183,8 @@ public void testStatementWithWhitespaceEffect() { public void testNullAndEmptyValueHandling() { Statement statement = Statement.builder() - .effect("Allow") - .action(null) - .action("") - .action(" ") - .action("storage:GetObject") + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) .resource(null) .resource("") .resource(" ") @@ -204,13 +194,13 @@ public void testNullAndEmptyValueHandling() { .principal(" ") .principal("valid-principal") .condition(null, "key", "value") - .condition("StringEquals", null, "value") - .condition("StringEquals", "key", null) - .condition("StringEquals", "aws:RequestedRegion", "us-west-2") + .condition(ConditionOperator.STRING_EQUALS, null, "value") + .condition(ConditionOperator.STRING_EQUALS, "key", null) + .condition(ConditionOperator.STRING_EQUALS, "aws:RequestedRegion", "us-west-2") .build(); assertEquals(1, statement.getActions().size()); - assertEquals("storage:GetObject", statement.getActions().get(0)); + assertEquals(StorageActions.GET_OBJECT, statement.getActions().get(0)); assertEquals(1, statement.getResources().size()); assertEquals("storage://test-bucket/*", statement.getResources().get(0)); @@ -219,51 +209,83 @@ public void testNullAndEmptyValueHandling() { assertEquals("valid-principal", statement.getPrincipals().get(0)); assertEquals(1, statement.getConditions().size()); - assertTrue(statement.getConditions().containsKey("StringEquals")); + assertTrue(statement.getConditions().containsKey(ConditionOperator.STRING_EQUALS)); assertEquals( - "us-west-2", statement.getConditions().get("StringEquals").get("aws:RequestedRegion")); + "us-west-2", + statement.getConditions().get(ConditionOperator.STRING_EQUALS).get("aws:RequestedRegion")); } @Test - public void testListMethodsWithNullValues() { - List principals = Arrays.asList("principal1", null, "", " ", "principal2"); - List actions = Arrays.asList("storage:GetObject", null, "", " ", "storage:PutObject"); - List resources = - Arrays.asList("storage://bucket1/*", null, "", " ", "storage://bucket2/*"); + public void testMixedServiceActions() { + Statement statement = + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .action(ComputeActions.CREATE_INSTANCE) + .action(IamActions.ASSUME_ROLE) + .build(); + + assertEquals(3, statement.getActions().size()); + assertEquals(StorageActions.GET_OBJECT, statement.getActions().get(0)); + assertEquals(ComputeActions.CREATE_INSTANCE, statement.getActions().get(1)); + assertEquals(IamActions.ASSUME_ROLE, statement.getActions().get(2)); + } + @Test + public void testWildcardActions() { Statement statement = Statement.builder() - .effect("Allow") - .actions(actions) - .resources(resources) - .principals(principals) + .effect(Effect.ALLOW) + .action(StorageActions.ALL) + .action(ComputeActions.ALL) + .action(IamActions.ALL) .build(); - assertEquals(2, statement.getActions().size()); - assertTrue(statement.getActions().contains("storage:GetObject")); - assertTrue(statement.getActions().contains("storage:PutObject")); + assertEquals(3, statement.getActions().size()); + assertTrue(statement.getActions().get(0).isWildcard()); + assertTrue(statement.getActions().get(1).isWildcard()); + assertTrue(statement.getActions().get(2).isWildcard()); + } - assertEquals(2, statement.getResources().size()); - assertTrue(statement.getResources().contains("storage://bucket1/*")); - assertTrue(statement.getResources().contains("storage://bucket2/*")); + @Test + public void testCustomAction() { + Action customAction = Action.of("customService:CustomOperation"); + Statement statement = Statement.builder().effect(Effect.ALLOW).action(customAction).build(); - assertEquals(2, statement.getPrincipals().size()); - assertTrue(statement.getPrincipals().contains("principal1")); - assertTrue(statement.getPrincipals().contains("principal2")); + assertEquals(1, statement.getActions().size()); + assertEquals("customService:CustomOperation", statement.getActions().get(0).toActionString()); } @Test - public void testListMethodsWithNullLists() { - // Test that individual actions and resources are preserved even without using list methods + public void testGetActionsAsStrings() { Statement statement = Statement.builder() - .effect("Allow") - .action("storage:GetObject") - .resource("storage://test-bucket/*") + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .action(StorageActions.PUT_OBJECT) .build(); - assertEquals(1, statement.getActions().size()); - assertEquals(1, statement.getResources().size()); - assertTrue(statement.getPrincipals().isEmpty()); + List actionStrings = statement.getActionsAsStrings(); + assertEquals(2, actionStrings.size()); + assertEquals("storage:GetObject", actionStrings.get(0)); + assertEquals("storage:PutObject", actionStrings.get(1)); + } + + @Test + public void testGetConditionsAsStrings() { + Statement statement = + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .condition(ConditionOperator.STRING_EQUALS, "key1", "value1") + .condition(ConditionOperator.NUMERIC_LESS_THAN, "key2", 100) + .build(); + + var conditionStrings = statement.getConditionsAsStrings(); + assertEquals(2, conditionStrings.size()); + assertTrue(conditionStrings.containsKey("stringEquals")); + assertTrue(conditionStrings.containsKey("numericLessThan")); + assertEquals("value1", conditionStrings.get("stringEquals").get("key1")); + assertEquals(100, conditionStrings.get("numericLessThan").get("key2")); } } diff --git a/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/StorageActionsTest.java b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/StorageActionsTest.java new file mode 100644 index 000000000..7712e6a8d --- /dev/null +++ b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/StorageActionsTest.java @@ -0,0 +1,52 @@ +package com.salesforce.multicloudj.iam.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +public class StorageActionsTest { + + @Test + public void testGetObject() { + assertEquals("storage:GetObject", StorageActions.GET_OBJECT.toActionString()); + assertEquals("storage", StorageActions.GET_OBJECT.getService()); + assertEquals("GetObject", StorageActions.GET_OBJECT.getOperation()); + } + + @Test + public void testPutObject() { + assertEquals("storage:PutObject", StorageActions.PUT_OBJECT.toActionString()); + } + + @Test + public void testDeleteObject() { + assertEquals("storage:DeleteObject", StorageActions.DELETE_OBJECT.toActionString()); + } + + @Test + public void testListBucket() { + assertEquals("storage:ListBucket", StorageActions.LIST_BUCKET.toActionString()); + } + + @Test + public void testGetBucketLocation() { + assertEquals("storage:GetBucketLocation", StorageActions.GET_BUCKET_LOCATION.toActionString()); + } + + @Test + public void testCreateBucket() { + assertEquals("storage:CreateBucket", StorageActions.CREATE_BUCKET.toActionString()); + } + + @Test + public void testDeleteBucket() { + assertEquals("storage:DeleteBucket", StorageActions.DELETE_BUCKET.toActionString()); + } + + @Test + public void testWildcard() { + assertEquals("storage:*", StorageActions.ALL.toActionString()); + assertTrue(StorageActions.ALL.isWildcard()); + } +} diff --git a/iam/iam-gcp/src/main/java/com/salesforce/multicloudj/iam/gcp/GcpIam.java b/iam/iam-gcp/src/main/java/com/salesforce/multicloudj/iam/gcp/GcpIam.java index e482f5a66..590b8549d 100644 --- a/iam/iam-gcp/src/main/java/com/salesforce/multicloudj/iam/gcp/GcpIam.java +++ b/iam/iam-gcp/src/main/java/com/salesforce/multicloudj/iam/gcp/GcpIam.java @@ -21,9 +21,11 @@ import com.salesforce.multicloudj.common.gcp.CommonErrorCodeMapping; import com.salesforce.multicloudj.common.gcp.GcpConstants; import com.salesforce.multicloudj.iam.driver.AbstractIam; +import com.salesforce.multicloudj.iam.model.Action; import com.salesforce.multicloudj.iam.model.AttachInlinePolicyRequest; import com.salesforce.multicloudj.iam.model.CreateIdentityRequest; import com.salesforce.multicloudj.iam.model.DeleteIdentityRequest; +import com.salesforce.multicloudj.iam.model.Effect; import com.salesforce.multicloudj.iam.model.GetAttachedPoliciesRequest; import com.salesforce.multicloudj.iam.model.GetIdentityRequest; import com.salesforce.multicloudj.iam.model.GetInlinePolicyDetailsRequest; @@ -62,18 +64,6 @@ public GcpIam(Builder builder) { * is provided, it also grants the roles/iam.serviceAccountTokenCreator role to the specified * trusted principals, enabling them to impersonate this service account. * - * @param identityName the service account ID (e.g., "my-service-account"). This will be used to - * construct the full email: {identityName}@{project-id}.iam.gserviceaccount.com - * @param description optional description for the service account (can be null, defaults to empty - * string) - * @param tenantId the GCP project ID (e.g., "my-project-123") or full project resource name - * (e.g., "projects/my-project-123"). The "projects/" prefix is optional. - * @param region the region (not used in GCP IAM as service accounts are global resources) - * @param trustConfig optional trust configuration containing principals that should be granted - * the roles/iam.serviceAccountTokenCreator role. Principals can be specified as: - Service - * account email: "sa@project.iam.gserviceaccount.com" - Formatted member: - * "serviceAccount:sa@project.iam.gserviceaccount.com" - User: "user:user@example.com" - - * Group: "group:group@example.com" * @param request the request containing identity name, description, tenant ID, region, trust * config, and options * @return the service account email address (unique identifier) in the format: @@ -164,20 +154,27 @@ private String formatPrincipalAsMember(String principal) { } /** - * Attaches an inline policy to a resource. This implementation treats each action in the - * PolicyDocument statement as a GCP IAM role name and grants that role to the IAM member. The - * action values are used directly as role names (e.g., "roles/iam.serviceAccountUser", - * "roles/storage.objectViewer"). + * Attaches an inline policy to a resource. This implementation translates substrate-neutral + * actions from the PolicyDocument to GCP IAM roles and grants those roles to the IAM member via + * bindings. + * + *

Translation examples: + * + *

    + *
  • storage:GetObject → roles/storage.objectViewer + *
  • storage:PutObject → roles/storage.objectCreator + *
  • compute:CreateInstance → roles/compute.instanceAdmin.v1 + *
* *

Note: GCP IAM is deny-by-default: access is denied unless explicitly allowed via bindings. * - *

Note: This implementation only processes "Allow" statements. "Deny" statements are skipped - * because ProjectsClient only supports allow policies (bindings). Deny policies require the IAM - * v2 API (PoliciesClient) and are managed separately from allow policies. + *

Note: This implementation only processes "Allow" statements. "Deny" statements are not + * supported because ProjectsClient only supports allow policies (bindings). Deny policies require + * the IAM v2 API (PoliciesClient) and are managed separately from allow policies. * - * @param request the request; GCP uses identityName as member, tenantId as resource name (e.g. - * organizations/123, folders/456, projects/my-project). Policy document actions are treated - * as GCP IAM role names. + * @param request the substrate-neutral policy document + * @throws SubstrateSdkException if translation fails (unknown action, unsupported condition, + * etc.) */ @Override protected void doAttachInlinePolicy(AttachInlinePolicyRequest request) { @@ -201,13 +198,16 @@ protected void doAttachInlinePolicy(AttachInlinePolicyRequest request) { for (Statement statement : request.getPolicyDocument().getStatements()) { // Skip Deny statements: ProjectsClient only supports allow policies (bindings). // Deny policies require the IAM v2 API (PoliciesClient) and are managed separately. - if (!EFFECT_ALLOW.equalsIgnoreCase(statement.getEffect())) { + if (statement.getEffect() != Effect.ALLOW) { continue; } - // Treat each action as a GCP IAM role name - for (String action : statement.getActions()) { - policy = addBinding(policy, action, member); + // Translate substrate-neutral actions to GCP roles + List roles = GcpIamPolicyTranslator.translateActionsToRoles(statement); + + // Add binding for each translated role + for (String role : roles) { + policy = addBinding(policy, role, member); } } @@ -324,12 +324,20 @@ protected String doGetInlinePolicyDetails(GetInlinePolicyDetailsRequest request) // Build a PolicyDocument to represent this role binding // The version field is immaterial for GCP IAM policy document. + // Convert GCP role format (e.g., "roles/iam.serviceAccountUser") to substrate-neutral format + String actionString = + request.getRoleName().startsWith("roles/") + ? "gcp-role:" + request.getRoleName().substring("roles/".length()) + : request.getRoleName(); PolicyDocument policyDocument = PolicyDocument.builder() .name(request.getRoleName()) .version("") .statement( - Statement.builder().effect(EFFECT_ALLOW).action(request.getRoleName()).build()) + Statement.builder() + .effect(Effect.ALLOW) + .action(Action.of(actionString)) + .build()) .build(); // Convert PolicyDocument to JSON string using Jackson @@ -361,7 +369,7 @@ private String toJsonString(PolicyDocument policyDocument) { * "serviceAccount:my-sa@project.iam.gserviceaccount.com", "user:user@example.com", * "group:group@example.com") tenantId the resource name that owns the IAM policy. Examples * include: "organizations/123456789012", "folders/987654321098", "projects/my-project", - * "projects/my-project/topics/my-topic",, Can be any GCP resource that supports IAM policies. + * "projects/my-project/topics/my-topic", Can be any GCP resource that supports IAM policies. * region the region (optional for GCP) * @return a list of role names (e.g., "roles/iam.serviceAccountUser", * "roles/storage.objectViewer") @@ -391,13 +399,6 @@ protected List doGetAttachedPolicies(GetAttachedPoliciesRequest request) * Removes an inline policy (role) from an IAM member. In GCP, this removes the IAM member from * the specified role binding in the resource's IAM policy. * - * @param identityName the IAM member (e.g., - * "serviceAccount:my-sa@project.iam.gserviceaccount.com", "user:user@example.com", - * "group:group@example.com") - * @param policyName the role name to remove (e.g., "roles/iam.serviceAccountUser") - * @param tenantId the resource name that owns the IAM policy. Examples include: - * "organizations/123456789012", "folders/987654321098", "projects/my-project", - * "projects/my-project/topics/my-topic",, Can be any GCP resource that supports IAM policies. * @param request the request containing identity name, policy name, tenant ID, and region */ @Override @@ -505,13 +506,7 @@ private Policy removeBinding(Policy policy, String role, String member) { * operation cannot be undone. The method accepts either a service account ID or full email * address as input and constructs the appropriate resource name for the API call. * - * @param identityName the service account identifier to delete, which can be: - Service account - * ID: "my-service-account" - Full email: - * "my-service-account@project-id.iam.gserviceaccount.com" Both formats are accepted and will - * be normalized to the full resource name. - * @param tenantId the GCP project ID (e.g., "my-project-123") or full project resource name - * (e.g., "projects/my-project-123"). The "projects/" prefix is optional. - * @param region the region (not used in GCP IAM as service accounts are global resources) + * @param request the request containing identity name, tenant ID, and region * @throws ApiException if the service account is not found, access is denied, or deletion fails * (propagates to IamClient) */ @@ -535,11 +530,6 @@ protected void doDeleteIdentity(DeleteIdentityRequest request) { * the unique identifier. The method accepts either a service account ID or full email address as * input and constructs the appropriate resource name for the API call. * - * @param identityName the service account identifier, which can be: - Service account ID: - * "my-service-account" - Full email: "my-service-account@project-id.iam.gserviceaccount.com" - * Both formats are accepted and will be normalized to the full resource name. - * @param tenantId the GCP project ID (e.g., "my-project-123") or full project resource name - * (e.g., "projects/my-project-123"). The "projects/" prefix is optional. * @param request the request containing identity name, tenant ID, and region * @return the service account email address (unique identifier) in the format: * {account-id}@{project-id}.iam.gserviceaccount.com diff --git a/iam/iam-gcp/src/main/java/com/salesforce/multicloudj/iam/gcp/GcpIamPolicyTranslator.java b/iam/iam-gcp/src/main/java/com/salesforce/multicloudj/iam/gcp/GcpIamPolicyTranslator.java new file mode 100644 index 000000000..0767a8925 --- /dev/null +++ b/iam/iam-gcp/src/main/java/com/salesforce/multicloudj/iam/gcp/GcpIamPolicyTranslator.java @@ -0,0 +1,146 @@ +package com.salesforce.multicloudj.iam.gcp; + +import com.salesforce.multicloudj.common.exceptions.InvalidArgumentException; +import com.salesforce.multicloudj.common.exceptions.SubstrateSdkException; +import com.salesforce.multicloudj.iam.model.Action; +import com.salesforce.multicloudj.iam.model.ComputeActions; +import com.salesforce.multicloudj.iam.model.IamActions; +import com.salesforce.multicloudj.iam.model.Statement; +import com.salesforce.multicloudj.iam.model.StorageActions; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Translates substrate-neutral PolicyDocument actions to GCP IAM roles. + * + *

This translator converts substrate-neutral actions to GCP-specific IAM roles according to the + * translation rules defined in PolicyDocument documentation. + * + *

Translation rules: + * + *

    + *
  • Actions: storage:GetObject → roles/storage.objectViewer + *
  • Actions: storage:PutObject → roles/storage.objectCreator + *
  • Actions: compute:CreateInstance → roles/compute.instanceAdmin.v1 + *
  • Actions: iam:AssumeRole → roles/iam.serviceAccountUser + *
+ * + *

Note: GCP IAM uses role-based access control, not action-based like AWS. Each + * substrate-neutral action maps to a GCP predefined role. Multiple actions may result in multiple + * role bindings. + */ +public class GcpIamPolicyTranslator { + + // Action mappings: substrate-neutral → GCP role + private static final Map ACTION_TO_ROLE_MAPPINGS = + Map.ofEntries( + // Storage actions + Map.entry(StorageActions.GET_OBJECT, "roles/storage.objectViewer"), + Map.entry(StorageActions.PUT_OBJECT, "roles/storage.objectCreator"), + Map.entry(StorageActions.DELETE_OBJECT, "roles/storage.objectAdmin"), + Map.entry(StorageActions.LIST_BUCKET, "roles/storage.objectViewer"), + Map.entry(StorageActions.GET_BUCKET_LOCATION, "roles/storage.objectViewer"), + Map.entry(StorageActions.CREATE_BUCKET, "roles/storage.admin"), + Map.entry(StorageActions.DELETE_BUCKET, "roles/storage.admin"), + + // Compute actions + Map.entry(ComputeActions.CREATE_INSTANCE, "roles/compute.instanceAdmin.v1"), + Map.entry(ComputeActions.DELETE_INSTANCE, "roles/compute.instanceAdmin.v1"), + Map.entry(ComputeActions.START_INSTANCE, "roles/compute.instanceAdmin.v1"), + Map.entry(ComputeActions.STOP_INSTANCE, "roles/compute.instanceAdmin.v1"), + Map.entry(ComputeActions.DESCRIBE_INSTANCES, "roles/compute.viewer"), + Map.entry(ComputeActions.GET_INSTANCE, "roles/compute.viewer"), + + // IAM actions + Map.entry(IamActions.ASSUME_ROLE, "roles/iam.serviceAccountUser"), + Map.entry(IamActions.CREATE_ROLE, "roles/iam.serviceAccountAdmin"), + Map.entry(IamActions.DELETE_ROLE, "roles/iam.serviceAccountAdmin"), + Map.entry(IamActions.GET_ROLE, "roles/iam.serviceAccountViewer"), + Map.entry(IamActions.ATTACH_ROLE_POLICY, "roles/iam.serviceAccountAdmin"), + Map.entry(IamActions.DETACH_ROLE_POLICY, "roles/iam.serviceAccountAdmin"), + Map.entry(IamActions.PUT_ROLE_POLICY, "roles/iam.serviceAccountAdmin"), + Map.entry(IamActions.GET_ROLE_POLICY, "roles/iam.serviceAccountViewer")); + + /** + * Translates substrate-neutral actions from a statement to GCP IAM roles. + * + * @param statement the substrate-neutral statement + * @return list of GCP IAM roles + * @throws SubstrateSdkException if action is unknown or conditions are unsupported + */ + public static List translateActionsToRoles(Statement statement) { + if (statement.getEffect() == null) { + throw new InvalidArgumentException("Effect is required for GCP IAM policy statement"); + } + + // Check for unsupported conditions + if (statement.getConditions() != null && !statement.getConditions().isEmpty()) { + // GCP IAM v1 bindings support limited conditions via CEL expressions + // For now, we throw an error for any conditions as basic implementation + throw new InvalidArgumentException( + "GCP IAM policy conditions are not yet supported in substrate-neutral translation. " + + "Statement SID: " + + (statement.getSid() != null ? statement.getSid() : "unnamed") + + ". " + + "GCP requires IAM Conditions API (v2) with CEL expressions."); + } + + List roles = new ArrayList<>(); + for (Action action : statement.getActions()) { + String role = translateActionToRole(action); + if (!roles.contains(role)) { + roles.add(role); + } + } + return roles; + } + + /** + * Translates a single substrate-neutral action to a GCP IAM role. Supports wildcard actions like + * storage:*, compute:*, iam:*. + * + * @param action the substrate-neutral action + * @return GCP IAM role + * @throws SubstrateSdkException if action is unknown + */ + public static String translateActionToRole(Action action) { + // Handle wildcard actions (e.g., storage:*, compute:*, iam:*) + if (action.isWildcard()) { + String service = action.getService(); + switch (service) { + case "storage": + // For storage:*, grant the most comprehensive storage role + return "roles/storage.admin"; + case "compute": + // For compute:*, grant the most comprehensive compute role + return "roles/compute.admin"; + case "iam": + // For iam:*, grant the most comprehensive IAM role + return "roles/iam.serviceAccountAdmin"; + default: + throw new InvalidArgumentException( + "Unknown substrate-neutral service for wildcard action: " + + action.toActionString() + + ". " + + "Supported wildcard services: storage:*, compute:*, iam:*"); + } + } + + // Handle specific actions + String role = ACTION_TO_ROLE_MAPPINGS.get(action); + if (role == null) { + throw new InvalidArgumentException( + "Unknown substrate-neutral action: " + + action.toActionString() + + ". " + + "Supported actions: " + + ACTION_TO_ROLE_MAPPINGS.keySet().stream() + .map(Action::toActionString) + .collect(Collectors.joining(", ")) + + ", or wildcard actions: storage:*, compute:*, iam:*"); + } + return role; + } +} diff --git a/iam/iam-gcp/src/test/java/com/salesforce/multicloudj/iam/gcp/GcpIamIT.java b/iam/iam-gcp/src/test/java/com/salesforce/multicloudj/iam/gcp/GcpIamIT.java index 98fbb487e..3edbe6322 100644 --- a/iam/iam-gcp/src/test/java/com/salesforce/multicloudj/iam/gcp/GcpIamIT.java +++ b/iam/iam-gcp/src/test/java/com/salesforce/multicloudj/iam/gcp/GcpIamIT.java @@ -202,12 +202,13 @@ public String getTestPolicyEffect() { @Override public List getTestPolicyActions() { - return List.of("roles/storage.objectViewer", "roles/storage.objectCreator"); + // Use substrate-neutral actions that will be translated to GCP roles + return List.of("storage:GetObject", "storage:PutObject"); } @Override public String getTestPolicyName() { - return "roles/storage.objectViewer"; + return "storage:GetObject"; } @Override diff --git a/iam/iam-gcp/src/test/java/com/salesforce/multicloudj/iam/gcp/GcpIamPolicyTranslatorTest.java b/iam/iam-gcp/src/test/java/com/salesforce/multicloudj/iam/gcp/GcpIamPolicyTranslatorTest.java new file mode 100644 index 000000000..e682ce651 --- /dev/null +++ b/iam/iam-gcp/src/test/java/com/salesforce/multicloudj/iam/gcp/GcpIamPolicyTranslatorTest.java @@ -0,0 +1,409 @@ +package com.salesforce.multicloudj.iam.gcp; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.salesforce.multicloudj.common.exceptions.InvalidArgumentException; +import com.salesforce.multicloudj.iam.model.Action; +import com.salesforce.multicloudj.iam.model.ComputeActions; +import com.salesforce.multicloudj.iam.model.ConditionOperator; +import com.salesforce.multicloudj.iam.model.Effect; +import com.salesforce.multicloudj.iam.model.IamActions; +import com.salesforce.multicloudj.iam.model.Statement; +import com.salesforce.multicloudj.iam.model.StorageActions; +import java.util.List; +import org.junit.jupiter.api.Test; + +public class GcpIamPolicyTranslatorTest { + + @Test + void testTranslateStorageGetObjectAction() { + Statement statement = + Statement.builder().effect(Effect.ALLOW).action(StorageActions.GET_OBJECT).build(); + + List roles = GcpIamPolicyTranslator.translateActionsToRoles(statement); + + assertEquals(1, roles.size()); + assertEquals("roles/storage.objectViewer", roles.get(0)); + } + + @Test + void testTranslateStoragePutObjectAction() { + Statement statement = + Statement.builder().effect(Effect.ALLOW).action(StorageActions.PUT_OBJECT).build(); + + List roles = GcpIamPolicyTranslator.translateActionsToRoles(statement); + + assertEquals(1, roles.size()); + assertEquals("roles/storage.objectCreator", roles.get(0)); + } + + @Test + void testTranslateMultipleStorageActions() { + Statement statement = + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .action(StorageActions.PUT_OBJECT) + .action(StorageActions.DELETE_OBJECT) + .build(); + + List roles = GcpIamPolicyTranslator.translateActionsToRoles(statement); + + assertEquals(3, roles.size()); + assertTrue(roles.contains("roles/storage.objectViewer")); + assertTrue(roles.contains("roles/storage.objectCreator")); + assertTrue(roles.contains("roles/storage.objectAdmin")); + } + + @Test + void testTranslateComputeActions() { + Statement statement = + Statement.builder() + .effect(Effect.ALLOW) + .action(ComputeActions.CREATE_INSTANCE) + .action(ComputeActions.DELETE_INSTANCE) + .action(ComputeActions.GET_INSTANCE) + .build(); + + List roles = GcpIamPolicyTranslator.translateActionsToRoles(statement); + + assertEquals(2, roles.size()); // CreateInstance and DeleteInstance map to same role + assertTrue(roles.contains("roles/compute.instanceAdmin.v1")); + assertTrue(roles.contains("roles/compute.viewer")); + } + + @Test + void testTranslateIamActions() { + Statement statement = + Statement.builder() + .effect(Effect.ALLOW) + .action(IamActions.ASSUME_ROLE) + .action(IamActions.CREATE_ROLE) + .action(IamActions.GET_ROLE) + .build(); + + List roles = GcpIamPolicyTranslator.translateActionsToRoles(statement); + + assertEquals(3, roles.size()); + assertTrue(roles.contains("roles/iam.serviceAccountUser")); + assertTrue(roles.contains("roles/iam.serviceAccountAdmin")); + assertTrue(roles.contains("roles/iam.serviceAccountViewer")); + } + + @Test + void testTranslateDuplicateActionsReturnUniqueRoles() { + Statement statement = + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .action(StorageActions.LIST_BUCKET) // Also maps to objectViewer + .build(); + + List roles = GcpIamPolicyTranslator.translateActionsToRoles(statement); + + assertEquals(1, roles.size()); + assertEquals("roles/storage.objectViewer", roles.get(0)); + } + + @Test + void testTranslateActionToRoleStorageActions() { + assertEquals( + "roles/storage.objectViewer", + GcpIamPolicyTranslator.translateActionToRole(StorageActions.GET_OBJECT)); + assertEquals( + "roles/storage.objectCreator", + GcpIamPolicyTranslator.translateActionToRole(StorageActions.PUT_OBJECT)); + assertEquals( + "roles/storage.objectAdmin", + GcpIamPolicyTranslator.translateActionToRole(StorageActions.DELETE_OBJECT)); + assertEquals( + "roles/storage.admin", + GcpIamPolicyTranslator.translateActionToRole(StorageActions.CREATE_BUCKET)); + } + + @Test + void testTranslateActionToRoleComputeActions() { + assertEquals( + "roles/compute.instanceAdmin.v1", + GcpIamPolicyTranslator.translateActionToRole(ComputeActions.CREATE_INSTANCE)); + assertEquals( + "roles/compute.instanceAdmin.v1", + GcpIamPolicyTranslator.translateActionToRole(ComputeActions.DELETE_INSTANCE)); + assertEquals( + "roles/compute.viewer", + GcpIamPolicyTranslator.translateActionToRole(ComputeActions.GET_INSTANCE)); + } + + @Test + void testTranslateActionToRoleIamActions() { + assertEquals( + "roles/iam.serviceAccountUser", + GcpIamPolicyTranslator.translateActionToRole(IamActions.ASSUME_ROLE)); + assertEquals( + "roles/iam.serviceAccountAdmin", + GcpIamPolicyTranslator.translateActionToRole(IamActions.CREATE_ROLE)); + assertEquals( + "roles/iam.serviceAccountViewer", + GcpIamPolicyTranslator.translateActionToRole(IamActions.GET_ROLE)); + } + + @Test + void testTranslateUnknownActionThrowsException() { + Statement statement = + Statement.builder().effect(Effect.ALLOW).action(Action.of("unknown:Action")).build(); + + InvalidArgumentException exception = + assertThrows( + InvalidArgumentException.class, + () -> { + GcpIamPolicyTranslator.translateActionsToRoles(statement); + }); + + assertTrue(exception.getMessage().contains("Unknown substrate-neutral action: unknown:Action")); + } + + @Test + void testTranslateActionToRoleUnknownActionThrowsException() { + InvalidArgumentException exception = + assertThrows( + InvalidArgumentException.class, + () -> { + GcpIamPolicyTranslator.translateActionToRole(Action.of("invalid:Action")); + }); + + assertTrue(exception.getMessage().contains("Unknown substrate-neutral action: invalid:Action")); + } + + @Test + void testTranslateActionsToRolesWithConditionsThrowsException() { + Statement statement = + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .condition(ConditionOperator.STRING_EQUALS, "key", "value") + .build(); + + InvalidArgumentException exception = + assertThrows( + InvalidArgumentException.class, + () -> { + GcpIamPolicyTranslator.translateActionsToRoles(statement); + }); + + assertTrue(exception.getMessage().contains("GCP IAM policy conditions are not yet supported")); + } + + @Test + void testTranslateAllStorageActions() { + Statement statement = + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .action(StorageActions.PUT_OBJECT) + .action(StorageActions.DELETE_OBJECT) + .action(StorageActions.LIST_BUCKET) + .action(StorageActions.GET_BUCKET_LOCATION) + .action(StorageActions.CREATE_BUCKET) + .action(StorageActions.DELETE_BUCKET) + .build(); + + List roles = GcpIamPolicyTranslator.translateActionsToRoles(statement); + + // Verify all unique roles are present + assertTrue(roles.contains("roles/storage.objectViewer")); + assertTrue(roles.contains("roles/storage.objectCreator")); + assertTrue(roles.contains("roles/storage.objectAdmin")); + assertTrue(roles.contains("roles/storage.admin")); + } + + @Test + void testTranslateAllComputeActions() { + Statement statement = + Statement.builder() + .effect(Effect.ALLOW) + .action(ComputeActions.CREATE_INSTANCE) + .action(ComputeActions.DELETE_INSTANCE) + .action(ComputeActions.START_INSTANCE) + .action(ComputeActions.STOP_INSTANCE) + .action(ComputeActions.DESCRIBE_INSTANCES) + .action(ComputeActions.GET_INSTANCE) + .build(); + + List roles = GcpIamPolicyTranslator.translateActionsToRoles(statement); + + // Verify all unique roles are present + assertTrue(roles.contains("roles/compute.instanceAdmin.v1")); + assertTrue(roles.contains("roles/compute.viewer")); + } + + @Test + void testTranslateAllIamActions() { + Statement statement = + Statement.builder() + .effect(Effect.ALLOW) + .action(IamActions.ASSUME_ROLE) + .action(IamActions.CREATE_ROLE) + .action(IamActions.DELETE_ROLE) + .action(IamActions.GET_ROLE) + .action(IamActions.ATTACH_ROLE_POLICY) + .action(IamActions.DETACH_ROLE_POLICY) + .action(IamActions.PUT_ROLE_POLICY) + .action(IamActions.GET_ROLE_POLICY) + .build(); + + List roles = GcpIamPolicyTranslator.translateActionsToRoles(statement); + + // Verify all unique roles are present + assertTrue(roles.contains("roles/iam.serviceAccountUser")); + assertTrue(roles.contains("roles/iam.serviceAccountAdmin")); + assertTrue(roles.contains("roles/iam.serviceAccountViewer")); + } + + @Test + void testTranslateMixedServiceActions() { + Statement statement = + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .action(ComputeActions.CREATE_INSTANCE) + .action(IamActions.ASSUME_ROLE) + .build(); + + List roles = GcpIamPolicyTranslator.translateActionsToRoles(statement); + + assertEquals(3, roles.size()); + assertTrue(roles.contains("roles/storage.objectViewer")); + assertTrue(roles.contains("roles/compute.instanceAdmin.v1")); + assertTrue(roles.contains("roles/iam.serviceAccountUser")); + } + + @Test + void testTranslateWildcardStorageAction() { + Statement statement = + Statement.builder().effect(Effect.ALLOW).action(StorageActions.ALL).build(); + + List roles = GcpIamPolicyTranslator.translateActionsToRoles(statement); + + assertEquals(1, roles.size()); + assertEquals("roles/storage.admin", roles.get(0)); + } + + @Test + void testTranslateWildcardComputeAction() { + Statement statement = + Statement.builder().effect(Effect.ALLOW).action(ComputeActions.ALL).build(); + + List roles = GcpIamPolicyTranslator.translateActionsToRoles(statement); + + assertEquals(1, roles.size()); + assertEquals("roles/compute.admin", roles.get(0)); + } + + @Test + void testTranslateWildcardIamAction() { + Statement statement = Statement.builder().effect(Effect.ALLOW).action(IamActions.ALL).build(); + + List roles = GcpIamPolicyTranslator.translateActionsToRoles(statement); + + assertEquals(1, roles.size()); + assertEquals("roles/iam.serviceAccountAdmin", roles.get(0)); + } + + @Test + void testTranslateMixedWildcardAndSpecificActions() { + Statement statement = + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.ALL) + .action(ComputeActions.CREATE_INSTANCE) + .action(IamActions.GET_ROLE) + .build(); + + List roles = GcpIamPolicyTranslator.translateActionsToRoles(statement); + + assertEquals(3, roles.size()); + assertTrue(roles.contains("roles/storage.admin")); + assertTrue(roles.contains("roles/compute.instanceAdmin.v1")); + assertTrue(roles.contains("roles/iam.serviceAccountViewer")); + } + + @Test + void testTranslateMultipleWildcardActions() { + Statement statement = + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.ALL) + .action(ComputeActions.ALL) + .action(IamActions.ALL) + .build(); + + List roles = GcpIamPolicyTranslator.translateActionsToRoles(statement); + + assertEquals(3, roles.size()); + assertTrue(roles.contains("roles/storage.admin")); + assertTrue(roles.contains("roles/compute.admin")); + assertTrue(roles.contains("roles/iam.serviceAccountAdmin")); + } + + @Test + void testTranslateUnknownWildcardServiceThrowsException() { + Statement statement = + Statement.builder().effect(Effect.ALLOW).action(Action.of("unknown:*")).build(); + + InvalidArgumentException exception = + assertThrows( + InvalidArgumentException.class, + () -> { + GcpIamPolicyTranslator.translateActionsToRoles(statement); + }); + + assertTrue( + exception + .getMessage() + .contains("Unknown substrate-neutral service for wildcard action: unknown:*")); + assertTrue( + exception + .getMessage() + .contains("Supported wildcard services: storage:*, compute:*, iam:*")); + } + + @Test + void testTranslateActionToRoleWildcardStorage() { + assertEquals( + "roles/storage.admin", GcpIamPolicyTranslator.translateActionToRole(StorageActions.ALL)); + } + + @Test + void testTranslateActionToRoleWildcardCompute() { + assertEquals( + "roles/compute.admin", GcpIamPolicyTranslator.translateActionToRole(ComputeActions.ALL)); + } + + @Test + void testTranslateActionToRoleWildcardIam() { + assertEquals( + "roles/iam.serviceAccountAdmin", + GcpIamPolicyTranslator.translateActionToRole(IamActions.ALL)); + } + + @Test + void testTranslateNullEffectThrowsException() { + Statement mockStatement = mock(Statement.class); + when(mockStatement.getEffect()).thenReturn(null); + when(mockStatement.getActions()) + .thenReturn(java.util.Collections.singletonList(StorageActions.GET_OBJECT)); + + InvalidArgumentException exception = + assertThrows( + InvalidArgumentException.class, + () -> { + GcpIamPolicyTranslator.translateActionsToRoles(mockStatement); + }); + + assertEquals("Effect is required for GCP IAM policy statement", exception.getMessage()); + } +} diff --git a/iam/iam-gcp/src/test/java/com/salesforce/multicloudj/iam/gcp/GcpIamTest.java b/iam/iam-gcp/src/test/java/com/salesforce/multicloudj/iam/gcp/GcpIamTest.java index ea827e5f5..07fcd9641 100644 --- a/iam/iam-gcp/src/test/java/com/salesforce/multicloudj/iam/gcp/GcpIamTest.java +++ b/iam/iam-gcp/src/test/java/com/salesforce/multicloudj/iam/gcp/GcpIamTest.java @@ -41,12 +41,18 @@ import com.salesforce.multicloudj.common.exceptions.UnAuthorizedException; import com.salesforce.multicloudj.common.exceptions.UnSupportedOperationException; import com.salesforce.multicloudj.common.exceptions.UnknownException; +import com.salesforce.multicloudj.iam.model.Action; import com.salesforce.multicloudj.iam.model.AttachInlinePolicyRequest; +import com.salesforce.multicloudj.iam.model.ComputeActions; +import com.salesforce.multicloudj.iam.model.ConditionOperator; +import com.salesforce.multicloudj.iam.model.Effect; import com.salesforce.multicloudj.iam.model.GetAttachedPoliciesRequest; import com.salesforce.multicloudj.iam.model.GetInlinePolicyDetailsRequest; +import com.salesforce.multicloudj.iam.model.IamActions; import com.salesforce.multicloudj.iam.model.PolicyDocument; import com.salesforce.multicloudj.iam.model.RemovePolicyRequest; import com.salesforce.multicloudj.iam.model.Statement; +import com.salesforce.multicloudj.iam.model.StorageActions; import com.salesforce.multicloudj.iam.model.TrustConfiguration; import java.io.IOException; import java.util.List; @@ -151,13 +157,17 @@ void testDoAttachInlinePolicySuccess() { when(mockProjectsClient.setIamPolicy(any(SetIamPolicyRequest.class))) .thenReturn(existingPolicy); - // Create policy document + // Create policy document with substrate-neutral action PolicyDocument policyDocument = PolicyDocument.builder() .name("TestPolicy") .version("2024-01-01") .statement( - Statement.builder().sid("TestPolicy").effect("Allow").action(TEST_ROLE).build()) + Statement.builder() + .sid("TestPolicy") + .effect(Effect.ALLOW) + .action(IamActions.ASSUME_ROLE) // Translates to roles/iam.serviceAccountUser + .build()) .build(); // Execute @@ -181,10 +191,10 @@ void testDoAttachInlinePolicySuccess() { Policy updatedPolicy = setRequest.getPolicy(); Assertions.assertNotNull(updatedPolicy); - // Verify the new binding was added + // Verify the new binding was added (translated role) boolean foundBinding = false; for (Binding binding : updatedPolicy.getBindingsList()) { - if (binding.getRole().equals(TEST_ROLE)) { + if (binding.getRole().equals("roles/iam.serviceAccountUser")) { assertTrue(binding.getMembersList().contains(TEST_SERVICE_ACCOUNT)); foundBinding = true; } @@ -203,7 +213,11 @@ void testDoAttachInlinePolicyWithNullPolicy() { .name("TestPolicy") .version("2024-01-01") .statement( - Statement.builder().sid("TestPolicy").effect("Allow").action(TEST_ROLE).build()) + Statement.builder() + .sid("TestPolicy") + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) // Translates to roles/storage.objectViewer + .build()) .build(); AttachInlinePolicyRequest request = @@ -225,7 +239,7 @@ void testDoAttachInlinePolicyMergesExistingBinding() { Policy.newBuilder() .addBindings( Binding.newBuilder() - .setRole(TEST_ROLE) + .setRole("roles/iam.serviceAccountUser") .addMembers("serviceAccount:existing@test-project.iam.gserviceaccount.com") .build()) .build(); @@ -240,7 +254,11 @@ void testDoAttachInlinePolicyMergesExistingBinding() { .name("TestPolicy") .version("2024-01-01") .statement( - Statement.builder().sid("TestPolicy").effect("Allow").action(TEST_ROLE).build()) + Statement.builder() + .sid("TestPolicy") + .effect(Effect.ALLOW) + .action(IamActions.ASSUME_ROLE) // Translates to roles/iam.serviceAccountUser + .build()) .build(); AttachInlinePolicyRequest request = @@ -259,7 +277,7 @@ void testDoAttachInlinePolicyMergesExistingBinding() { Policy updatedPolicy = setRequestCaptor.getValue().getPolicy(); Binding updatedBinding = updatedPolicy.getBindingsList().stream() - .filter(b -> b.getRole().equals(TEST_ROLE)) + .filter(b -> b.getRole().equals("roles/iam.serviceAccountUser")) .findFirst() .orElse(null); @@ -273,15 +291,28 @@ void testDoAttachInlinePolicySkipsDenyStatements() { Policy existingPolicy = Policy.newBuilder().build(); when(mockProjectsClient.getIamPolicy(any(GetIamPolicyRequest.class))) .thenReturn(existingPolicy); + when(mockProjectsClient.setIamPolicy(any(SetIamPolicyRequest.class))) + .thenReturn(existingPolicy); PolicyDocument policyDocument = PolicyDocument.builder() .name("DenyPolicy") .version("2024-01-01") .statement( - Statement.builder().sid("DenyPolicy").effect("Deny").action(TEST_ROLE).build()) + Statement.builder() + .sid("DenyPolicy") + .effect(Effect.DENY) + .action(StorageActions.GET_OBJECT) + .build()) + .statement( + Statement.builder() + .sid("AllowPolicy") + .effect(Effect.ALLOW) + .action(StorageActions.PUT_OBJECT) + .build()) .build(); + // Verify: Deny statements are skipped, Allow statements are processed AttachInlinePolicyRequest request = AttachInlinePolicyRequest.builder() .policyDocument(policyDocument) @@ -291,9 +322,21 @@ void testDoAttachInlinePolicySkipsDenyStatements() { .build(); Assertions.assertDoesNotThrow(() -> gcpIam.doAttachInlinePolicy(request)); - // Verify: setIamPolicy should not be called since Deny statements are skipped and nothing - // changes - verify(mockProjectsClient, times(0)).setIamPolicy(any(SetIamPolicyRequest.class)); + verify(mockProjectsClient, times(1)).getIamPolicy(any(GetIamPolicyRequest.class)); + verify(mockProjectsClient, times(1)).setIamPolicy(any(SetIamPolicyRequest.class)); + + // Verify the policy was updated with only the Allow statement's role + ArgumentCaptor setRequestCaptor = + ArgumentCaptor.forClass(SetIamPolicyRequest.class); + verify(mockProjectsClient, times(1)).setIamPolicy(setRequestCaptor.capture()); + + SetIamPolicyRequest setRequest = setRequestCaptor.getValue(); + Policy updatedPolicy = setRequest.getPolicy(); + + // Should have only one binding for the Allow statement's role + assertEquals(1, updatedPolicy.getBindingsCount()); + assertEquals("roles/storage.objectCreator", updatedPolicy.getBindings(0).getRole()); + assertTrue(updatedPolicy.getBindings(0).getMembersList().contains(TEST_SERVICE_ACCOUNT)); } @Test @@ -1658,4 +1701,236 @@ void testDeleteIdentitySuccessfullyDeletesServiceAccount() { // Assert - Verify the method was called verify(mockIamClient, times(1)).deleteServiceAccount(any(DeleteServiceAccountRequest.class)); } + + @Test + void testAttachInlinePolicyWithStorageActions() { + Policy existingPolicy = Policy.newBuilder().build(); + when(mockProjectsClient.getIamPolicy(any(GetIamPolicyRequest.class))) + .thenReturn(existingPolicy); + when(mockProjectsClient.setIamPolicy(any(SetIamPolicyRequest.class))) + .thenReturn(existingPolicy); + + PolicyDocument policyDocument = + PolicyDocument.builder() + .version("2024-01-01") + .statement( + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .action(StorageActions.PUT_OBJECT) + .build()) + .build(); + + // policyDocument, TEST_TENANT_ID, TEST_REGION, TEST_SERVICE_ACCOUNT + gcpIam.doAttachInlinePolicy( + AttachInlinePolicyRequest.builder() + .policyDocument(policyDocument) + .tenantId(TEST_TENANT_ID) + .region(TEST_REGION) + .identityName(TEST_SERVICE_ACCOUNT) + .build()); + + ArgumentCaptor captor = ArgumentCaptor.forClass(SetIamPolicyRequest.class); + verify(mockProjectsClient, times(1)).setIamPolicy(captor.capture()); + + Policy updatedPolicy = captor.getValue().getPolicy(); + List roles = + updatedPolicy.getBindingsList().stream() + .map(Binding::getRole) + .collect(java.util.stream.Collectors.toList()); + + assertTrue(roles.contains("roles/storage.objectViewer")); + assertTrue(roles.contains("roles/storage.objectCreator")); + } + + @Test + void testAttachInlinePolicyWithComputeActions() { + Policy existingPolicy = Policy.newBuilder().build(); + when(mockProjectsClient.getIamPolicy(any(GetIamPolicyRequest.class))) + .thenReturn(existingPolicy); + when(mockProjectsClient.setIamPolicy(any(SetIamPolicyRequest.class))) + .thenReturn(existingPolicy); + + PolicyDocument policyDocument = + PolicyDocument.builder() + .version("2024-01-01") + .statement( + Statement.builder() + .effect(Effect.ALLOW) + .action(ComputeActions.CREATE_INSTANCE) + .action(ComputeActions.GET_INSTANCE) + .build()) + .build(); + + gcpIam.doAttachInlinePolicy( + AttachInlinePolicyRequest.builder() + .policyDocument(policyDocument) + .tenantId(TEST_TENANT_ID) + .region(TEST_REGION) + .identityName(TEST_SERVICE_ACCOUNT) + .build()); + + ArgumentCaptor captor = ArgumentCaptor.forClass(SetIamPolicyRequest.class); + verify(mockProjectsClient, times(1)).setIamPolicy(captor.capture()); + + Policy updatedPolicy = captor.getValue().getPolicy(); + List roles = + updatedPolicy.getBindingsList().stream() + .map(Binding::getRole) + .collect(java.util.stream.Collectors.toList()); + + assertTrue(roles.contains("roles/compute.instanceAdmin.v1")); + assertTrue(roles.contains("roles/compute.viewer")); + } + + @Test + void testAttachInlinePolicyWithIamActions() { + Policy existingPolicy = Policy.newBuilder().build(); + when(mockProjectsClient.getIamPolicy(any(GetIamPolicyRequest.class))) + .thenReturn(existingPolicy); + when(mockProjectsClient.setIamPolicy(any(SetIamPolicyRequest.class))) + .thenReturn(existingPolicy); + + PolicyDocument policyDocument = + PolicyDocument.builder() + .version("2024-01-01") + .statement( + Statement.builder().effect(Effect.ALLOW).action(IamActions.ASSUME_ROLE).build()) + .build(); + + // policyDocument, TEST_TENANT_ID, TEST_REGION, TEST_SERVICE_ACCOUNT + gcpIam.doAttachInlinePolicy( + AttachInlinePolicyRequest.builder() + .policyDocument(policyDocument) + .tenantId(TEST_TENANT_ID) + .region(TEST_REGION) + .identityName(TEST_SERVICE_ACCOUNT) + .build()); + + ArgumentCaptor captor = ArgumentCaptor.forClass(SetIamPolicyRequest.class); + verify(mockProjectsClient, times(1)).setIamPolicy(captor.capture()); + + Policy updatedPolicy = captor.getValue().getPolicy(); + Binding binding = updatedPolicy.getBindings(0); + assertEquals("roles/iam.serviceAccountUser", binding.getRole()); + assertTrue(binding.getMembersList().contains(TEST_SERVICE_ACCOUNT)); + } + + @Test + void testAttachInlinePolicyWithConditionsThrowsException() { + Policy existingPolicy = Policy.newBuilder().build(); + when(mockProjectsClient.getIamPolicy(any(GetIamPolicyRequest.class))) + .thenReturn(existingPolicy); + + PolicyDocument policyDocument = + PolicyDocument.builder() + .version("2024-01-01") + .statement( + Statement.builder() + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .condition(ConditionOperator.STRING_EQUALS, "key", "value") + .build()) + .build(); + + SubstrateSdkException exception = + assertThrows( + SubstrateSdkException.class, + () -> { + // policyDocument, TEST_TENANT_ID, TEST_REGION, TEST_SERVICE_ACCOUNT + gcpIam.doAttachInlinePolicy( + AttachInlinePolicyRequest.builder() + .policyDocument(policyDocument) + .tenantId(TEST_TENANT_ID) + .region(TEST_REGION) + .identityName(TEST_SERVICE_ACCOUNT) + .build()); + }); + + assertTrue(exception.getMessage().contains("GCP IAM policy conditions are not yet supported")); + verify(mockProjectsClient, times(1)).getIamPolicy(any(GetIamPolicyRequest.class)); + verify(mockProjectsClient, times(0)).setIamPolicy(any(SetIamPolicyRequest.class)); + } + + @Test + void testAttachInlinePolicyWithUnknownActionThrowsException() { + Policy existingPolicy = Policy.newBuilder().build(); + when(mockProjectsClient.getIamPolicy(any(GetIamPolicyRequest.class))) + .thenReturn(existingPolicy); + + PolicyDocument policyDocument = + PolicyDocument.builder() + .version("2024-01-01") + .statement( + Statement.builder() + .effect(Effect.ALLOW) + .action(Action.of("unknown:Action")) + .build()) + .build(); + + SubstrateSdkException exception = + assertThrows( + SubstrateSdkException.class, + () -> { + // policyDocument, TEST_TENANT_ID, TEST_REGION, TEST_SERVICE_ACCOUNT + gcpIam.doAttachInlinePolicy( + AttachInlinePolicyRequest.builder() + .policyDocument(policyDocument) + .tenantId(TEST_TENANT_ID) + .region(TEST_REGION) + .identityName(TEST_SERVICE_ACCOUNT) + .build()); + }); + + assertTrue(exception.getMessage().contains("Unknown substrate-neutral action: unknown:Action")); + verify(mockProjectsClient, times(1)).getIamPolicy(any(GetIamPolicyRequest.class)); + verify(mockProjectsClient, times(0)).setIamPolicy(any(SetIamPolicyRequest.class)); + } + + @Test + void testAttachInlinePolicyWithMultipleStatements() { + Policy existingPolicy = Policy.newBuilder().build(); + when(mockProjectsClient.getIamPolicy(any(GetIamPolicyRequest.class))) + .thenReturn(existingPolicy); + when(mockProjectsClient.setIamPolicy(any(SetIamPolicyRequest.class))) + .thenReturn(existingPolicy); + + PolicyDocument policyDocument = + PolicyDocument.builder() + .version("2024-01-01") + .statement( + Statement.builder() + .sid("StorageAccess") + .effect(Effect.ALLOW) + .action(StorageActions.GET_OBJECT) + .build()) + .statement( + Statement.builder() + .sid("ComputeAccess") + .effect(Effect.ALLOW) + .action(ComputeActions.CREATE_INSTANCE) + .build()) + .build(); + + // policyDocument, TEST_TENANT_ID, TEST_REGION, TEST_SERVICE_ACCOUNT + gcpIam.doAttachInlinePolicy( + AttachInlinePolicyRequest.builder() + .policyDocument(policyDocument) + .tenantId(TEST_TENANT_ID) + .region(TEST_REGION) + .identityName(TEST_SERVICE_ACCOUNT) + .build()); + + ArgumentCaptor captor = ArgumentCaptor.forClass(SetIamPolicyRequest.class); + verify(mockProjectsClient, times(1)).setIamPolicy(captor.capture()); + + Policy updatedPolicy = captor.getValue().getPolicy(); + List roles = + updatedPolicy.getBindingsList().stream() + .map(Binding::getRole) + .collect(java.util.stream.Collectors.toList()); + + assertTrue(roles.contains("roles/storage.objectViewer")); + assertTrue(roles.contains("roles/compute.instanceAdmin.v1")); + } } diff --git a/iam/iam-gcp/src/test/resources/__files/v3_projects_substrate-sdk-gcp-poc1getiampolicy.json b/iam/iam-gcp/src/test/resources/__files/GcpIamIT_testAttachInlinePolicy-POST-0.json similarity index 77% rename from iam/iam-gcp/src/test/resources/__files/v3_projects_substrate-sdk-gcp-poc1getiampolicy.json rename to iam/iam-gcp/src/test/resources/__files/GcpIamIT_testAttachInlinePolicy-POST-0.json index 845e80d47..af363ccc7 100644 --- a/iam/iam-gcp/src/test/resources/__files/v3_projects_substrate-sdk-gcp-poc1getiampolicy.json +++ b/iam/iam-gcp/src/test/resources/__files/GcpIamIT_testAttachInlinePolicy-POST-0.json @@ -1,8 +1,8 @@ { "version" : 1, - "etag" : "BwZFJCktcro=", + "etag" : "BwZMmdsi9KE=", "bindings" : [ { - "role" : "organizations/000000000000/roles/CustomRole499", + "role" : "organizations/540886916070/roles/CustomRole499", "members" : [ "group:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] }, { "role" : "projects/substrate-sdk-gcp-poc1/roles/bucket_reader_id", @@ -10,6 +10,9 @@ }, { "role" : "roles/artifactregistry.admin", "members" : [ "serviceAccount:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/artifactregistry.createOnPushRepoAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/artifactregistry.createOnPushWriter", "members" : [ "serviceAccount:user@domain.com" ] @@ -21,10 +24,19 @@ "members" : [ "serviceAccount:service-599653580068@gcp-sa-artifactregistry.iam.gserviceaccount.com" ] }, { "role" : "roles/browser", - "members" : [ "group:user@domain.com", "serviceAccount:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + "members" : [ "group:user@domain.com", "serviceAccount:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] }, { "role" : "roles/cloudaicompanion.serviceAgent", "members" : [ "serviceAccount:service-599653580068@gcp-sa-cloudaicompanion.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudbuild.builds.builder", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/cloudbuild.builds.editor", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudbuild.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-cloudbuild.iam.gserviceaccount.com" ] }, { "role" : "roles/cloudkms.admin", "members" : [ "serviceAccount:user@domain.com", "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com" ] @@ -33,7 +45,7 @@ "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/cloudkms.cryptoKeyEncrypterDecrypter", - "members" : [ "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com" ] + "members" : [ "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] }, { "role" : "roles/cloudkms.cryptoOperator", "members" : [ "serviceAccount:user@domain.com" ] @@ -42,13 +54,16 @@ "members" : [ "serviceAccount:service-599653580068@gcp-sa-cloudkms.iam.gserviceaccount.com" ] }, { "role" : "roles/cloudkms.viewer", - "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com" ] + "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] }, { "role" : "roles/compute.instanceAdmin.v1", "members" : [ "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/compute.serviceAgent", "members" : [ "serviceAccount:service-599653580068@compute-system.iam.gserviceaccount.com" ] + }, { + "role" : "roles/container.clusterAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/container.defaultNodeServiceAgent", "members" : [ "serviceAccount:service-599653580068@gcp-sa-gkenode.iam.gserviceaccount.com" ] @@ -66,13 +81,16 @@ "members" : [ "user:user@domain.com" ] }, { "role" : "roles/datastore.user", - "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] }, { "role" : "roles/dns.admin", - "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/editor", - "members" : [ "group:user@domain.com", "group:user@domain.com", "serviceAccount:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + "members" : [ "group:user@domain.com", "group:user@domain.com", "serviceAccount:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/firebase.admin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/firebase.managementServiceAgent", "members" : [ "serviceAccount:service-599653580068@gcp-sa-firebase.iam.gserviceaccount.com" ] @@ -85,6 +103,9 @@ }, { "role" : "roles/firestore.serviceAgent", "members" : [ "serviceAccount:service-599653580068@gcp-sa-firestore.iam.gserviceaccount.com" ] + }, { + "role" : "roles/gkehub.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-gkehub.iam.gserviceaccount.com" ] }, { "role" : "roles/iam.securityAdmin", "members" : [ "group:user@domain.com", "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] @@ -96,7 +117,7 @@ "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/iam.serviceAccountTokenCreator", - "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:firebase-adminsdk-fbsvc@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-service@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:firebase-adminsdk-fbsvc@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-service@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] }, { "role" : "roles/iam.serviceAccountUser", "members" : [ "serviceAccount:pcs-wis-service@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:test-chameleon-multisubstrate@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] @@ -106,9 +127,18 @@ }, { "role" : "roles/iam.workloadIdentityUser", "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-service@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:test-tags-iam@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/logging.logWriter", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/logging.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-logging.iam.gserviceaccount.com" ] }, { "role" : "roles/logging.viewer", "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/multiclustermetering.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-mcmetering.iam.gserviceaccount.com" ] }, { "role" : "roles/networkconnectivity.serviceAgent", "members" : [ "serviceAccount:service-599653580068@gcp-sa-networkconnectivity.iam.gserviceaccount.com" ] @@ -117,25 +147,25 @@ "members" : [ "serviceAccount:service-599653580068@gcp-sa-osconfig.iam.gserviceaccount.com" ] }, { "role" : "roles/owner", - "members" : [ "serviceAccount:test-chameleon-multisubstrate@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:zxie-test@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] + "members" : [ "serviceAccount:test-chameleon-multisubstrate@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:zxie-test@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com" ] }, { "role" : "roles/pubsub.admin", "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/pubsub.publisher", - "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/pubsub.serviceAgent", "members" : [ "serviceAccount:service-599653580068@gcp-sa-pubsub.iam.gserviceaccount.com" ] }, { "role" : "roles/pubsub.subscriber", - "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/pubsub.viewer", "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/resourcemanager.projectIamAdmin", - "members" : [ "group:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + "members" : [ "group:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] }, { "role" : "roles/resourcemanager.tagAdmin", "members" : [ "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] @@ -157,6 +187,12 @@ }, { "role" : "roles/secretmanager.admin", "members" : [ "group:user@domain.com" ] + }, { + "role" : "roles/serviceusage.serviceUsageAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] + }, { + "role" : "roles/serviceusage.serviceUsageConsumer", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/storage.admin", "members" : [ "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:my-gcp-sa-s3@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] @@ -165,7 +201,7 @@ "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/storage.objectAdmin", - "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/storage.objectCreator", "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] @@ -174,13 +210,16 @@ "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/storage.objectViewer", - "members" : [ "principalSet://iam.googleapis.com/projects/599653580068/locations/global/workloadIdentityPools/raphty-aws/attribute.aws_role/arn:aws:iam::000000000000:role/raphty-yz6qfcuppuxhyomcqhw1lgu", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:my-gcp-sa-s3@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + "members" : [ "principalSet://iam.googleapis.com/projects/599653580068/locations/global/workloadIdentityPools/raphty-aws/attribute.aws_role/arn:aws:iam::065351723461:role/raphty-yz6qfcuppuxhyomcqhw1lgu", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:my-gcp-sa-s3@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/storageinsights.serviceAgent", "members" : [ "serviceAccount:service-599653580068@gcp-sa-storageinsights.iam.gserviceaccount.com" ] }, { "role" : "roles/viewer", - "members" : [ "serviceAccount:user@domain.com", "serviceAccount:test-sa-1@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:test-sa-2@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + "members" : [ "serviceAccount:user@domain.com", "serviceAccount:test-sa-1@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:test-sa-2@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/websecurityscanner.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-websecurityscanner.iam.gserviceaccount.com" ] }, { "role" : "roles/workflows.admin", "members" : [ "user:user@domain.com" ] @@ -189,12 +228,12 @@ "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/workflows.invoker", - "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/workflows.serviceAgent", "members" : [ "serviceAccount:service-599653580068@gcp-sa-workflows.iam.gserviceaccount.com" ] }, { "role" : "roles/workflows.viewer", - "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] } ] } \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/__files/v3_projects_substrate-sdk-gcp-poc1setiampolicy.json b/iam/iam-gcp/src/test/resources/__files/GcpIamIT_testGetAttachedPolicies-POST-0.json similarity index 77% rename from iam/iam-gcp/src/test/resources/__files/v3_projects_substrate-sdk-gcp-poc1setiampolicy.json rename to iam/iam-gcp/src/test/resources/__files/GcpIamIT_testGetAttachedPolicies-POST-0.json index 845e80d47..af363ccc7 100644 --- a/iam/iam-gcp/src/test/resources/__files/v3_projects_substrate-sdk-gcp-poc1setiampolicy.json +++ b/iam/iam-gcp/src/test/resources/__files/GcpIamIT_testGetAttachedPolicies-POST-0.json @@ -1,8 +1,8 @@ { "version" : 1, - "etag" : "BwZFJCktcro=", + "etag" : "BwZMmdsi9KE=", "bindings" : [ { - "role" : "organizations/000000000000/roles/CustomRole499", + "role" : "organizations/540886916070/roles/CustomRole499", "members" : [ "group:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] }, { "role" : "projects/substrate-sdk-gcp-poc1/roles/bucket_reader_id", @@ -10,6 +10,9 @@ }, { "role" : "roles/artifactregistry.admin", "members" : [ "serviceAccount:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/artifactregistry.createOnPushRepoAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/artifactregistry.createOnPushWriter", "members" : [ "serviceAccount:user@domain.com" ] @@ -21,10 +24,19 @@ "members" : [ "serviceAccount:service-599653580068@gcp-sa-artifactregistry.iam.gserviceaccount.com" ] }, { "role" : "roles/browser", - "members" : [ "group:user@domain.com", "serviceAccount:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + "members" : [ "group:user@domain.com", "serviceAccount:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] }, { "role" : "roles/cloudaicompanion.serviceAgent", "members" : [ "serviceAccount:service-599653580068@gcp-sa-cloudaicompanion.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudbuild.builds.builder", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/cloudbuild.builds.editor", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudbuild.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-cloudbuild.iam.gserviceaccount.com" ] }, { "role" : "roles/cloudkms.admin", "members" : [ "serviceAccount:user@domain.com", "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com" ] @@ -33,7 +45,7 @@ "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/cloudkms.cryptoKeyEncrypterDecrypter", - "members" : [ "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com" ] + "members" : [ "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] }, { "role" : "roles/cloudkms.cryptoOperator", "members" : [ "serviceAccount:user@domain.com" ] @@ -42,13 +54,16 @@ "members" : [ "serviceAccount:service-599653580068@gcp-sa-cloudkms.iam.gserviceaccount.com" ] }, { "role" : "roles/cloudkms.viewer", - "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com" ] + "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] }, { "role" : "roles/compute.instanceAdmin.v1", "members" : [ "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/compute.serviceAgent", "members" : [ "serviceAccount:service-599653580068@compute-system.iam.gserviceaccount.com" ] + }, { + "role" : "roles/container.clusterAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/container.defaultNodeServiceAgent", "members" : [ "serviceAccount:service-599653580068@gcp-sa-gkenode.iam.gserviceaccount.com" ] @@ -66,13 +81,16 @@ "members" : [ "user:user@domain.com" ] }, { "role" : "roles/datastore.user", - "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] }, { "role" : "roles/dns.admin", - "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/editor", - "members" : [ "group:user@domain.com", "group:user@domain.com", "serviceAccount:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + "members" : [ "group:user@domain.com", "group:user@domain.com", "serviceAccount:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/firebase.admin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/firebase.managementServiceAgent", "members" : [ "serviceAccount:service-599653580068@gcp-sa-firebase.iam.gserviceaccount.com" ] @@ -85,6 +103,9 @@ }, { "role" : "roles/firestore.serviceAgent", "members" : [ "serviceAccount:service-599653580068@gcp-sa-firestore.iam.gserviceaccount.com" ] + }, { + "role" : "roles/gkehub.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-gkehub.iam.gserviceaccount.com" ] }, { "role" : "roles/iam.securityAdmin", "members" : [ "group:user@domain.com", "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] @@ -96,7 +117,7 @@ "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/iam.serviceAccountTokenCreator", - "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:firebase-adminsdk-fbsvc@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-service@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:firebase-adminsdk-fbsvc@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-service@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] }, { "role" : "roles/iam.serviceAccountUser", "members" : [ "serviceAccount:pcs-wis-service@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:test-chameleon-multisubstrate@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] @@ -106,9 +127,18 @@ }, { "role" : "roles/iam.workloadIdentityUser", "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-service@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:test-tags-iam@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/logging.logWriter", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/logging.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-logging.iam.gserviceaccount.com" ] }, { "role" : "roles/logging.viewer", "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/multiclustermetering.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-mcmetering.iam.gserviceaccount.com" ] }, { "role" : "roles/networkconnectivity.serviceAgent", "members" : [ "serviceAccount:service-599653580068@gcp-sa-networkconnectivity.iam.gserviceaccount.com" ] @@ -117,25 +147,25 @@ "members" : [ "serviceAccount:service-599653580068@gcp-sa-osconfig.iam.gserviceaccount.com" ] }, { "role" : "roles/owner", - "members" : [ "serviceAccount:test-chameleon-multisubstrate@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:zxie-test@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] + "members" : [ "serviceAccount:test-chameleon-multisubstrate@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:zxie-test@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com" ] }, { "role" : "roles/pubsub.admin", "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/pubsub.publisher", - "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/pubsub.serviceAgent", "members" : [ "serviceAccount:service-599653580068@gcp-sa-pubsub.iam.gserviceaccount.com" ] }, { "role" : "roles/pubsub.subscriber", - "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/pubsub.viewer", "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/resourcemanager.projectIamAdmin", - "members" : [ "group:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + "members" : [ "group:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] }, { "role" : "roles/resourcemanager.tagAdmin", "members" : [ "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] @@ -157,6 +187,12 @@ }, { "role" : "roles/secretmanager.admin", "members" : [ "group:user@domain.com" ] + }, { + "role" : "roles/serviceusage.serviceUsageAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] + }, { + "role" : "roles/serviceusage.serviceUsageConsumer", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/storage.admin", "members" : [ "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:my-gcp-sa-s3@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] @@ -165,7 +201,7 @@ "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/storage.objectAdmin", - "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/storage.objectCreator", "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] @@ -174,13 +210,16 @@ "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/storage.objectViewer", - "members" : [ "principalSet://iam.googleapis.com/projects/599653580068/locations/global/workloadIdentityPools/raphty-aws/attribute.aws_role/arn:aws:iam::000000000000:role/raphty-yz6qfcuppuxhyomcqhw1lgu", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:my-gcp-sa-s3@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + "members" : [ "principalSet://iam.googleapis.com/projects/599653580068/locations/global/workloadIdentityPools/raphty-aws/attribute.aws_role/arn:aws:iam::065351723461:role/raphty-yz6qfcuppuxhyomcqhw1lgu", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:my-gcp-sa-s3@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/storageinsights.serviceAgent", "members" : [ "serviceAccount:service-599653580068@gcp-sa-storageinsights.iam.gserviceaccount.com" ] }, { "role" : "roles/viewer", - "members" : [ "serviceAccount:user@domain.com", "serviceAccount:test-sa-1@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:test-sa-2@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + "members" : [ "serviceAccount:user@domain.com", "serviceAccount:test-sa-1@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:test-sa-2@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/websecurityscanner.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-websecurityscanner.iam.gserviceaccount.com" ] }, { "role" : "roles/workflows.admin", "members" : [ "user:user@domain.com" ] @@ -189,12 +228,12 @@ "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/workflows.invoker", - "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] }, { "role" : "roles/workflows.serviceAgent", "members" : [ "serviceAccount:service-599653580068@gcp-sa-workflows.iam.gserviceaccount.com" ] }, { "role" : "roles/workflows.viewer", - "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] } ] } \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/__files/GcpIamIT_testGetAttachedPolicies-POST-1.json b/iam/iam-gcp/src/test/resources/__files/GcpIamIT_testGetAttachedPolicies-POST-1.json new file mode 100644 index 000000000..af363ccc7 --- /dev/null +++ b/iam/iam-gcp/src/test/resources/__files/GcpIamIT_testGetAttachedPolicies-POST-1.json @@ -0,0 +1,239 @@ +{ + "version" : 1, + "etag" : "BwZMmdsi9KE=", + "bindings" : [ { + "role" : "organizations/540886916070/roles/CustomRole499", + "members" : [ "group:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "projects/substrate-sdk-gcp-poc1/roles/bucket_reader_id", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/artifactregistry.admin", + "members" : [ "serviceAccount:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/artifactregistry.createOnPushRepoAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/artifactregistry.createOnPushWriter", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/artifactregistry.reader", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/artifactregistry.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-artifactregistry.iam.gserviceaccount.com" ] + }, { + "role" : "roles/browser", + "members" : [ "group:user@domain.com", "serviceAccount:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/cloudaicompanion.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-cloudaicompanion.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudbuild.builds.builder", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/cloudbuild.builds.editor", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudbuild.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-cloudbuild.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudkms.admin", + "members" : [ "serviceAccount:user@domain.com", "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/cloudkms.cryptoKeyEncrypter", + "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudkms.cryptoKeyEncrypterDecrypter", + "members" : [ "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/cloudkms.cryptoOperator", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/cloudkms.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-cloudkms.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudkms.viewer", + "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/compute.instanceAdmin.v1", + "members" : [ "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/compute.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@compute-system.iam.gserviceaccount.com" ] + }, { + "role" : "roles/container.clusterAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/container.defaultNodeServiceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-gkenode.iam.gserviceaccount.com" ] + }, { + "role" : "roles/container.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@container-engine-robot.iam.gserviceaccount.com" ] + }, { + "role" : "roles/containerregistry.ServiceAgent", + "members" : [ "serviceAccount:service-599653580068@containerregistry.iam.gserviceaccount.com" ] + }, { + "role" : "roles/datastore.bulkAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/datastore.owner", + "members" : [ "user:user@domain.com" ] + }, { + "role" : "roles/datastore.user", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] + }, { + "role" : "roles/dns.admin", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/editor", + "members" : [ "group:user@domain.com", "group:user@domain.com", "serviceAccount:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/firebase.admin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/firebase.managementServiceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-firebase.iam.gserviceaccount.com" ] + }, { + "role" : "roles/firebase.sdkAdminServiceAgent", + "members" : [ "serviceAccount:firebase-adminsdk-fbsvc@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/firebaserules.system", + "members" : [ "serviceAccount:service-599653580068@firebase-rules.iam.gserviceaccount.com" ] + }, { + "role" : "roles/firestore.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-firestore.iam.gserviceaccount.com" ] + }, { + "role" : "roles/gkehub.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-gkehub.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.securityAdmin", + "members" : [ "group:user@domain.com", "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.serviceAccountAdmin", + "members" : [ "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/iam.serviceAccountOpenIdTokenCreator", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.serviceAccountTokenCreator", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:firebase-adminsdk-fbsvc@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-service@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/iam.serviceAccountUser", + "members" : [ "serviceAccount:pcs-wis-service@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:test-chameleon-multisubstrate@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.workloadIdentityPoolAdmin", + "members" : [ "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.workloadIdentityUser", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-service@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:test-tags-iam@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/logging.logWriter", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/logging.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-logging.iam.gserviceaccount.com" ] + }, { + "role" : "roles/logging.viewer", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/multiclustermetering.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-mcmetering.iam.gserviceaccount.com" ] + }, { + "role" : "roles/networkconnectivity.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-networkconnectivity.iam.gserviceaccount.com" ] + }, { + "role" : "roles/osconfig.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-osconfig.iam.gserviceaccount.com" ] + }, { + "role" : "roles/owner", + "members" : [ "serviceAccount:test-chameleon-multisubstrate@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:zxie-test@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/pubsub.admin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/pubsub.publisher", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/pubsub.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-pubsub.iam.gserviceaccount.com" ] + }, { + "role" : "roles/pubsub.subscriber", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/pubsub.viewer", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/resourcemanager.projectIamAdmin", + "members" : [ "group:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/resourcemanager.tagAdmin", + "members" : [ "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] + }, { + "role" : "roles/resourcemanager.tagUser", + "members" : [ "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/resourcemanager.tagViewer", + "members" : [ "user:user@domain.com" ] + }, { + "role" : "roles/run.admin", + "members" : [ "serviceAccount:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/run.builder", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/run.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@serverless-robot-prod.iam.gserviceaccount.com" ] + }, { + "role" : "roles/secretmanager.admin", + "members" : [ "group:user@domain.com" ] + }, { + "role" : "roles/serviceusage.serviceUsageAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] + }, { + "role" : "roles/serviceusage.serviceUsageConsumer", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.admin", + "members" : [ "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:my-gcp-sa-s3@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.bucketViewer", + "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.objectAdmin", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.objectCreator", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.objectCreator_withcond_959e4e2cb764fe9c3a0a", + "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.objectViewer", + "members" : [ "principalSet://iam.googleapis.com/projects/599653580068/locations/global/workloadIdentityPools/raphty-aws/attribute.aws_role/arn:aws:iam::065351723461:role/raphty-yz6qfcuppuxhyomcqhw1lgu", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:my-gcp-sa-s3@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storageinsights.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-storageinsights.iam.gserviceaccount.com" ] + }, { + "role" : "roles/viewer", + "members" : [ "serviceAccount:user@domain.com", "serviceAccount:test-sa-1@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:test-sa-2@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/websecurityscanner.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-websecurityscanner.iam.gserviceaccount.com" ] + }, { + "role" : "roles/workflows.admin", + "members" : [ "user:user@domain.com" ] + }, { + "role" : "roles/workflows.editor", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/workflows.invoker", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/workflows.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-workflows.iam.gserviceaccount.com" ] + }, { + "role" : "roles/workflows.viewer", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + } ] +} \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/__files/GcpIamIT_testGetInlinePolicyDetails-POST-0.json b/iam/iam-gcp/src/test/resources/__files/GcpIamIT_testGetInlinePolicyDetails-POST-0.json new file mode 100644 index 000000000..af363ccc7 --- /dev/null +++ b/iam/iam-gcp/src/test/resources/__files/GcpIamIT_testGetInlinePolicyDetails-POST-0.json @@ -0,0 +1,239 @@ +{ + "version" : 1, + "etag" : "BwZMmdsi9KE=", + "bindings" : [ { + "role" : "organizations/540886916070/roles/CustomRole499", + "members" : [ "group:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "projects/substrate-sdk-gcp-poc1/roles/bucket_reader_id", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/artifactregistry.admin", + "members" : [ "serviceAccount:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/artifactregistry.createOnPushRepoAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/artifactregistry.createOnPushWriter", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/artifactregistry.reader", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/artifactregistry.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-artifactregistry.iam.gserviceaccount.com" ] + }, { + "role" : "roles/browser", + "members" : [ "group:user@domain.com", "serviceAccount:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/cloudaicompanion.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-cloudaicompanion.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudbuild.builds.builder", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/cloudbuild.builds.editor", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudbuild.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-cloudbuild.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudkms.admin", + "members" : [ "serviceAccount:user@domain.com", "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/cloudkms.cryptoKeyEncrypter", + "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudkms.cryptoKeyEncrypterDecrypter", + "members" : [ "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/cloudkms.cryptoOperator", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/cloudkms.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-cloudkms.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudkms.viewer", + "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/compute.instanceAdmin.v1", + "members" : [ "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/compute.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@compute-system.iam.gserviceaccount.com" ] + }, { + "role" : "roles/container.clusterAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/container.defaultNodeServiceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-gkenode.iam.gserviceaccount.com" ] + }, { + "role" : "roles/container.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@container-engine-robot.iam.gserviceaccount.com" ] + }, { + "role" : "roles/containerregistry.ServiceAgent", + "members" : [ "serviceAccount:service-599653580068@containerregistry.iam.gserviceaccount.com" ] + }, { + "role" : "roles/datastore.bulkAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/datastore.owner", + "members" : [ "user:user@domain.com" ] + }, { + "role" : "roles/datastore.user", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] + }, { + "role" : "roles/dns.admin", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/editor", + "members" : [ "group:user@domain.com", "group:user@domain.com", "serviceAccount:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/firebase.admin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/firebase.managementServiceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-firebase.iam.gserviceaccount.com" ] + }, { + "role" : "roles/firebase.sdkAdminServiceAgent", + "members" : [ "serviceAccount:firebase-adminsdk-fbsvc@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/firebaserules.system", + "members" : [ "serviceAccount:service-599653580068@firebase-rules.iam.gserviceaccount.com" ] + }, { + "role" : "roles/firestore.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-firestore.iam.gserviceaccount.com" ] + }, { + "role" : "roles/gkehub.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-gkehub.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.securityAdmin", + "members" : [ "group:user@domain.com", "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.serviceAccountAdmin", + "members" : [ "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/iam.serviceAccountOpenIdTokenCreator", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.serviceAccountTokenCreator", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:firebase-adminsdk-fbsvc@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-service@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/iam.serviceAccountUser", + "members" : [ "serviceAccount:pcs-wis-service@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:test-chameleon-multisubstrate@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.workloadIdentityPoolAdmin", + "members" : [ "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.workloadIdentityUser", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-service@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:test-tags-iam@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/logging.logWriter", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/logging.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-logging.iam.gserviceaccount.com" ] + }, { + "role" : "roles/logging.viewer", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/multiclustermetering.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-mcmetering.iam.gserviceaccount.com" ] + }, { + "role" : "roles/networkconnectivity.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-networkconnectivity.iam.gserviceaccount.com" ] + }, { + "role" : "roles/osconfig.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-osconfig.iam.gserviceaccount.com" ] + }, { + "role" : "roles/owner", + "members" : [ "serviceAccount:test-chameleon-multisubstrate@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:zxie-test@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/pubsub.admin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/pubsub.publisher", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/pubsub.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-pubsub.iam.gserviceaccount.com" ] + }, { + "role" : "roles/pubsub.subscriber", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/pubsub.viewer", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/resourcemanager.projectIamAdmin", + "members" : [ "group:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/resourcemanager.tagAdmin", + "members" : [ "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] + }, { + "role" : "roles/resourcemanager.tagUser", + "members" : [ "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/resourcemanager.tagViewer", + "members" : [ "user:user@domain.com" ] + }, { + "role" : "roles/run.admin", + "members" : [ "serviceAccount:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/run.builder", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/run.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@serverless-robot-prod.iam.gserviceaccount.com" ] + }, { + "role" : "roles/secretmanager.admin", + "members" : [ "group:user@domain.com" ] + }, { + "role" : "roles/serviceusage.serviceUsageAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] + }, { + "role" : "roles/serviceusage.serviceUsageConsumer", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.admin", + "members" : [ "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:my-gcp-sa-s3@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.bucketViewer", + "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.objectAdmin", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.objectCreator", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.objectCreator_withcond_959e4e2cb764fe9c3a0a", + "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.objectViewer", + "members" : [ "principalSet://iam.googleapis.com/projects/599653580068/locations/global/workloadIdentityPools/raphty-aws/attribute.aws_role/arn:aws:iam::065351723461:role/raphty-yz6qfcuppuxhyomcqhw1lgu", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:my-gcp-sa-s3@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storageinsights.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-storageinsights.iam.gserviceaccount.com" ] + }, { + "role" : "roles/viewer", + "members" : [ "serviceAccount:user@domain.com", "serviceAccount:test-sa-1@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:test-sa-2@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/websecurityscanner.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-websecurityscanner.iam.gserviceaccount.com" ] + }, { + "role" : "roles/workflows.admin", + "members" : [ "user:user@domain.com" ] + }, { + "role" : "roles/workflows.editor", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/workflows.invoker", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/workflows.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-workflows.iam.gserviceaccount.com" ] + }, { + "role" : "roles/workflows.viewer", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + } ] +} \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/__files/GcpIamIT_testGetInlinePolicyDetails-POST-1.json b/iam/iam-gcp/src/test/resources/__files/GcpIamIT_testGetInlinePolicyDetails-POST-1.json new file mode 100644 index 000000000..af363ccc7 --- /dev/null +++ b/iam/iam-gcp/src/test/resources/__files/GcpIamIT_testGetInlinePolicyDetails-POST-1.json @@ -0,0 +1,239 @@ +{ + "version" : 1, + "etag" : "BwZMmdsi9KE=", + "bindings" : [ { + "role" : "organizations/540886916070/roles/CustomRole499", + "members" : [ "group:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "projects/substrate-sdk-gcp-poc1/roles/bucket_reader_id", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/artifactregistry.admin", + "members" : [ "serviceAccount:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/artifactregistry.createOnPushRepoAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/artifactregistry.createOnPushWriter", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/artifactregistry.reader", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/artifactregistry.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-artifactregistry.iam.gserviceaccount.com" ] + }, { + "role" : "roles/browser", + "members" : [ "group:user@domain.com", "serviceAccount:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/cloudaicompanion.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-cloudaicompanion.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudbuild.builds.builder", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/cloudbuild.builds.editor", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudbuild.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-cloudbuild.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudkms.admin", + "members" : [ "serviceAccount:user@domain.com", "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/cloudkms.cryptoKeyEncrypter", + "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudkms.cryptoKeyEncrypterDecrypter", + "members" : [ "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/cloudkms.cryptoOperator", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/cloudkms.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-cloudkms.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudkms.viewer", + "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/compute.instanceAdmin.v1", + "members" : [ "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/compute.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@compute-system.iam.gserviceaccount.com" ] + }, { + "role" : "roles/container.clusterAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/container.defaultNodeServiceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-gkenode.iam.gserviceaccount.com" ] + }, { + "role" : "roles/container.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@container-engine-robot.iam.gserviceaccount.com" ] + }, { + "role" : "roles/containerregistry.ServiceAgent", + "members" : [ "serviceAccount:service-599653580068@containerregistry.iam.gserviceaccount.com" ] + }, { + "role" : "roles/datastore.bulkAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/datastore.owner", + "members" : [ "user:user@domain.com" ] + }, { + "role" : "roles/datastore.user", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] + }, { + "role" : "roles/dns.admin", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/editor", + "members" : [ "group:user@domain.com", "group:user@domain.com", "serviceAccount:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/firebase.admin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/firebase.managementServiceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-firebase.iam.gserviceaccount.com" ] + }, { + "role" : "roles/firebase.sdkAdminServiceAgent", + "members" : [ "serviceAccount:firebase-adminsdk-fbsvc@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/firebaserules.system", + "members" : [ "serviceAccount:service-599653580068@firebase-rules.iam.gserviceaccount.com" ] + }, { + "role" : "roles/firestore.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-firestore.iam.gserviceaccount.com" ] + }, { + "role" : "roles/gkehub.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-gkehub.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.securityAdmin", + "members" : [ "group:user@domain.com", "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.serviceAccountAdmin", + "members" : [ "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/iam.serviceAccountOpenIdTokenCreator", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.serviceAccountTokenCreator", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:firebase-adminsdk-fbsvc@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-service@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/iam.serviceAccountUser", + "members" : [ "serviceAccount:pcs-wis-service@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:test-chameleon-multisubstrate@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.workloadIdentityPoolAdmin", + "members" : [ "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.workloadIdentityUser", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-service@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:test-tags-iam@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/logging.logWriter", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/logging.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-logging.iam.gserviceaccount.com" ] + }, { + "role" : "roles/logging.viewer", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/multiclustermetering.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-mcmetering.iam.gserviceaccount.com" ] + }, { + "role" : "roles/networkconnectivity.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-networkconnectivity.iam.gserviceaccount.com" ] + }, { + "role" : "roles/osconfig.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-osconfig.iam.gserviceaccount.com" ] + }, { + "role" : "roles/owner", + "members" : [ "serviceAccount:test-chameleon-multisubstrate@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:zxie-test@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/pubsub.admin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/pubsub.publisher", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/pubsub.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-pubsub.iam.gserviceaccount.com" ] + }, { + "role" : "roles/pubsub.subscriber", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/pubsub.viewer", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/resourcemanager.projectIamAdmin", + "members" : [ "group:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/resourcemanager.tagAdmin", + "members" : [ "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] + }, { + "role" : "roles/resourcemanager.tagUser", + "members" : [ "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/resourcemanager.tagViewer", + "members" : [ "user:user@domain.com" ] + }, { + "role" : "roles/run.admin", + "members" : [ "serviceAccount:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/run.builder", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/run.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@serverless-robot-prod.iam.gserviceaccount.com" ] + }, { + "role" : "roles/secretmanager.admin", + "members" : [ "group:user@domain.com" ] + }, { + "role" : "roles/serviceusage.serviceUsageAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] + }, { + "role" : "roles/serviceusage.serviceUsageConsumer", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.admin", + "members" : [ "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:my-gcp-sa-s3@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.bucketViewer", + "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.objectAdmin", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.objectCreator", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.objectCreator_withcond_959e4e2cb764fe9c3a0a", + "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.objectViewer", + "members" : [ "principalSet://iam.googleapis.com/projects/599653580068/locations/global/workloadIdentityPools/raphty-aws/attribute.aws_role/arn:aws:iam::065351723461:role/raphty-yz6qfcuppuxhyomcqhw1lgu", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:my-gcp-sa-s3@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storageinsights.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-storageinsights.iam.gserviceaccount.com" ] + }, { + "role" : "roles/viewer", + "members" : [ "serviceAccount:user@domain.com", "serviceAccount:test-sa-1@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:test-sa-2@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/websecurityscanner.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-websecurityscanner.iam.gserviceaccount.com" ] + }, { + "role" : "roles/workflows.admin", + "members" : [ "user:user@domain.com" ] + }, { + "role" : "roles/workflows.editor", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/workflows.invoker", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/workflows.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-workflows.iam.gserviceaccount.com" ] + }, { + "role" : "roles/workflows.viewer", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + } ] +} \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/__files/GcpIamIT_testRemovePolicy-POST-0.json b/iam/iam-gcp/src/test/resources/__files/GcpIamIT_testRemovePolicy-POST-0.json new file mode 100644 index 000000000..af363ccc7 --- /dev/null +++ b/iam/iam-gcp/src/test/resources/__files/GcpIamIT_testRemovePolicy-POST-0.json @@ -0,0 +1,239 @@ +{ + "version" : 1, + "etag" : "BwZMmdsi9KE=", + "bindings" : [ { + "role" : "organizations/540886916070/roles/CustomRole499", + "members" : [ "group:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "projects/substrate-sdk-gcp-poc1/roles/bucket_reader_id", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/artifactregistry.admin", + "members" : [ "serviceAccount:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/artifactregistry.createOnPushRepoAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/artifactregistry.createOnPushWriter", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/artifactregistry.reader", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/artifactregistry.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-artifactregistry.iam.gserviceaccount.com" ] + }, { + "role" : "roles/browser", + "members" : [ "group:user@domain.com", "serviceAccount:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/cloudaicompanion.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-cloudaicompanion.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudbuild.builds.builder", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/cloudbuild.builds.editor", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudbuild.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-cloudbuild.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudkms.admin", + "members" : [ "serviceAccount:user@domain.com", "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/cloudkms.cryptoKeyEncrypter", + "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudkms.cryptoKeyEncrypterDecrypter", + "members" : [ "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/cloudkms.cryptoOperator", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/cloudkms.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-cloudkms.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudkms.viewer", + "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/compute.instanceAdmin.v1", + "members" : [ "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/compute.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@compute-system.iam.gserviceaccount.com" ] + }, { + "role" : "roles/container.clusterAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/container.defaultNodeServiceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-gkenode.iam.gserviceaccount.com" ] + }, { + "role" : "roles/container.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@container-engine-robot.iam.gserviceaccount.com" ] + }, { + "role" : "roles/containerregistry.ServiceAgent", + "members" : [ "serviceAccount:service-599653580068@containerregistry.iam.gserviceaccount.com" ] + }, { + "role" : "roles/datastore.bulkAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/datastore.owner", + "members" : [ "user:user@domain.com" ] + }, { + "role" : "roles/datastore.user", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] + }, { + "role" : "roles/dns.admin", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/editor", + "members" : [ "group:user@domain.com", "group:user@domain.com", "serviceAccount:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/firebase.admin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/firebase.managementServiceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-firebase.iam.gserviceaccount.com" ] + }, { + "role" : "roles/firebase.sdkAdminServiceAgent", + "members" : [ "serviceAccount:firebase-adminsdk-fbsvc@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/firebaserules.system", + "members" : [ "serviceAccount:service-599653580068@firebase-rules.iam.gserviceaccount.com" ] + }, { + "role" : "roles/firestore.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-firestore.iam.gserviceaccount.com" ] + }, { + "role" : "roles/gkehub.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-gkehub.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.securityAdmin", + "members" : [ "group:user@domain.com", "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.serviceAccountAdmin", + "members" : [ "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/iam.serviceAccountOpenIdTokenCreator", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.serviceAccountTokenCreator", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:firebase-adminsdk-fbsvc@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-service@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/iam.serviceAccountUser", + "members" : [ "serviceAccount:pcs-wis-service@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:test-chameleon-multisubstrate@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.workloadIdentityPoolAdmin", + "members" : [ "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.workloadIdentityUser", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-service@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:test-tags-iam@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/logging.logWriter", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/logging.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-logging.iam.gserviceaccount.com" ] + }, { + "role" : "roles/logging.viewer", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/multiclustermetering.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-mcmetering.iam.gserviceaccount.com" ] + }, { + "role" : "roles/networkconnectivity.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-networkconnectivity.iam.gserviceaccount.com" ] + }, { + "role" : "roles/osconfig.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-osconfig.iam.gserviceaccount.com" ] + }, { + "role" : "roles/owner", + "members" : [ "serviceAccount:test-chameleon-multisubstrate@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:zxie-test@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/pubsub.admin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/pubsub.publisher", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/pubsub.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-pubsub.iam.gserviceaccount.com" ] + }, { + "role" : "roles/pubsub.subscriber", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/pubsub.viewer", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/resourcemanager.projectIamAdmin", + "members" : [ "group:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/resourcemanager.tagAdmin", + "members" : [ "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] + }, { + "role" : "roles/resourcemanager.tagUser", + "members" : [ "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/resourcemanager.tagViewer", + "members" : [ "user:user@domain.com" ] + }, { + "role" : "roles/run.admin", + "members" : [ "serviceAccount:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/run.builder", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/run.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@serverless-robot-prod.iam.gserviceaccount.com" ] + }, { + "role" : "roles/secretmanager.admin", + "members" : [ "group:user@domain.com" ] + }, { + "role" : "roles/serviceusage.serviceUsageAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] + }, { + "role" : "roles/serviceusage.serviceUsageConsumer", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.admin", + "members" : [ "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:my-gcp-sa-s3@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.bucketViewer", + "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.objectAdmin", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.objectCreator", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.objectCreator_withcond_959e4e2cb764fe9c3a0a", + "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.objectViewer", + "members" : [ "principalSet://iam.googleapis.com/projects/599653580068/locations/global/workloadIdentityPools/raphty-aws/attribute.aws_role/arn:aws:iam::065351723461:role/raphty-yz6qfcuppuxhyomcqhw1lgu", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:my-gcp-sa-s3@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storageinsights.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-storageinsights.iam.gserviceaccount.com" ] + }, { + "role" : "roles/viewer", + "members" : [ "serviceAccount:user@domain.com", "serviceAccount:test-sa-1@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:test-sa-2@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/websecurityscanner.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-websecurityscanner.iam.gserviceaccount.com" ] + }, { + "role" : "roles/workflows.admin", + "members" : [ "user:user@domain.com" ] + }, { + "role" : "roles/workflows.editor", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/workflows.invoker", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/workflows.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-workflows.iam.gserviceaccount.com" ] + }, { + "role" : "roles/workflows.viewer", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + } ] +} \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/__files/GcpIamIT_testRemovePolicy-POST-1.json b/iam/iam-gcp/src/test/resources/__files/GcpIamIT_testRemovePolicy-POST-1.json new file mode 100644 index 000000000..af363ccc7 --- /dev/null +++ b/iam/iam-gcp/src/test/resources/__files/GcpIamIT_testRemovePolicy-POST-1.json @@ -0,0 +1,239 @@ +{ + "version" : 1, + "etag" : "BwZMmdsi9KE=", + "bindings" : [ { + "role" : "organizations/540886916070/roles/CustomRole499", + "members" : [ "group:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "projects/substrate-sdk-gcp-poc1/roles/bucket_reader_id", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/artifactregistry.admin", + "members" : [ "serviceAccount:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/artifactregistry.createOnPushRepoAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/artifactregistry.createOnPushWriter", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/artifactregistry.reader", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/artifactregistry.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-artifactregistry.iam.gserviceaccount.com" ] + }, { + "role" : "roles/browser", + "members" : [ "group:user@domain.com", "serviceAccount:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/cloudaicompanion.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-cloudaicompanion.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudbuild.builds.builder", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/cloudbuild.builds.editor", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudbuild.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-cloudbuild.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudkms.admin", + "members" : [ "serviceAccount:user@domain.com", "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/cloudkms.cryptoKeyEncrypter", + "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudkms.cryptoKeyEncrypterDecrypter", + "members" : [ "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/cloudkms.cryptoOperator", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/cloudkms.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-cloudkms.iam.gserviceaccount.com" ] + }, { + "role" : "roles/cloudkms.viewer", + "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/compute.instanceAdmin.v1", + "members" : [ "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/compute.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@compute-system.iam.gserviceaccount.com" ] + }, { + "role" : "roles/container.clusterAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/container.defaultNodeServiceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-gkenode.iam.gserviceaccount.com" ] + }, { + "role" : "roles/container.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@container-engine-robot.iam.gserviceaccount.com" ] + }, { + "role" : "roles/containerregistry.ServiceAgent", + "members" : [ "serviceAccount:service-599653580068@containerregistry.iam.gserviceaccount.com" ] + }, { + "role" : "roles/datastore.bulkAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/datastore.owner", + "members" : [ "user:user@domain.com" ] + }, { + "role" : "roles/datastore.user", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] + }, { + "role" : "roles/dns.admin", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/editor", + "members" : [ "group:user@domain.com", "group:user@domain.com", "serviceAccount:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/firebase.admin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/firebase.managementServiceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-firebase.iam.gserviceaccount.com" ] + }, { + "role" : "roles/firebase.sdkAdminServiceAgent", + "members" : [ "serviceAccount:firebase-adminsdk-fbsvc@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/firebaserules.system", + "members" : [ "serviceAccount:service-599653580068@firebase-rules.iam.gserviceaccount.com" ] + }, { + "role" : "roles/firestore.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-firestore.iam.gserviceaccount.com" ] + }, { + "role" : "roles/gkehub.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-gkehub.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.securityAdmin", + "members" : [ "group:user@domain.com", "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.serviceAccountAdmin", + "members" : [ "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/iam.serviceAccountOpenIdTokenCreator", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.serviceAccountTokenCreator", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:firebase-adminsdk-fbsvc@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-service@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/iam.serviceAccountUser", + "members" : [ "serviceAccount:pcs-wis-service@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:test-chameleon-multisubstrate@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.workloadIdentityPoolAdmin", + "members" : [ "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/iam.workloadIdentityUser", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:pcs-wis-service@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:test-tags-iam@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/logging.logWriter", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/logging.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-logging.iam.gserviceaccount.com" ] + }, { + "role" : "roles/logging.viewer", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/multiclustermetering.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-mcmetering.iam.gserviceaccount.com" ] + }, { + "role" : "roles/networkconnectivity.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-networkconnectivity.iam.gserviceaccount.com" ] + }, { + "role" : "roles/osconfig.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-osconfig.iam.gserviceaccount.com" ] + }, { + "role" : "roles/owner", + "members" : [ "serviceAccount:test-chameleon-multisubstrate@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:zxie-test@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/pubsub.admin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/pubsub.publisher", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/pubsub.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-pubsub.iam.gserviceaccount.com" ] + }, { + "role" : "roles/pubsub.subscriber", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/pubsub.viewer", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/resourcemanager.projectIamAdmin", + "members" : [ "group:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/resourcemanager.tagAdmin", + "members" : [ "serviceAccount:pcs-wis-access@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:wisglobalrole@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] + }, { + "role" : "roles/resourcemanager.tagUser", + "members" : [ "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/resourcemanager.tagViewer", + "members" : [ "user:user@domain.com" ] + }, { + "role" : "roles/run.admin", + "members" : [ "serviceAccount:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/run.builder", + "members" : [ "serviceAccount:user@domain.com" ] + }, { + "role" : "roles/run.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@serverless-robot-prod.iam.gserviceaccount.com" ] + }, { + "role" : "roles/secretmanager.admin", + "members" : [ "group:user@domain.com" ] + }, { + "role" : "roles/serviceusage.serviceUsageAdmin", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com" ] + }, { + "role" : "roles/serviceusage.serviceUsageConsumer", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.admin", + "members" : [ "serviceAccount:bootstrap-terraform@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:my-gcp-sa-s3@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.bucketViewer", + "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.objectAdmin", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.objectCreator", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.objectCreator_withcond_959e4e2cb764fe9c3a0a", + "members" : [ "serviceAccount:raphty-aws@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storage.objectViewer", + "members" : [ "principalSet://iam.googleapis.com/projects/599653580068/locations/global/workloadIdentityPools/raphty-aws/attribute.aws_role/arn:aws:iam::065351723461:role/raphty-yz6qfcuppuxhyomcqhw1lgu", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:my-gcp-sa-s3@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/storageinsights.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-storageinsights.iam.gserviceaccount.com" ] + }, { + "role" : "roles/viewer", + "members" : [ "serviceAccount:user@domain.com", "serviceAccount:test-sa-1@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "serviceAccount:test-sa-2@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com", "user:user@domain.com" ] + }, { + "role" : "roles/websecurityscanner.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-websecurityscanner.iam.gserviceaccount.com" ] + }, { + "role" : "roles/workflows.admin", + "members" : [ "user:user@domain.com" ] + }, { + "role" : "roles/workflows.editor", + "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/workflows.invoker", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + }, { + "role" : "roles/workflows.serviceAgent", + "members" : [ "serviceAccount:service-599653580068@gcp-sa-workflows.iam.gserviceaccount.com" ] + }, { + "role" : "roles/workflows.viewer", + "members" : [ "serviceAccount:cha-pdtgeka5xmxny3szlqqj4tvwkq@sfdc-gffjhgy7cpswrysq98dnt9mbz.iam.gserviceaccount.com", "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] + } ] +} \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/mappings/gcpiamit_testattachinlinepolicy-post-0.json b/iam/iam-gcp/src/test/resources/mappings/gcpiamit_testattachinlinepolicy-post-0.json new file mode 100644 index 000000000..82fd71d71 --- /dev/null +++ b/iam/iam-gcp/src/test/resources/mappings/gcpiamit_testattachinlinepolicy-post-0.json @@ -0,0 +1,42 @@ +{ + "id" : "22d93c52-f67e-43c8-88db-3e484ac651e4", + "name" : "GcpIamIT_testAttachInlinePolicy-POST-0", + "request" : { + "urlPath" : "/v3/projects/substrate-sdk-gcp-poc1:getIamPolicy", + "method" : "POST", + "headers" : { + "X-Query-Param-Count" : { + "equalTo" : "1" + } + }, + "queryParameters" : { + "$alt" : { + "hasExactly" : [ { + "equalTo" : "json;enum-encoding=int" + } ] + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "GcpIamIT_testAttachInlinePolicy-POST-0.json", + "headers" : { + "X-Frame-Options" : "SAMEORIGIN", + "Alt-Svc" : "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000", + "Server" : "ESF", + "X-Content-Type-Options" : "nosniff", + "Vary" : [ "Origin", "X-Origin", "Referer" ], + "X-XSS-Protection" : "0", + "Date" : "Tue, 10 Mar 2026 06:21:31 GMT", + "Content-Type" : "application/json; charset=UTF-8" + } + }, + "uuid" : "22d93c52-f67e-43c8-88db-3e484ac651e4", + "persistent" : true, + "insertionIndex" : 25 +} \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/mappings/post-nminjngckd.json b/iam/iam-gcp/src/test/resources/mappings/gcpiamit_testgetattachedpolicies-post-0.json similarity index 56% rename from iam/iam-gcp/src/test/resources/mappings/post-nminjngckd.json rename to iam/iam-gcp/src/test/resources/mappings/gcpiamit_testgetattachedpolicies-post-0.json index e7f9d3c42..7515421d0 100644 --- a/iam/iam-gcp/src/test/resources/mappings/post-nminjngckd.json +++ b/iam/iam-gcp/src/test/resources/mappings/gcpiamit_testgetattachedpolicies-post-0.json @@ -1,9 +1,21 @@ { - "id" : "e49fea98-8778-4b86-932e-4cfe8c9037e1", - "name" : "v3_projects_substrate-sdk-gcp-poc1getiampolicy", + "id" : "c0e86160-423b-4e65-bb58-0b9b5b374254", + "name" : "GcpIamIT_testGetAttachedPolicies-POST-0", "request" : { - "url" : "/v3/projects/substrate-sdk-gcp-poc1:getIamPolicy?$alt=json;enum-encoding%3Dint", + "urlPath" : "/v3/projects/substrate-sdk-gcp-poc1:getIamPolicy", "method" : "POST", + "headers" : { + "X-Query-Param-Count" : { + "equalTo" : "1" + } + }, + "queryParameters" : { + "$alt" : { + "hasExactly" : [ { + "equalTo" : "json;enum-encoding=int" + } ] + } + }, "bodyPatterns" : [ { "equalToJson" : "{}", "ignoreArrayOrder" : true, @@ -12,7 +24,7 @@ }, "response" : { "status" : 200, - "bodyFileName" : "v3_projects_substrate-sdk-gcp-poc1getiampolicy.json", + "bodyFileName" : "GcpIamIT_testGetAttachedPolicies-POST-0.json", "headers" : { "X-Frame-Options" : "SAMEORIGIN", "Alt-Svc" : "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000", @@ -20,13 +32,13 @@ "X-Content-Type-Options" : "nosniff", "Vary" : [ "Origin", "X-Origin", "Referer" ], "X-XSS-Protection" : "0", - "Date" : "Thu, 04 Dec 2025 18:04:24 GMT", + "Date" : "Tue, 10 Mar 2026 06:21:17 GMT", "Content-Type" : "application/json; charset=UTF-8" } }, - "uuid" : "e49fea98-8778-4b86-932e-4cfe8c9037e1", + "uuid" : "c0e86160-423b-4e65-bb58-0b9b5b374254", "persistent" : true, "scenarioName" : "scenario-1-v3-projects-substrate-sdk-gcp-poc1:getIamPolicy", "requiredScenarioState" : "scenario-1-v3-projects-substrate-sdk-gcp-poc1:getIamPolicy-2", - "insertionIndex" : 1 + "insertionIndex" : 19 } \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/mappings/post-5aattfatgv.json b/iam/iam-gcp/src/test/resources/mappings/gcpiamit_testgetattachedpolicies-post-1.json similarity index 57% rename from iam/iam-gcp/src/test/resources/mappings/post-5aattfatgv.json rename to iam/iam-gcp/src/test/resources/mappings/gcpiamit_testgetattachedpolicies-post-1.json index 45e180d64..0314e5256 100644 --- a/iam/iam-gcp/src/test/resources/mappings/post-5aattfatgv.json +++ b/iam/iam-gcp/src/test/resources/mappings/gcpiamit_testgetattachedpolicies-post-1.json @@ -1,9 +1,21 @@ { - "id" : "50b9598e-41a3-48d1-91c4-cc76fc83f125", - "name" : "v3_projects_substrate-sdk-gcp-poc1getiampolicy", + "id" : "b4277c8a-5694-4d7a-87ea-d09211150390", + "name" : "GcpIamIT_testGetAttachedPolicies-POST-1", "request" : { - "url" : "/v3/projects/substrate-sdk-gcp-poc1:getIamPolicy?$alt=json;enum-encoding%3Dint", + "urlPath" : "/v3/projects/substrate-sdk-gcp-poc1:getIamPolicy", "method" : "POST", + "headers" : { + "X-Query-Param-Count" : { + "equalTo" : "1" + } + }, + "queryParameters" : { + "$alt" : { + "hasExactly" : [ { + "equalTo" : "json;enum-encoding=int" + } ] + } + }, "bodyPatterns" : [ { "equalToJson" : "{}", "ignoreArrayOrder" : true, @@ -12,7 +24,7 @@ }, "response" : { "status" : 200, - "bodyFileName" : "v3_projects_substrate-sdk-gcp-poc1getiampolicy.json", + "bodyFileName" : "GcpIamIT_testGetAttachedPolicies-POST-1.json", "headers" : { "X-Frame-Options" : "SAMEORIGIN", "Alt-Svc" : "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000", @@ -20,14 +32,14 @@ "X-Content-Type-Options" : "nosniff", "Vary" : [ "Origin", "X-Origin", "Referer" ], "X-XSS-Protection" : "0", - "Date" : "Thu, 04 Dec 2025 18:04:25 GMT", + "Date" : "Tue, 10 Mar 2026 06:21:15 GMT", "Content-Type" : "application/json; charset=UTF-8" } }, - "uuid" : "50b9598e-41a3-48d1-91c4-cc76fc83f125", + "uuid" : "b4277c8a-5694-4d7a-87ea-d09211150390", "persistent" : true, "scenarioName" : "scenario-1-v3-projects-substrate-sdk-gcp-poc1:getIamPolicy", "requiredScenarioState" : "Started", "newScenarioState" : "scenario-1-v3-projects-substrate-sdk-gcp-poc1:getIamPolicy-2", - "insertionIndex" : 6 + "insertionIndex" : 20 } \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/mappings/post-xkfmqhdn11.json b/iam/iam-gcp/src/test/resources/mappings/gcpiamit_testgetinlinepolicydetails-post-0.json similarity index 57% rename from iam/iam-gcp/src/test/resources/mappings/post-xkfmqhdn11.json rename to iam/iam-gcp/src/test/resources/mappings/gcpiamit_testgetinlinepolicydetails-post-0.json index 039e48980..f6906a247 100644 --- a/iam/iam-gcp/src/test/resources/mappings/post-xkfmqhdn11.json +++ b/iam/iam-gcp/src/test/resources/mappings/gcpiamit_testgetinlinepolicydetails-post-0.json @@ -1,9 +1,21 @@ { - "id" : "1ca367ef-1ab1-42e0-bd8d-e5b327da0828", - "name" : "v3_projects_substrate-sdk-gcp-poc1getiampolicy", + "id" : "88f7182c-bc2a-4722-baed-0690b332548c", + "name" : "GcpIamIT_testGetInlinePolicyDetails-POST-0", "request" : { - "url" : "/v3/projects/substrate-sdk-gcp-poc1:getIamPolicy?$alt=json;enum-encoding%3Dint", + "urlPath" : "/v3/projects/substrate-sdk-gcp-poc1:getIamPolicy", "method" : "POST", + "headers" : { + "X-Query-Param-Count" : { + "equalTo" : "1" + } + }, + "queryParameters" : { + "$alt" : { + "hasExactly" : [ { + "equalTo" : "json;enum-encoding=int" + } ] + } + }, "bodyPatterns" : [ { "equalToJson" : "{}", "ignoreArrayOrder" : true, @@ -12,7 +24,7 @@ }, "response" : { "status" : 200, - "bodyFileName" : "v3_projects_substrate-sdk-gcp-poc1getiampolicy.json", + "bodyFileName" : "GcpIamIT_testGetInlinePolicyDetails-POST-0.json", "headers" : { "X-Frame-Options" : "SAMEORIGIN", "Alt-Svc" : "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000", @@ -20,11 +32,11 @@ "X-Content-Type-Options" : "nosniff", "Vary" : [ "Origin", "X-Origin", "Referer" ], "X-XSS-Protection" : "0", - "Date" : "Thu, 04 Dec 2025 18:04:33 GMT", + "Date" : "Tue, 10 Mar 2026 06:20:56 GMT", "Content-Type" : "application/json; charset=UTF-8" } }, - "uuid" : "1ca367ef-1ab1-42e0-bd8d-e5b327da0828", + "uuid" : "88f7182c-bc2a-4722-baed-0690b332548c", "persistent" : true, "scenarioName" : "scenario-1-v3-projects-substrate-sdk-gcp-poc1:getIamPolicy", "requiredScenarioState" : "scenario-1-v3-projects-substrate-sdk-gcp-poc1:getIamPolicy-2", diff --git a/iam/iam-gcp/src/test/resources/mappings/post-mxkzqugtut.json b/iam/iam-gcp/src/test/resources/mappings/gcpiamit_testgetinlinepolicydetails-post-1.json similarity index 56% rename from iam/iam-gcp/src/test/resources/mappings/post-mxkzqugtut.json rename to iam/iam-gcp/src/test/resources/mappings/gcpiamit_testgetinlinepolicydetails-post-1.json index a0653b796..3bcda473b 100644 --- a/iam/iam-gcp/src/test/resources/mappings/post-mxkzqugtut.json +++ b/iam/iam-gcp/src/test/resources/mappings/gcpiamit_testgetinlinepolicydetails-post-1.json @@ -1,9 +1,21 @@ { - "id" : "0acb1c66-bec3-4879-bab8-8db44a6fc534", - "name" : "v3_projects_substrate-sdk-gcp-poc1getiampolicy", + "id" : "33e13a3c-d5af-4a95-813b-5e7ef75d7db8", + "name" : "GcpIamIT_testGetInlinePolicyDetails-POST-1", "request" : { - "url" : "/v3/projects/substrate-sdk-gcp-poc1:getIamPolicy?$alt=json;enum-encoding%3Dint", + "urlPath" : "/v3/projects/substrate-sdk-gcp-poc1:getIamPolicy", "method" : "POST", + "headers" : { + "X-Query-Param-Count" : { + "equalTo" : "1" + } + }, + "queryParameters" : { + "$alt" : { + "hasExactly" : [ { + "equalTo" : "json;enum-encoding=int" + } ] + } + }, "bodyPatterns" : [ { "equalToJson" : "{}", "ignoreArrayOrder" : true, @@ -12,7 +24,7 @@ }, "response" : { "status" : 200, - "bodyFileName" : "v3_projects_substrate-sdk-gcp-poc1getiampolicy.json", + "bodyFileName" : "GcpIamIT_testGetInlinePolicyDetails-POST-1.json", "headers" : { "X-Frame-Options" : "SAMEORIGIN", "Alt-Svc" : "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000", @@ -20,14 +32,14 @@ "X-Content-Type-Options" : "nosniff", "Vary" : [ "Origin", "X-Origin", "Referer" ], "X-XSS-Protection" : "0", - "Date" : "Thu, 04 Dec 2025 18:04:22 GMT", + "Date" : "Tue, 10 Mar 2026 06:20:54 GMT", "Content-Type" : "application/json; charset=UTF-8" } }, - "uuid" : "0acb1c66-bec3-4879-bab8-8db44a6fc534", + "uuid" : "33e13a3c-d5af-4a95-813b-5e7ef75d7db8", "persistent" : true, "scenarioName" : "scenario-1-v3-projects-substrate-sdk-gcp-poc1:getIamPolicy", "requiredScenarioState" : "Started", "newScenarioState" : "scenario-1-v3-projects-substrate-sdk-gcp-poc1:getIamPolicy-2", - "insertionIndex" : 2 + "insertionIndex" : 9 } \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/mappings/post-oac0vju14e.json b/iam/iam-gcp/src/test/resources/mappings/gcpiamit_testremovepolicy-post-0.json similarity index 56% rename from iam/iam-gcp/src/test/resources/mappings/post-oac0vju14e.json rename to iam/iam-gcp/src/test/resources/mappings/gcpiamit_testremovepolicy-post-0.json index a0772e4de..010664ddd 100644 --- a/iam/iam-gcp/src/test/resources/mappings/post-oac0vju14e.json +++ b/iam/iam-gcp/src/test/resources/mappings/gcpiamit_testremovepolicy-post-0.json @@ -1,9 +1,21 @@ { - "id" : "7633676d-e774-4262-be57-571dd0e16f92", - "name" : "v3_projects_substrate-sdk-gcp-poc1getiampolicy", + "id" : "dc601264-598f-41b7-ad7b-b760df7e7189", + "name" : "GcpIamIT_testRemovePolicy-POST-0", "request" : { - "url" : "/v3/projects/substrate-sdk-gcp-poc1:getIamPolicy?$alt=json;enum-encoding%3Dint", + "urlPath" : "/v3/projects/substrate-sdk-gcp-poc1:getIamPolicy", "method" : "POST", + "headers" : { + "X-Query-Param-Count" : { + "equalTo" : "1" + } + }, + "queryParameters" : { + "$alt" : { + "hasExactly" : [ { + "equalTo" : "json;enum-encoding=int" + } ] + } + }, "bodyPatterns" : [ { "equalToJson" : "{}", "ignoreArrayOrder" : true, @@ -12,7 +24,7 @@ }, "response" : { "status" : 200, - "bodyFileName" : "v3_projects_substrate-sdk-gcp-poc1getiampolicy.json", + "bodyFileName" : "GcpIamIT_testRemovePolicy-POST-0.json", "headers" : { "X-Frame-Options" : "SAMEORIGIN", "Alt-Svc" : "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000", @@ -20,13 +32,13 @@ "X-Content-Type-Options" : "nosniff", "Vary" : [ "Origin", "X-Origin", "Referer" ], "X-XSS-Protection" : "0", - "Date" : "Thu, 04 Dec 2025 18:04:26 GMT", + "Date" : "Tue, 10 Mar 2026 06:21:13 GMT", "Content-Type" : "application/json; charset=UTF-8" } }, - "uuid" : "7633676d-e774-4262-be57-571dd0e16f92", + "uuid" : "dc601264-598f-41b7-ad7b-b760df7e7189", "persistent" : true, "scenarioName" : "scenario-1-v3-projects-substrate-sdk-gcp-poc1:getIamPolicy", "requiredScenarioState" : "scenario-1-v3-projects-substrate-sdk-gcp-poc1:getIamPolicy-2", - "insertionIndex" : 5 + "insertionIndex" : 16 } \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/mappings/post-skt7azqyn1.json b/iam/iam-gcp/src/test/resources/mappings/gcpiamit_testremovepolicy-post-1.json similarity index 57% rename from iam/iam-gcp/src/test/resources/mappings/post-skt7azqyn1.json rename to iam/iam-gcp/src/test/resources/mappings/gcpiamit_testremovepolicy-post-1.json index ac8b77fc2..d2ca5b897 100644 --- a/iam/iam-gcp/src/test/resources/mappings/post-skt7azqyn1.json +++ b/iam/iam-gcp/src/test/resources/mappings/gcpiamit_testremovepolicy-post-1.json @@ -1,9 +1,21 @@ { - "id" : "b99f2e19-aa6b-4d92-b88b-53ece072e869", - "name" : "v3_projects_substrate-sdk-gcp-poc1getiampolicy", + "id" : "80c15e98-0c97-4175-a80f-d6ebbbca4226", + "name" : "GcpIamIT_testRemovePolicy-POST-1", "request" : { - "url" : "/v3/projects/substrate-sdk-gcp-poc1:getIamPolicy?$alt=json;enum-encoding%3Dint", + "urlPath" : "/v3/projects/substrate-sdk-gcp-poc1:getIamPolicy", "method" : "POST", + "headers" : { + "X-Query-Param-Count" : { + "equalTo" : "1" + } + }, + "queryParameters" : { + "$alt" : { + "hasExactly" : [ { + "equalTo" : "json;enum-encoding=int" + } ] + } + }, "bodyPatterns" : [ { "equalToJson" : "{}", "ignoreArrayOrder" : true, @@ -12,7 +24,7 @@ }, "response" : { "status" : 200, - "bodyFileName" : "v3_projects_substrate-sdk-gcp-poc1getiampolicy.json", + "bodyFileName" : "GcpIamIT_testRemovePolicy-POST-1.json", "headers" : { "X-Frame-Options" : "SAMEORIGIN", "Alt-Svc" : "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000", @@ -20,14 +32,14 @@ "X-Content-Type-Options" : "nosniff", "Vary" : [ "Origin", "X-Origin", "Referer" ], "X-XSS-Protection" : "0", - "Date" : "Thu, 04 Dec 2025 18:04:30 GMT", + "Date" : "Tue, 10 Mar 2026 06:21:12 GMT", "Content-Type" : "application/json; charset=UTF-8" } }, - "uuid" : "b99f2e19-aa6b-4d92-b88b-53ece072e869", + "uuid" : "80c15e98-0c97-4175-a80f-d6ebbbca4226", "persistent" : true, "scenarioName" : "scenario-1-v3-projects-substrate-sdk-gcp-poc1:getIamPolicy", "requiredScenarioState" : "Started", "newScenarioState" : "scenario-1-v3-projects-substrate-sdk-gcp-poc1:getIamPolicy-2", - "insertionIndex" : 10 + "insertionIndex" : 17 } \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/mappings/post-pkw37nmslw.json b/iam/iam-gcp/src/test/resources/mappings/post-pkw37nmslw.json deleted file mode 100644 index 5694eb5a3..000000000 --- a/iam/iam-gcp/src/test/resources/mappings/post-pkw37nmslw.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "id" : "e870947d-5f8c-4b0c-b4a2-691c27366dea", - "name" : "v3_projects_substrate-sdk-gcp-poc1setiampolicy", - "request" : { - "url" : "/v3/projects/substrate-sdk-gcp-poc1:setIamPolicy?$alt=json;enum-encoding%3Dint", - "method" : "POST", - "bodyPatterns" : [ { - "matchesJsonPath" : "$.policy" - }, { - "matchesJsonPath" : "$.policy.bindings" - } ] - }, - "response" : { - "status" : 200, - "bodyFileName" : "v3_projects_substrate-sdk-gcp-poc1setiampolicy.json", - "headers" : { - "X-Frame-Options" : "SAMEORIGIN", - "Alt-Svc" : "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000", - "Server" : "ESF", - "X-Content-Type-Options" : "nosniff", - "Vary" : [ "Origin", "X-Origin", "Referer" ], - "X-XSS-Protection" : "0", - "Date" : "Thu, 04 Dec 2025 18:04:32 GMT", - "Content-Type" : "application/json; charset=UTF-8" - } - }, - "uuid" : "e870947d-5f8c-4b0c-b4a2-691c27366dea", - "persistent" : true, - "insertionIndex" : 9 -} \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/mappings/post-wvlsovhqyv.json b/iam/iam-gcp/src/test/resources/mappings/post-wvlsovhqyv.json deleted file mode 100644 index ca520b1aa..000000000 --- a/iam/iam-gcp/src/test/resources/mappings/post-wvlsovhqyv.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "id" : "2bd9315b-7a98-4be0-888b-0b624db826a9", - "name" : "v3_projects_substrate-sdk-gcp-poc1setiampolicy", - "request" : { - "url" : "/v3/projects/substrate-sdk-gcp-poc1:setIamPolicy?$alt=json;enum-encoding%3Dint", - "method" : "POST", - "bodyPatterns" : [ { - "matchesJsonPath" : "$.policy" - }, { - "matchesJsonPath" : "$.policy.bindings" - } ] - }, - "response" : { - "status" : 200, - "bodyFileName" : "v3_projects_substrate-sdk-gcp-poc1setiampolicy.json", - "headers" : { - "X-Frame-Options" : "SAMEORIGIN", - "Alt-Svc" : "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000", - "Server" : "ESF", - "X-Content-Type-Options" : "nosniff", - "Vary" : [ "Origin", "X-Origin", "Referer" ], - "X-XSS-Protection" : "0", - "Date" : "Thu, 04 Dec 2025 18:04:28 GMT", - "Content-Type" : "application/json; charset=UTF-8" - } - }, - "uuid" : "2bd9315b-7a98-4be0-888b-0b624db826a9", - "persistent" : true, - "insertionIndex" : 4 -} \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/mappings/post-xuddonq8r7.json b/iam/iam-gcp/src/test/resources/mappings/post-xuddonq8r7.json deleted file mode 100644 index 1f487b51a..000000000 --- a/iam/iam-gcp/src/test/resources/mappings/post-xuddonq8r7.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "id" : "68bcaca7-e8b2-4bf5-a8e6-8b3cc92a3e7e", - "name" : "v3_projects_substrate-sdk-gcp-poc1getiampolicy", - "request" : { - "url" : "/v3/projects/substrate-sdk-gcp-poc1:getIamPolicy?$alt=json;enum-encoding%3Dint", - "method" : "POST", - "bodyPatterns" : [ { - "equalToJson" : "{}", - "ignoreArrayOrder" : true, - "ignoreExtraElements" : false - } ] - }, - "response" : { - "status" : 200, - "bodyFileName" : "v3_projects_substrate-sdk-gcp-poc1getiampolicy.json", - "headers" : { - "X-Frame-Options" : "SAMEORIGIN", - "Alt-Svc" : "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000", - "Server" : "ESF", - "X-Content-Type-Options" : "nosniff", - "Vary" : [ "Origin", "X-Origin", "Referer" ], - "X-XSS-Protection" : "0", - "Date" : "Thu, 04 Dec 2025 18:04:34 GMT", - "Content-Type" : "application/json; charset=UTF-8" - } - }, - "uuid" : "68bcaca7-e8b2-4bf5-a8e6-8b3cc92a3e7e", - "persistent" : true, - "insertionIndex" : 12 -} \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/recordings/CreateServiceAccount-0038e34cce.json b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithNullDescription-CreateServiceAccount-0.json similarity index 85% rename from iam/iam-gcp/src/test/resources/recordings/CreateServiceAccount-0038e34cce.json rename to iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithNullDescription-CreateServiceAccount-0.json index 10b46c662..03baaed91 100644 --- a/iam/iam-gcp/src/test/resources/recordings/CreateServiceAccount-0038e34cce.json +++ b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithNullDescription-CreateServiceAccount-0.json @@ -10,10 +10,10 @@ "response" : { "name" : "projects/substrate-sdk-gcp-poc1/serviceAccounts/testSaNoDesc@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "projectId" : "substrate-sdk-gcp-poc1", - "uniqueId" : "108085590103743633246", + "uniqueId" : "102865126650479399537", "email" : "testSaNoDesc@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "displayName" : "testSaNoDesc", "etag" : "MDEwMjE5MjA=", - "oauth2ClientId" : "108085590103743633246" + "oauth2ClientId" : "102865126650479399537" } } \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/recordings/DeleteServiceAccount-2b53a9fbf4.json b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithNullDescription-DeleteServiceAccount-1.json similarity index 100% rename from iam/iam-gcp/src/test/resources/recordings/DeleteServiceAccount-2b53a9fbf4.json rename to iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithNullDescription-DeleteServiceAccount-1.json diff --git a/iam/iam-gcp/src/test/resources/recordings/CreateServiceAccount-f89eed1a0c.json b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithOptions-CreateServiceAccount-0.json similarity index 88% rename from iam/iam-gcp/src/test/resources/recordings/CreateServiceAccount-f89eed1a0c.json rename to iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithOptions-CreateServiceAccount-0.json index 201617fd2..5f829b0d9 100644 --- a/iam/iam-gcp/src/test/resources/recordings/CreateServiceAccount-f89eed1a0c.json +++ b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithOptions-CreateServiceAccount-0.json @@ -11,11 +11,11 @@ "response" : { "name" : "projects/substrate-sdk-gcp-poc1/serviceAccounts/testSaOptions@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "projectId" : "substrate-sdk-gcp-poc1", - "uniqueId" : "109565557264935454464", + "uniqueId" : "102953692975457158239", "email" : "testSaOptions@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "displayName" : "testSaOptions", "etag" : "MDEwMjE5MjA=", "description" : "Test identity with options", - "oauth2ClientId" : "109565557264935454464" + "oauth2ClientId" : "102953692975457158239" } } \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/recordings/DeleteServiceAccount-3fbaf6618d.json b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithOptions-DeleteServiceAccount-1.json similarity index 100% rename from iam/iam-gcp/src/test/resources/recordings/DeleteServiceAccount-3fbaf6618d.json rename to iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithOptions-DeleteServiceAccount-1.json diff --git a/iam/iam-gcp/src/test/resources/recordings/CreateServiceAccount-5ac1ccc649.json b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithTrustConfig-CreateServiceAccount-0.json similarity index 88% rename from iam/iam-gcp/src/test/resources/recordings/CreateServiceAccount-5ac1ccc649.json rename to iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithTrustConfig-CreateServiceAccount-0.json index 9898f4d90..426f86022 100644 --- a/iam/iam-gcp/src/test/resources/recordings/CreateServiceAccount-5ac1ccc649.json +++ b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithTrustConfig-CreateServiceAccount-0.json @@ -11,11 +11,11 @@ "response" : { "name" : "projects/substrate-sdk-gcp-poc1/serviceAccounts/testSaTrusted@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "projectId" : "substrate-sdk-gcp-poc1", - "uniqueId" : "114226505833153891027", + "uniqueId" : "115083799994541468311", "email" : "testSaTrusted@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "displayName" : "testSaTrusted", "etag" : "MDEwMjE5MjA=", "description" : "Test identity with trust configuration", - "oauth2ClientId" : "114226505833153891027" + "oauth2ClientId" : "115083799994541468311" } } \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/recordings/DeleteServiceAccount-3a633a932c.json b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithTrustConfig-DeleteServiceAccount-3.json similarity index 100% rename from iam/iam-gcp/src/test/resources/recordings/DeleteServiceAccount-3a633a932c.json rename to iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithTrustConfig-DeleteServiceAccount-3.json diff --git a/iam/iam-gcp/src/test/resources/recordings/GetIamPolicy-9ed4add206.json b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithTrustConfig-GetIamPolicy-1.json similarity index 100% rename from iam/iam-gcp/src/test/resources/recordings/GetIamPolicy-9ed4add206.json rename to iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithTrustConfig-GetIamPolicy-1.json diff --git a/iam/iam-gcp/src/test/resources/recordings/SetIamPolicy-b8908f14aa.json b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithTrustConfig-SetIamPolicy-2.json similarity index 95% rename from iam/iam-gcp/src/test/resources/recordings/SetIamPolicy-b8908f14aa.json rename to iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithTrustConfig-SetIamPolicy-2.json index d6fc61b96..950b8000b 100644 --- a/iam/iam-gcp/src/test/resources/recordings/SetIamPolicy-b8908f14aa.json +++ b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithTrustConfig-SetIamPolicy-2.json @@ -12,7 +12,7 @@ }, "response" : { "version" : 1, - "etag" : "BwZGM212JDM=", + "etag" : "BwZMpYeYQ7Y=", "bindings" : [ { "role" : "roles/iam.serviceAccountTokenCreator", "members" : [ "serviceAccount:chameleon@substrate-sdk-gcp-poc1.iam.gserviceaccount.com" ] diff --git a/iam/iam-gcp/src/test/resources/recordings/CreateServiceAccount-fad45e7acf.json b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithoutTrustConfig-CreateServiceAccount-0.json similarity index 88% rename from iam/iam-gcp/src/test/resources/recordings/CreateServiceAccount-fad45e7acf.json rename to iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithoutTrustConfig-CreateServiceAccount-0.json index 2b46794d7..3dd8b166f 100644 --- a/iam/iam-gcp/src/test/resources/recordings/CreateServiceAccount-fad45e7acf.json +++ b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithoutTrustConfig-CreateServiceAccount-0.json @@ -11,11 +11,11 @@ "response" : { "name" : "projects/substrate-sdk-gcp-poc1/serviceAccounts/testSa@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "projectId" : "substrate-sdk-gcp-poc1", - "uniqueId" : "103620143516080021483", + "uniqueId" : "104843033574003145131", "email" : "testSa@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "displayName" : "testSa", "etag" : "MDEwMjE5MjA=", "description" : "Test identity for MultiCloudJ integration tests", - "oauth2ClientId" : "103620143516080021483" + "oauth2ClientId" : "104843033574003145131" } } \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/recordings/DeleteServiceAccount-dfbbbafc77.json b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithoutTrustConfig-DeleteServiceAccount-1.json similarity index 100% rename from iam/iam-gcp/src/test/resources/recordings/DeleteServiceAccount-dfbbbafc77.json rename to iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testCreateIdentityWithoutTrustConfig-DeleteServiceAccount-1.json diff --git a/iam/iam-gcp/src/test/resources/recordings/CreateServiceAccount-dbb645f094.json b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testDeleteIdentity-CreateServiceAccount-0.json similarity index 88% rename from iam/iam-gcp/src/test/resources/recordings/CreateServiceAccount-dbb645f094.json rename to iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testDeleteIdentity-CreateServiceAccount-0.json index 7618a409c..90db8bb94 100644 --- a/iam/iam-gcp/src/test/resources/recordings/CreateServiceAccount-dbb645f094.json +++ b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testDeleteIdentity-CreateServiceAccount-0.json @@ -11,11 +11,11 @@ "response" : { "name" : "projects/substrate-sdk-gcp-poc1/serviceAccounts/testSaDelete@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "projectId" : "substrate-sdk-gcp-poc1", - "uniqueId" : "112498036806527349406", + "uniqueId" : "103339348629474298603", "email" : "testSaDelete@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "displayName" : "testSaDelete", "etag" : "MDEwMjE5MjA=", "description" : "Test identity for delete operation", - "oauth2ClientId" : "112498036806527349406" + "oauth2ClientId" : "103339348629474298603" } } \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/recordings/DeleteServiceAccount-0aacb9ede1.json b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testDeleteIdentity-DeleteServiceAccount-1.json similarity index 100% rename from iam/iam-gcp/src/test/resources/recordings/DeleteServiceAccount-0aacb9ede1.json rename to iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testDeleteIdentity-DeleteServiceAccount-1.json diff --git a/iam/iam-gcp/src/test/resources/recordings/CreateServiceAccount-192993f719.json b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testGetIdentity-CreateServiceAccount-0.json similarity index 87% rename from iam/iam-gcp/src/test/resources/recordings/CreateServiceAccount-192993f719.json rename to iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testGetIdentity-CreateServiceAccount-0.json index 73d22c97f..968b529b8 100644 --- a/iam/iam-gcp/src/test/resources/recordings/CreateServiceAccount-192993f719.json +++ b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testGetIdentity-CreateServiceAccount-0.json @@ -11,11 +11,11 @@ "response" : { "name" : "projects/substrate-sdk-gcp-poc1/serviceAccounts/testSaGet@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "projectId" : "substrate-sdk-gcp-poc1", - "uniqueId" : "105446840476600676066", + "uniqueId" : "116075516548726492820", "email" : "testSaGet@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "displayName" : "testSaGet", "etag" : "MDEwMjE5MjA=", "description" : "Test identity for get operation", - "oauth2ClientId" : "105446840476600676066" + "oauth2ClientId" : "116075516548726492820" } } \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/recordings/DeleteServiceAccount-b21348fb04.json b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testGetIdentity-DeleteServiceAccount-2.json similarity index 100% rename from iam/iam-gcp/src/test/resources/recordings/DeleteServiceAccount-b21348fb04.json rename to iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testGetIdentity-DeleteServiceAccount-2.json diff --git a/iam/iam-gcp/src/test/resources/recordings/GetServiceAccount-d6d8fa9d22.json b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testGetIdentity-GetServiceAccount-1.json similarity index 86% rename from iam/iam-gcp/src/test/resources/recordings/GetServiceAccount-d6d8fa9d22.json rename to iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testGetIdentity-GetServiceAccount-1.json index 51805fc86..dd5c9239a 100644 --- a/iam/iam-gcp/src/test/resources/recordings/GetServiceAccount-d6d8fa9d22.json +++ b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testGetIdentity-GetServiceAccount-1.json @@ -6,11 +6,11 @@ "response" : { "name" : "projects/substrate-sdk-gcp-poc1/serviceAccounts/testSaGet@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "projectId" : "substrate-sdk-gcp-poc1", - "uniqueId" : "105446840476600676066", + "uniqueId" : "116075516548726492820", "email" : "testSaGet@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "displayName" : "testSaGet", "etag" : "MDEwMjE5MjA=", "description" : "Test identity for get operation", - "oauth2ClientId" : "105446840476600676066" + "oauth2ClientId" : "116075516548726492820" } } \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/recordings/CreateServiceAccount-a838751584.json b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testIdentityLifecycle-CreateServiceAccount-0.json similarity index 88% rename from iam/iam-gcp/src/test/resources/recordings/CreateServiceAccount-a838751584.json rename to iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testIdentityLifecycle-CreateServiceAccount-0.json index 3e40aef20..c7f36437f 100644 --- a/iam/iam-gcp/src/test/resources/recordings/CreateServiceAccount-a838751584.json +++ b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testIdentityLifecycle-CreateServiceAccount-0.json @@ -11,11 +11,11 @@ "response" : { "name" : "projects/substrate-sdk-gcp-poc1/serviceAccounts/testSaLifeCycle@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "projectId" : "substrate-sdk-gcp-poc1", - "uniqueId" : "105479164116917983204", + "uniqueId" : "105239457643377913600", "email" : "testSaLifeCycle@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "displayName" : "testSaLifeCycle", "etag" : "MDEwMjE5MjA=", "description" : "Test identity for lifecycle test", - "oauth2ClientId" : "105479164116917983204" + "oauth2ClientId" : "105239457643377913600" } } \ No newline at end of file diff --git a/iam/iam-gcp/src/test/resources/recordings/DeleteServiceAccount-a4bc7f20c4.json b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testIdentityLifecycle-DeleteServiceAccount-2.json similarity index 100% rename from iam/iam-gcp/src/test/resources/recordings/DeleteServiceAccount-a4bc7f20c4.json rename to iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testIdentityLifecycle-DeleteServiceAccount-2.json diff --git a/iam/iam-gcp/src/test/resources/recordings/GetServiceAccount-dc77b3e304.json b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testIdentityLifecycle-GetServiceAccount-1.json similarity index 86% rename from iam/iam-gcp/src/test/resources/recordings/GetServiceAccount-dc77b3e304.json rename to iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testIdentityLifecycle-GetServiceAccount-1.json index 58995d12f..283092a3b 100644 --- a/iam/iam-gcp/src/test/resources/recordings/GetServiceAccount-dc77b3e304.json +++ b/iam/iam-gcp/src/test/resources/recordings/GcpIamIT_testIdentityLifecycle-GetServiceAccount-1.json @@ -6,11 +6,11 @@ "response" : { "name" : "projects/substrate-sdk-gcp-poc1/serviceAccounts/testSaLifeCycle@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "projectId" : "substrate-sdk-gcp-poc1", - "uniqueId" : "105479164116917983204", + "uniqueId" : "105239457643377913600", "email" : "testSaLifeCycle@substrate-sdk-gcp-poc1.iam.gserviceaccount.com", "displayName" : "testSaLifeCycle", "etag" : "MDEwMjE5MjA=", "description" : "Test identity for lifecycle test", - "oauth2ClientId" : "105479164116917983204" + "oauth2ClientId" : "105239457643377913600" } } \ No newline at end of file diff --git a/registry/registry-gcp/pom.xml b/registry/registry-gcp/pom.xml index ed1634512..8192e9465 100644 --- a/registry/registry-gcp/pom.xml +++ b/registry/registry-gcp/pom.xml @@ -89,7 +89,7 @@ com.google.api gax - 2.50.0 + 2.65.0