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

sammichen pushed a commit to branch HDDS-13323-sts
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/HDDS-13323-sts by this push:
     new e63936bce0e HDDS-14716. [STS] Use MalformedPolicyDocument error code 
for IAM Session Policy validation errors (#9823)
e63936bce0e is described below

commit e63936bce0ed9c67b287266ec504925c18a7af30
Author: fmorg-git <[email protected]>
AuthorDate: Thu Feb 26 23:53:22 2026 -0800

    HDDS-14716. [STS] Use MalformedPolicyDocument error code for IAM Session 
Policy validation errors (#9823)
---
 .../hadoop/ozone/om/exceptions/OMException.java    |   1 +
 .../security/acl/iam/IamSessionPolicyResolver.java |  22 ++--
 .../acl/iam/TestIamSessionPolicyResolver.java      |  29 ++---
 .../src/main/proto/OmClientProtocol.proto          |   1 +
 .../apache/hadoop/ozone/s3sts/S3STSEndpoint.java   |  10 +-
 .../hadoop/ozone/s3sts/TestS3STSEndpoint.java      | 124 ++++++++++++++-------
 6 files changed, 120 insertions(+), 67 deletions(-)

diff --git 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/exceptions/OMException.java
 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/exceptions/OMException.java
index 70acadefed8..fcd1e7807f1 100644
--- 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/exceptions/OMException.java
+++ 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/exceptions/OMException.java
@@ -277,5 +277,6 @@ public enum ResultCodes {
     TOO_MANY_SNAPSHOTS,
 
     REVOKED_TOKEN,
+    MALFORMED_POLICY_DOCUMENT,
   }
 }
diff --git 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/security/acl/iam/IamSessionPolicyResolver.java
 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/security/acl/iam/IamSessionPolicyResolver.java
index 0da9781e8af..b8b032f1b35 100644
--- 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/security/acl/iam/IamSessionPolicyResolver.java
+++ 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/security/acl/iam/IamSessionPolicyResolver.java
@@ -19,7 +19,7 @@
 
 import static java.util.Collections.singleton;
 import static 
org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.INTERNAL_ERROR;
-import static 
org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.INVALID_REQUEST;
+import static 
org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.MALFORMED_POLICY_DOCUMENT;
 import static 
org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.NOT_SUPPORTED_OPERATION;
 import static 
org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType.CREATE;
 import static 
org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType.DELETE;
@@ -181,7 +181,7 @@ private static void validateInputParameters(String 
policyJson, String volumeName
     if (policyJson.length() > MAX_JSON_LENGTH) {
       throw new OMException(
           ERROR_PREFIX + "Invalid policy JSON - exceeds maximum length of " + 
MAX_JSON_LENGTH + " characters",
-          INVALID_REQUEST);
+          MALFORMED_POLICY_DOCUMENT);
     }
   }
 
@@ -194,12 +194,12 @@ private static Set<JsonNode> 
parseJsonAndRetrieveStatements(String policyJson) t
       root = MAPPER.readTree(policyJson);
     } catch (Exception e) {
       throw new OMException(
-          ERROR_PREFIX + "Invalid policy JSON (most likely JSON structure is 
incorrect)", e, INVALID_REQUEST);
+          ERROR_PREFIX + "Invalid policy JSON (most likely JSON structure is 
incorrect)", e, MALFORMED_POLICY_DOCUMENT);
     }
 
     final JsonNode statementsNode = root.path("Statement");
     if (statementsNode.isMissingNode()) {
-      throw new OMException(ERROR_PREFIX + "Invalid policy JSON - missing 
Statement", INVALID_REQUEST);
+      throw new OMException(ERROR_PREFIX + "Invalid policy JSON - missing 
Statement", MALFORMED_POLICY_DOCUMENT);
     }
 
     final Set<JsonNode> statements = new HashSet<>();
@@ -227,10 +227,10 @@ private static void 
validateEffectInJsonStatement(JsonNode statement) throws OME
       }
 
       throw new OMException(
-          ERROR_PREFIX + "Invalid Effect in JSON policy (must be a String) - " 
+ effectNode, INVALID_REQUEST);
+          ERROR_PREFIX + "Invalid Effect in JSON policy (must be a String) - " 
+ effectNode, MALFORMED_POLICY_DOCUMENT);
     }
 
