aws / aws/aws-sdk-java-v2

QueryProtocolUnmarshaller unmarshall() relies on the order of XML elements

Open
#2,638 2 comments 1 reaction 0 assignees View on GitHub
feature-request p3 third-party
Dominant language
Java
Stars
2.6k
Forks
1k
Avg merge
2d 9h
Merged PRs (30d)
51

Description

Implementation of unmarhall() in QueryProtocolUnmarshaller assumes that response is the first XML element

## Describe the bug

Method has implementation as follows

```
public Pair> unmarshall(SdkPojo sdkPojo,
SdkHttpFullResponse response) {
XmlElement document = response.content().map(XmlDomParser::parse).orElse(XmlElement.empty());
XmlElement resultRoot = hasResultWrapper ? document.getFirstChild() : document;
return Pair.of(unmarshall(sdkPojo, resultRoot, response), parseMetadata(document));
}
```

If ResponseMetadata element is first, the XML parsing will return incorrect result, although XML is in a valid format.
Implementation relies on the strict order of XML elements.

This can be reproduced with Ceph storage, which for listing IAM roles and possibly other operations returns ResponseMetadata as the first element.

## Expected Behavior
Parse XML without relying on the order of children

## Current Behavior
Operation of listing roles is successful but with Ceph storage it fails due to different order of children.

Example structure returned
```


tx000000000000000000bf3-00610902d3-df5c88-something




800c18b6-8259-4697-b1b0-7498d9487446
exampleRole
/base/
arn:aws:iam::demo:role/base/exampleRole
2021-07-20T10:03:45.743Z
3600
{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Federated":["arn:aws:iam:::oidc-provider/localhost.example.com:8443/auth/realms/demo"]},"Action":["sts:AssumeRoleWithWebIdentity"],"Condition":[{"StringEquals":{"localhost.example.com:8443/auth/realms/demo:app_id":"account"}},{"StringEquals":{"localhost.example.com:8443/auth/realms/demo:sub":["c7d03371-6d87-4b46-80ef-518eec3f7aa6"]}}]}]}


```

## Possible Solution
Reimplement the logic as below or similar
```
public Pair> unmarshall(SdkPojo sdkPojo, SdkHttpFullResponse response) {
XmlElement document = response.content().map(XmlDomParser::parse).orElse(XmlElement.empty());
XmlElement resultRoot;
if (hasResultWrapper) {
Optional element = document.children().stream().filter(e -> !"ResponseMetadata".equals(e.elementName())).findFirst();
resultRoot = element.orElse(document.getFirstChild());
} else {
resultRoot = document;
}
return Pair.of(unmarshall(sdkPojo, resultRoot, response), parseMetadata(document));
}
```
## Your Environment
Reproducible with currently used 2.16.103

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.