Skip to content

Commit f0f4327

Browse files
committed
adding header handling in routeVeam + unit tests
This commit updates the validation logic for query parameters in the Veeam route handler, ensuring better compatibility with AWS SDK clients and stricter enforcement of supported actions. The main changes include introducing case-insensitive query key handling, explicit support for AWS SDK auxiliary parameters, and improved error handling for unsupported or mismatched actions. Unit tests have been added to verify these behaviors throughout. Issue: CLDSRV-806
1 parent 60b7aa4 commit f0f4327

File tree

2 files changed

+72
-2
lines changed

2 files changed

+72
-2
lines changed

lib/routes/routeVeeam.js

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ const apiToAction = {
2929
LIST: 'ListObjects',
3030
};
3131

32+
const allowedSdkQueryKeys = new Set([
33+
'x-id',
34+
'x-amz-user-agent',
35+
'x-amz-sdk-invocation-id',
36+
'x-amz-sdk-request',
37+
]);
38+
3239
const routeMap = {
3340
GET: getVeeamFile,
3441
PUT: putVeeamFile,
@@ -67,8 +74,33 @@ function checkBucketAndKey(bucketName, objectKey, requestQueryParams, method, lo
6774
// Download relies on GETs calls with auth in query parameters, that can be
6875
// checked if 'X-Amz-Credential' is included.
6976
// Deletion requires that the tags of the object are returned.
70-
if (requestQueryParams && Object.keys(requestQueryParams).length > 0
71-
&& !(method === 'GET' && (requestQueryParams['X-Amz-Credential'] || ('tagging' in requestQueryParams)))) {
77+
const originalQuery = requestQueryParams || {};
78+
const normalizedQueryKeys = new Map(
79+
Object.keys(originalQuery).map(key => [key.toLowerCase(), key])
80+
);
81+
const isPresignedGet = method === 'GET'
82+
&& (normalizedQueryKeys.has('x-amz-credential')
83+
|| normalizedQueryKeys.has('tagging'));
84+
85+
if (!isPresignedGet && normalizedQueryKeys.size > 0) {
86+
const unsupportedKeys = Array.from(normalizedQueryKeys.keys())
87+
.filter(lowerKey => {
88+
if (allowedSdkQueryKeys.has(lowerKey)) {
89+
return false;
90+
}
91+
if (lowerKey.startsWith('x-amz-sdk-')) {
92+
return false;
93+
}
94+
return true;
95+
});
96+
if (unsupportedKeys.length > 0) {
97+
return errorInstances.InvalidRequest
98+
.customizeDescription('The Veeam SOSAPI folder does not support this action.');
99+
}
100+
}
101+
const xIdOriginalKey = normalizedQueryKeys.get('x-id');
102+
const xIdValue = xIdOriginalKey ? originalQuery[xIdOriginalKey] : undefined;
103+
if (xIdValue && xIdValue !== apiToAction[method]) {
72104
return errorInstances.InvalidRequest
73105
.customizeDescription('The Veeam SOSAPI folder does not support this action.');
74106
}

tests/unit/internal/routeVeeam.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,44 @@ describe('RouteVeeam: checkBucketAndKey', () => {
7777
assert.strictEqual(routeVeeam.checkBucketAndKey(...test), undefined);
7878
});
7979
});
80+
81+
it('should allow AWS SDK x-id=PutObject query on PUT for system.xml', () => {
82+
const err = routeVeeam.checkBucketAndKey(
83+
'test',
84+
'.system-d26a9498-cb7c-4a87-a44a-8ae204f5ba6c/system.xml',
85+
{ 'x-id': 'PutObject' },
86+
'PUT',
87+
log,
88+
);
89+
assert.strictEqual(err, undefined);
90+
});
91+
92+
it('should allow AWS SDK auxiliary x-amz-sdk-* query params on PUT for system.xml', () => {
93+
const err = routeVeeam.checkBucketAndKey(
94+
'test',
95+
'.system-d26a9498-cb7c-4a87-a44a-8ae204f5ba6c/system.xml',
96+
{
97+
'x-id': 'PutObject',
98+
'x-amz-sdk-request': 'attempt=1',
99+
'x-amz-sdk-invocation-id': 'abc-123',
100+
'x-amz-user-agent': 'aws-sdk-js-v3',
101+
},
102+
'PUT',
103+
log,
104+
);
105+
assert.strictEqual(err, undefined);
106+
});
107+
108+
it('should reject mismatched x-id value on PUT for system.xml', () => {
109+
const err = routeVeeam.checkBucketAndKey(
110+
'test',
111+
'.system-d26a9498-cb7c-4a87-a44a-8ae204f5ba6c/system.xml',
112+
{ 'x-id': 'GetObject' },
113+
'PUT',
114+
log,
115+
);
116+
assert.strictEqual(err.is.InvalidRequest, true);
117+
});
80118
});
81119

82120
describe('RouteVeeam: checkBucketAndKey', () => {

0 commit comments

Comments
 (0)