-    throw new OMException(ERROR_PREFIX + "Effect is missing from JSON policy", 
INVALID_REQUEST);
+    throw new OMException(ERROR_PREFIX + "Effect is missing from JSON policy", 
MALFORMED_POLICY_DOCUMENT);
   }
 
   /**
@@ -276,7 +276,7 @@ private static Set<String> 
parsePrefixesFromConditions(JsonNode stmt) throws OME
       if (!cond.isObject()) {
         throw new OMException(
             ERROR_PREFIX + "Invalid Condition (must have operator StringEquals 
or StringLike " +
-            "and key name s3:prefix) - " + cond, INVALID_REQUEST);
+            "and key name s3:prefix) - " + cond, MALFORMED_POLICY_DOCUMENT);
       }
 
       final String operator = cond.fieldNames().next();
@@ -287,12 +287,12 @@ private static Set<String> 
parsePrefixesFromConditions(JsonNode stmt) throws OME
       final JsonNode operatorValue = cond.get(operator);
       if ("null".equals(operatorValue.asText())) {
         throw new OMException(
-            ERROR_PREFIX + "Missing Condition operator value for " + operator, 
INVALID_REQUEST);
+            ERROR_PREFIX + "Missing Condition operator value for " + operator, 
MALFORMED_POLICY_DOCUMENT);
       }
 
       if (!operatorValue.isObject()) {
         throw new OMException(
-            ERROR_PREFIX + "Invalid Condition operator value structure - " + 
operatorValue, INVALID_REQUEST);
+            ERROR_PREFIX + "Invalid Condition operator value structure - " + 
operatorValue, MALFORMED_POLICY_DOCUMENT);
       }
 
       final String keyName = operatorValue.fieldNames().hasNext() ? 
operatorValue.fieldNames().next() : null;
@@ -382,7 +382,7 @@ static Set<ResourceSpec> 
validateAndCategorizeResources(AuthorizerType authorize
       Set<String> resources) throws OMException {
     final Set<ResourceSpec> resourceSpecs = new HashSet<>();
     if (resources.isEmpty()) {
-      throw new OMException(ERROR_PREFIX + "No Resource(s) found in policy", 
INVALID_REQUEST);
+      throw new OMException(ERROR_PREFIX + "No Resource(s) found in policy", 
MALFORMED_POLICY_DOCUMENT);
     }
     for (String resource : resources) {
       if ("*".equals(resource)) {
@@ -397,7 +397,7 @@ static Set<ResourceSpec> 
validateAndCategorizeResources(AuthorizerType authorize
 
       final String suffix = resource.substring(AWS_S3_ARN_PREFIX.length());
       if (suffix.isEmpty()) {
-        throw new OMException(ERROR_PREFIX + "Invalid Resource Arn - " + 
resource, INVALID_REQUEST);
+        throw new OMException(ERROR_PREFIX + "Invalid Resource Arn - " + 
resource, MALFORMED_POLICY_DOCUMENT);
       }
 
       ResourceSpec spec = parseResourceSpec(suffix);
diff --git 
a/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/security/acl/iam/TestIamSessionPolicyResolver.java
 
b/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/security/acl/iam/TestIamSessionPolicyResolver.java
index 4ca478156a3..41d2fc338f3 100644
--- 
a/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/security/acl/iam/TestIamSessionPolicyResolver.java
+++ 
b/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/security/acl/iam/TestIamSessionPolicyResolver.java
@@ -18,7 +18,7 @@
 package org.apache.hadoop.ozone.security.acl.iam;
 
 import static java.util.Collections.emptySet;
-import static 
org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.INVALID_REQUEST;
+import static 
org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.MALFORMED_POLICY_DOCUMENT;
 import static 
org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.NOT_SUPPORTED_OPERATION;
 import static 
org.apache.hadoop.ozone.security.acl.AssumeRoleRequest.OzoneGrant;
 import static org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType;
@@ -119,7 +119,7 @@ public void testInvalidJsonWithoutStatementThrows() {
         "}";
 
     expectResolveThrowsForBothAuthorizers(
-        json, "IAM session policy: Invalid policy JSON - missing Statement", 
INVALID_REQUEST);
+        json, "IAM session policy: Invalid policy JSON - missing Statement", 
MALFORMED_POLICY_DOCUMENT);
   }
 
   @Test
@@ -134,7 +134,7 @@ public void testInvalidEffectThrows() {
 
     expectResolveThrowsForBothAuthorizers(
         json, "IAM session policy: Invalid Effect in JSON policy (must be a 
String) - [\"Allow\"]",
-        INVALID_REQUEST);
+        MALFORMED_POLICY_DOCUMENT);
   }
 
   @Test
@@ -147,7 +147,7 @@ public void testMissingEffectInStatementThrows() {
         "}";
 
     expectResolveThrowsForBothAuthorizers(
-        json, "IAM session policy: Effect is missing from JSON policy", 
INVALID_REQUEST);
+        json, "IAM session policy: Effect is missing from JSON policy", 
MALFORMED_POLICY_DOCUMENT);
   }
 
   @Test
@@ -193,7 +193,7 @@ public void testInvalidConditionThrows() {
 
     expectResolveThrowsForBothAuthorizers(
         json, "IAM session policy: Invalid Condition (must have operator 
StringEquals or StringLike and key name " +
-        "s3:prefix) - [\"RandomCondition\"]", INVALID_REQUEST);
+        "s3:prefix) - [\"RandomCondition\"]", MALFORMED_POLICY_DOCUMENT);
   }
 
   @Test
@@ -209,7 +209,7 @@ public void 
testInvalidConditionAttributeMissingStringEqualsThrows() {
 
     expectResolveThrowsForBothAuthorizers(
         json, "IAM session policy: Missing Condition operator value for 
StringEquals",
-        INVALID_REQUEST);
+        MALFORMED_POLICY_DOCUMENT);
   }
 
   @Test
@@ -225,7 +225,7 @@ public void testInvalidConditionAttributeStructureThrows() {
 
     expectResolveThrowsForBothAuthorizers(
         json, "IAM session policy: Invalid Condition operator value structure 
- [{\"s3:prefix\":\"folder/\"}]",
-        INVALID_REQUEST);
+        MALFORMED_POLICY_DOCUMENT);
   }
 
   @Test
@@ -234,7 +234,7 @@ public void testInvalidJsonThrows() {
 
     expectResolveThrowsForBothAuthorizers(
         invalidJson, "IAM session policy: Invalid policy JSON (most likely 
JSON structure is incorrect)",
-        INVALID_REQUEST);
+        MALFORMED_POLICY_DOCUMENT);
   }
 
   @Test
@@ -242,7 +242,8 @@ public void testJsonExceedsMaxLengthThrows() {
     final String json = createJsonStringLargerThan2048Characters();
 
     expectResolveThrowsForBothAuthorizers(
-        json, "IAM session policy: Invalid policy JSON - exceeds maximum 
length of 2048 characters", INVALID_REQUEST);
+        json, "IAM session policy: Invalid policy JSON - exceeds maximum 
length of 2048 characters",
+        MALFORMED_POLICY_DOCUMENT);
   }
 
   @Test
@@ -681,20 +682,20 @@ public void 
testValidateAndCategorizeResourcesWithInvalidArnThrows() {
   public void testValidateAndCategorizeResourcesWithArnWithNoBucketThrows() {
     expectOMExceptionWithCode(
         () -> validateAndCategorizeResources(NATIVE, 
Collections.singleton("arn:aws:s3:::")),
-        "IAM session policy: Invalid Resource Arn - arn:aws:s3:::", 
INVALID_REQUEST);
+        "IAM session policy: Invalid Resource Arn - arn:aws:s3:::", 
MALFORMED_POLICY_DOCUMENT);
     expectOMExceptionWithCode(
         () -> validateAndCategorizeResources(RANGER, 
Collections.singleton("arn:aws:s3:::")),
-        "IAM session policy: Invalid Resource Arn - arn:aws:s3:::", 
INVALID_REQUEST);
+        "IAM session policy: Invalid Resource Arn - arn:aws:s3:::", 
MALFORMED_POLICY_DOCUMENT);
   }
 
   @Test
   public void testValidateAndCategorizeResourcesWithNoResourcesThrows() {
     expectOMExceptionWithCode(
         () -> validateAndCategorizeResources(NATIVE, emptySet()), "IAM session 
policy: No Resource(s) found in policy",
-        INVALID_REQUEST);
+        MALFORMED_POLICY_DOCUMENT);
     expectOMExceptionWithCode(
         () -> validateAndCategorizeResources(RANGER, emptySet()), "IAM session 
policy: No Resource(s) found in policy",
-        INVALID_REQUEST);
+        MALFORMED_POLICY_DOCUMENT);
   }
 
   @Test
@@ -1925,7 +1926,7 @@ public void testInvalidResourceArnThrows() {
         "}";
 
     expectResolveThrowsForBothAuthorizers(
-        json, "IAM session policy: Invalid Resource Arn - arn:aws:s3:::", 
INVALID_REQUEST);
+        json, "IAM session policy: Invalid Resource Arn - arn:aws:s3:::", 
MALFORMED_POLICY_DOCUMENT);
   }
 
   private static void expectIllegalArgumentException(Runnable runnable, String 
expectedMessage) {
diff --git 
a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto 
b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
index 173b444e6f1..1102d44966d 100644
--- a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
+++ b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
@@ -578,6 +578,7 @@ enum Status {
     TOO_MANY_SNAPSHOTS = 98;
 
     REVOKED_TOKEN = 99;
+    MALFORMED_POLICY_DOCUMENT = 100;
 }
 
 /**
diff --git 
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3sts/S3STSEndpoint.java
 
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3sts/S3STSEndpoint.java
index e2dee7dc6cf..e0be5c5183d 100644
--- 
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3sts/S3STSEndpoint.java
+++ 
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3sts/S3STSEndpoint.java
@@ -88,6 +88,7 @@ public class S3STSEndpoint extends S3STSEndpointBase {
   private static final String ACCESS_DENIED = "AccessDenied";
   private static final String INVALID_CLIENT_TOKEN_ID = "InvalidClientTokenId";
   private static final String UNSUPPORTED_OPERATION = "UnsupportedOperation";
+  private static final String MALFORMED_POLICY_DOCUMENT = 
"MalformedPolicyDocument";
 
   @Inject
   private RequestIdentifier requestIdentifier;
@@ -284,12 +285,13 @@ private Response handleAssumeRole(String roleArn, String 
roleSessionName, Intege
         }
         if (omException.getResult() == 
OMException.ResultCodes.NOT_SUPPORTED_OPERATION ||
             omException.getResult() == 
OMException.ResultCodes.FEATURE_NOT_ENABLED) {
-          throw new OSTSException(
-              UNSUPPORTED_OPERATION, omException.getMessage(), 
NOT_IMPLEMENTED.getStatusCode());
+          throw new OSTSException(UNSUPPORTED_OPERATION, 
omException.getMessage(), NOT_IMPLEMENTED.getStatusCode());
         }
         if (omException.getResult() == 
OMException.ResultCodes.INVALID_REQUEST) {
-          throw new OSTSException(
-              VALIDATION_ERROR, omException.getMessage(), 
BAD_REQUEST.getStatusCode());
+          throw new OSTSException(VALIDATION_ERROR, omException.getMessage(), 
BAD_REQUEST.getStatusCode());
+        }
+        if (omException.getResult() == 
OMException.ResultCodes.MALFORMED_POLICY_DOCUMENT) {
+          throw new OSTSException(MALFORMED_POLICY_DOCUMENT, 
omException.getMessage(), BAD_REQUEST.getStatusCode());
         }
       }
       throw new OSTSException(
diff --git 
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3sts/TestS3STSEndpoint.java
 
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3sts/TestS3STSEndpoint.java
index d0eaca9a5dc..059f54e0993 100644
--- 
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3sts/TestS3STSEndpoint.java
+++ 
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3sts/TestS3STSEndpoint.java
@@ -73,6 +73,7 @@ public class TestS3STSEndpoint {
   private static final String ROLE_USER_ARN = 
"arn:aws:sts::123456789012:assumed-role/test-role/" + ROLE_SESSION_NAME;
   private static final String STS_NS = 
"https://sts.amazonaws.com/doc/2011-06-15/";;
   private static final String AWS_FAULT_NS = 
"http://webservices.amazon.com/AWSFault/2005-15-09";;
+  private static final String REQUEST_ID = "test-request-id";
 
   @BeforeEach
   public void setup() throws Exception {
@@ -105,7 +106,7 @@ public void setup() throws Exception {
     auditLogger = mock(AuditLogger.class);
     endpoint.setAuditLogger(auditLogger);
     
-    when(requestIdentifier.getRequestId()).thenReturn("test-request-id");
+    when(requestIdentifier.getRequestId()).thenReturn(REQUEST_ID);
     endpoint.setRequestIdentifier(requestIdentifier);
 
     SignatureInfo signatureInfo = new 
SignatureInfo.Builder(SignatureInfo.Version.V4)
@@ -212,8 +213,7 @@ public void testStsUnsupportedActionWithVersionSupplied() 
throws Exception {
     assertEquals(400, ex.getHttpCode());
     verifyNoInteractions(auditLogger);
 
-    final String requestId = "test-request-id";
-    ex.setRequestId(requestId);
+    ex.setRequestId(REQUEST_ID);
     assertStsErrorXml(ex.toXml(), AWS_FAULT_NS, "Sender", "InvalidAction",
         "Could not find operation UnsupportedAction for version 2011-06-15");
   }
@@ -226,8 +226,7 @@ public void 
testStsUnsupportedActionWithVersionNotSupplied() throws Exception {
     assertEquals(400, ex.getHttpCode());
     verifyNoInteractions(auditLogger);
 
-    final String requestId = "test-request-id";
-    ex.setRequestId(requestId);
+    ex.setRequestId(REQUEST_ID);
     assertStsErrorXml(ex.toXml(), AWS_FAULT_NS, "Sender", "InvalidAction",
         "Could not find operation UnsupportedAction for version 
NO_VERSION_SPECIFIED");
   }
@@ -241,8 +240,7 @@ public void testStsAssumeRoleWithInvalidVersion() throws 
Exception {
     verify(auditLogger).logWriteFailure(any(AuditMessage.class));
     verify(auditLogger, never()).logWriteSuccess(any(AuditMessage.class));
 
-    final String requestId = "test-request-id";
-    ex.setRequestId(requestId);
+    ex.setRequestId(REQUEST_ID);
     assertStsErrorXml(ex.toXml(), AWS_FAULT_NS, "Sender", "InvalidAction",
         "Could not find operation AssumeRole for version 2000-01-01");
   }
@@ -256,8 +254,7 @@ public void testStsInvalidDuration() throws Exception {
     verify(auditLogger).logWriteFailure(any(AuditMessage.class));
     verify(auditLogger, never()).logWriteSuccess(any(AuditMessage.class));
 
-    final String requestId = "test-request-id";
-    ex.setRequestId(requestId);
+    ex.setRequestId(REQUEST_ID);
     assertStsErrorXml(ex.toXml(), STS_NS, "Sender", "ValidationError", 
"Invalid Value: DurationSeconds");
   }
 
@@ -285,8 +282,7 @@ public void testStsPolicyTooLarge() throws Exception {
     verify(auditLogger).logWriteFailure(any(AuditMessage.class));
     verify(auditLogger, never()).logWriteSuccess(any(AuditMessage.class));
 
-    final String requestId = "test-request-id";
-    ex.setRequestId(requestId);
+    ex.setRequestId(REQUEST_ID);
     assertStsErrorXml(ex.toXml(), STS_NS, "Sender", "ValidationError",
         "Value '" + tooLargePolicy + "' at 'policy' failed to satisfy 
constraint: Member " +
         "must have length less than or equal to 2048");
@@ -302,8 +298,7 @@ public void testStsInvalidRoleArn() throws Exception {
     verify(auditLogger).logWriteFailure(any(AuditMessage.class));
     verify(auditLogger, never()).logWriteSuccess(any(AuditMessage.class));
 
-    final String requestId = "test-request-id";
-    ex.setRequestId(requestId);
+    ex.setRequestId(REQUEST_ID);
     assertStsErrorXml(ex.toXml(), STS_NS, "Sender", "ValidationError",
         "Invalid role ARN (does not start with arn:aws:iam::)");
   }
@@ -317,8 +312,7 @@ public void testStsMissingRoleArn() throws Exception {
     verify(auditLogger).logWriteFailure(any(AuditMessage.class));
     verify(auditLogger, never()).logWriteSuccess(any(AuditMessage.class));
 
-    final String requestId = "test-request-id";
-    ex.setRequestId(requestId);
+    ex.setRequestId(REQUEST_ID);
     assertStsErrorXml(ex.toXml(), STS_NS, "Sender", "ValidationError", "Value 
null at 'roleArn'");
   }
 
@@ -333,8 +327,7 @@ public void testStsInvalidRoleArnMissingRoleName() throws 
Exception {
     verify(auditLogger).logWriteFailure(any(AuditMessage.class));
     verify(auditLogger, never()).logWriteSuccess(any(AuditMessage.class));
 
-    final String requestId = "test-request-id";
-    ex.setRequestId(requestId);
+    ex.setRequestId(REQUEST_ID);
     assertStsErrorXml(ex.toXml(), STS_NS, "Sender", "ValidationError", 
"Invalid role ARN: missing role name");
   }
 
@@ -349,8 +342,7 @@ public void testStsInvalidRoleArnMissingAccountId() throws 
Exception {
     verify(auditLogger).logWriteFailure(any(AuditMessage.class));
     verify(auditLogger, never()).logWriteSuccess(any(AuditMessage.class));
 
-    final String requestId = "test-request-id";
-    ex.setRequestId(requestId);
+    ex.setRequestId(REQUEST_ID);
     assertStsErrorXml(ex.toXml(), STS_NS, "Sender", "ValidationError", 
"Invalid AWS account ID in ARN"
     );
   }
@@ -363,8 +355,7 @@ public void testStsWhenActionNotImplemented() throws 
Exception {
     assertEquals(501, ex.getHttpCode());
     verifyNoInteractions(auditLogger);
 
-    final String requestId = "test-request-id";
-    ex.setRequestId(requestId);
+    ex.setRequestId(REQUEST_ID);
     assertStsErrorXml(ex.toXml(), AWS_FAULT_NS, "Sender", "InvalidAction",
         "Operation GetSessionToken is not supported yet.");
   }
@@ -378,8 +369,7 @@ public void testStsMissingRoleSessionName() throws 
Exception {
     verify(auditLogger).logWriteFailure(any(AuditMessage.class));
     verify(auditLogger, never()).logWriteSuccess(any(AuditMessage.class));
 
-    final String requestId = "test-request-id";
-    ex.setRequestId(requestId);
+    ex.setRequestId(REQUEST_ID);
     assertStsErrorXml(ex.toXml(), STS_NS, "Sender", "ValidationError", "Value 
null at 'roleSessionName'");
   }
 
@@ -393,8 +383,7 @@ public void 
testStsInvalidRoleSessionNameWithInvalidCharacter() throws Exception
     verify(auditLogger).logWriteFailure(any(AuditMessage.class));
     verify(auditLogger, never()).logWriteSuccess(any(AuditMessage.class));
 
-    final String requestId = "test-request-id";
-    ex.setRequestId(requestId);
+    ex.setRequestId(REQUEST_ID);
     assertStsErrorXml(
         ex.toXml(), STS_NS, "Sender", "ValidationError", "1 validation error 
detected: " +
         "Invalid character '/' in RoleSessionName: it must be 2-64 characters 
long and contain only alphanumeric " +
@@ -411,8 +400,7 @@ public void testStsInvalidRoleSessionNameTooShort() throws 
Exception {
     verify(auditLogger).logWriteFailure(any(AuditMessage.class));
     verify(auditLogger, never()).logWriteSuccess(any(AuditMessage.class));
 
-    final String requestId = "test-request-id";
-    ex.setRequestId(requestId);
+    ex.setRequestId(REQUEST_ID);
     assertStsErrorXml(
         ex.toXml(), STS_NS, "Sender", "ValidationError", "1 validation error 
detected: Invalid RoleSessionName " +
         "length 1: it must be 2-64 characters long and contain only 
alphanumeric characters and +, =, ,, ., @, -");
@@ -429,8 +417,7 @@ public void testStsInvalidRoleArnResourceType() throws 
Exception {
     verify(auditLogger).logWriteFailure(any(AuditMessage.class));
     verify(auditLogger, never()).logWriteSuccess(any(AuditMessage.class));
 
-    final String requestId = "test-request-id";
-    ex.setRequestId(requestId);
+    ex.setRequestId(REQUEST_ID);
     assertStsErrorXml(ex.toXml(), STS_NS, "Sender", "ValidationError", 
"Invalid role ARN (unexpected field count)");
   }
 
@@ -446,8 +433,7 @@ public void testStsInternalFailureWhenBackendThrows() 
throws Exception {
     verify(auditLogger).logWriteFailure(any(AuditMessage.class));
     verify(auditLogger, never()).logWriteSuccess(any(AuditMessage.class));
 
-    final String requestId = "test-request-id";
-    ex.setRequestId(requestId);
+    ex.setRequestId(REQUEST_ID);
     assertStsErrorXml(ex.toXml(), STS_NS, "Receiver", "InternalFailure", "An 
internal error has occurred.");
   }
 
@@ -463,12 +449,76 @@ public void testStsAccessDenied() throws Exception {
     verify(auditLogger).logWriteFailure(any(AuditMessage.class));
     verify(auditLogger, never()).logWriteSuccess(any(AuditMessage.class));
 
-    final String requestId = "test-request-id";
-    ex.setRequestId(requestId);
+    ex.setRequestId(REQUEST_ID);
     assertStsErrorXml(ex.toXml(), STS_NS, "Sender", "AccessDenied",
         "User is not authorized to perform: sts:AssumeRole on resource: " + 
ROLE_ARN);
   }
 
+  @Test
+  public void 
testStsUnsupportedOperationWhenBackendThrowsNotSupportedOperation() throws 
Exception {
+    when(objectStore.assumeRole(anyString(), anyString(), anyInt(), any(), 
anyString()))
+        .thenThrow(new OMException("Operation is not supported", 
OMException.ResultCodes.NOT_SUPPORTED_OPERATION));
+
+    final OSTSException ex = assertThrows(OSTSException.class, () ->
+        endpoint.get("AssumeRole", ROLE_ARN, ROLE_SESSION_NAME, 3600, 
"2011-06-15", null));
+
+    assertEquals(501, ex.getHttpCode());
+    verify(auditLogger).logWriteFailure(any(AuditMessage.class));
+    verify(auditLogger, never()).logWriteSuccess(any(AuditMessage.class));
+
+    ex.setRequestId(REQUEST_ID);
+    assertStsErrorXml(ex.toXml(), STS_NS, "Sender", "UnsupportedOperation", 
"Operation is not supported");
+  }
+
+  @Test
+  public void testStsUnsupportedOperationWhenBackendThrowsFeatureNotEnabled() 
throws Exception {
+    when(objectStore.assumeRole(anyString(), anyString(), anyInt(), any(), 
anyString()))
+        .thenThrow(new OMException("Feature is not enabled", 
OMException.ResultCodes.FEATURE_NOT_ENABLED));
+
+    final OSTSException ex = assertThrows(OSTSException.class, () ->
+        endpoint.get("AssumeRole", ROLE_ARN, ROLE_SESSION_NAME, 3600, 
"2011-06-15", null));
+
+    assertEquals(501, ex.getHttpCode());
+    verify(auditLogger).logWriteFailure(any(AuditMessage.class));
+    verify(auditLogger, never()).logWriteSuccess(any(AuditMessage.class));
+
+    ex.setRequestId(REQUEST_ID);
+    assertStsErrorXml(ex.toXml(), STS_NS, "Sender", "UnsupportedOperation", 
"Feature is not enabled");
+  }
+
+  @Test
+  public void testStsValidationErrorWhenBackendThrowsInvalidRequest() throws 
Exception {
+    when(objectStore.assumeRole(anyString(), anyString(), anyInt(), any(), 
anyString()))
+        .thenThrow(new OMException("Invalid request parameter", 
OMException.ResultCodes.INVALID_REQUEST));
+
+    final OSTSException ex = assertThrows(OSTSException.class, () ->
+        endpoint.get("AssumeRole", ROLE_ARN, ROLE_SESSION_NAME, 3600, 
"2011-06-15", null));
+
+    assertEquals(400, ex.getHttpCode());
+    verify(auditLogger).logWriteFailure(any(AuditMessage.class));
+    verify(auditLogger, never()).logWriteSuccess(any(AuditMessage.class));
+
+    ex.setRequestId(REQUEST_ID);
+    assertStsErrorXml(ex.toXml(), STS_NS, "Sender", "ValidationError", 
"Invalid request parameter");
+  }
+
+  @Test
+  public void 
testStsMalformedPolicyDocumentWhenBackendThrowsMalformedPolicyDocument() throws 
Exception {
+    when(objectStore.assumeRole(anyString(), anyString(), anyInt(), any(), 
anyString()))
+        .thenThrow(new OMException("Malformed session policy", 
OMException.ResultCodes.MALFORMED_POLICY_DOCUMENT));
+
+    final OSTSException ex = assertThrows(OSTSException.class, () ->
+        endpoint.get("AssumeRole", ROLE_ARN, ROLE_SESSION_NAME, 3600, 
"2011-06-15", null));
+
+    assertEquals(400, ex.getHttpCode());
+    verify(auditLogger).logWriteFailure(any(AuditMessage.class));
+    verify(auditLogger, never()).logWriteSuccess(any(AuditMessage.class));
+
+    ex.setRequestId(REQUEST_ID);
+    assertStsErrorXml(
+        ex.toXml(), STS_NS, "Sender", "MalformedPolicyDocument", "Malformed 
session policy");
+  }
+
   @Test
   public void testStsIOExceptionWrappedAsInternalFailure() throws Exception {
     when(objectStore.assumeRole(anyString(), anyString(), anyInt(), any(), 
anyString()))
@@ -481,8 +531,7 @@ public void testStsIOExceptionWrappedAsInternalFailure() 
throws Exception {
     verify(auditLogger).logWriteFailure(any(AuditMessage.class));
     verify(auditLogger, never()).logWriteSuccess(any(AuditMessage.class));
 
-    final String requestId = "test-request-id";
-    ex.setRequestId(requestId);
+    ex.setRequestId(REQUEST_ID);
     assertStsErrorXml(ex.toXml(), STS_NS, "Receiver", "InternalFailure", "An 
internal error has occurred.");
   }
 
@@ -500,8 +549,7 @@ public void testStsMultipleValidationErrors() throws 
Exception {
     verify(auditLogger).logWriteFailure(any(AuditMessage.class));
     verify(auditLogger, never()).logWriteSuccess(any(AuditMessage.class));
 
-    final String requestId = "test-request-id";
-    ex.setRequestId(requestId);
+    ex.setRequestId(REQUEST_ID);
 
     final String xml = ex.toXml();
     // The order of individual validation errors is not guaranteed because 
it's a HashSet, so check
@@ -540,6 +588,6 @@ private static void assertStsErrorXml(String xml, String 
expectedNamespace, Stri
     assertTrue(message.contains(expectedMessageContains), "Expected message to 
contain: " + expectedMessageContains);
 
     final String requestId = 
doc.getElementsByTagName("RequestId").item(0).getTextContent();
-    assertEquals("test-request-id", requestId);
+    assertEquals(REQUEST_ID, requestId);
   }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to