HDDS-16110. [STS] Update key in sts revocation table - #11030
Conversation
chihsuan
left a comment
There was a problem hiding this comment.
Thanks for the patch! @fmorg-git I left a few comments. Otherwise, this looks good.
| return omClientResponse; | ||
| } | ||
|
|
||
| private static void validateRevokeRequestFields(OzoneManagerProtocolProtos.RevokeSTSTokenRequest revokeReq) |
There was a problem hiding this comment.
Since the value comes directly from the request, allowing | could create a revoke-key collision across users. Would it make sense to validate tempAccessKeyId against its generated format (ASIA plus 20 [0-9A-Z] characters) and bound both field lengths??
There was a problem hiding this comment.
good catch - updated
| throw new SecretManager.InvalidToken("Failed to decode STS token string: " + e); | ||
| } catch (IOException | RuntimeException e) { | ||
| throw new SecretManager.InvalidToken( | ||
| "Failed to decode STS token string: " + e + " for encodedToken: " + encodedToken); |
There was a problem hiding this comment.
Including the full client-provided token here could make failed requests unusually noisy. Perhaps the token length, a short prefix, or a hash would provide enough debugging context without writing the entire value to the response and logs. What do you think?
There was a problem hiding this comment.
updated (sorry I forgot why I left it out originally)
| // created the token) so the audit trail is not limited to the opaque tempAccessKeyId. | ||
| final String originalAccessKeyId = AuditUtils.getStsOriginalAccessKeyId(s3Auth.getSessionToken()); | ||
| if (originalAccessKeyId != null) { | ||
| auditMap.put("originalAccessKeyId", originalAccessKeyId); |
There was a problem hiding this comment.
nit: this uses the literal "originalAccessKeyId" while the OM side goes through OzoneConsts.S3_REVOKESTSTOKEN_ORIGINAL_ACCESS_KEY_ID. Could this share a constant so the two audit logs can't drift?
chihsuan
left a comment
There was a problem hiding this comment.
Thanks for the update! @fmorg-git While taking another look, I noticed a couple of additional issues. Please see new inline comments for the details. Thanks.
| public static final String S3_STS_ORIGINAL_ACCESS_KEY_ID = "originalAccessKeyId"; | ||
| public static final String S3_STS_TEMP_ACCESS_KEY_ID = "tempAccessKeyId"; | ||
| public static final String S3_REVOKESTSTOKEN_ORIGINAL_ACCESS_KEY_ID = S3_STS_ORIGINAL_ACCESS_KEY_ID; | ||
| public static final String S3_REVOKESTSTOKEN_TEMP_ACCESS_KEY_ID = S3_STS_TEMP_ACCESS_KEY_ID; |
There was a problem hiding this comment.
Just curious, do we need the two S3_REVOKESTSTOKEN_* aliases here?
There was a problem hiding this comment.
these are no longer here after the redesign
| `tempAccessKeyId|originalAccessKeyId`. Because `tempAccessKeyId` is always `ASIA` followed by characters drawn only | ||
| from `[0-9A-Z]`, it can never contain the `|` delimiter, so no escaping is needed even though `originalAccessKeyId` | ||
| is unconstrained. In this way, specific STS tokens can be revoked as opposed | ||
| to all tokens. Furthermore, |
There was a problem hiding this comment.
Note: Furthermore, is left on its own short line after the rewrap, and there are two spaces before it. Could we improve this so it's easier to read?
There was a problem hiding this comment.
this is no longer here after the redesign
| final STSTokenIdentifier stsTokenIdentifier = STSSecurityUtil.constructValidateAndDecryptSTSToken( | ||
| sessionToken, ozoneManager.getSecretKeyClient(), CLOCK); | ||
| final String originalAccessKeyId = stsTokenIdentifier.getOriginalAccessKeyId(); | ||
| final String originalAccessKeyId = revokeReq.getOriginalAccessKeyId(); |
There was a problem hiding this comment.
I noticed that both tempAccessKeyId and originalAccessKeyId now come directly from the request. If originalAccessKeyId is mistyped, OM will store a different revocation key and still return success, while the token remains usable because authentication derives its key from the token itself.
Should we validate that the two IDs belong to the same issued token, or return a distinguishable result when we can't confirm the pairing?
There was a problem hiding this comment.
this is no longer applicable after redesign. Only originalAccessKeyId is there and there is a check in S3RevokeSTSTokenRequest that the originalAccessKeyId is valid.
| if (s3Auth != null) { | ||
| // For STS temporary credentials, record the originalAccessKeyId (the permanent principal that | ||
| // created the token) so the audit trail is not limited to the opaque tempAccessKeyId. | ||
| final String originalAccessKeyId = AuditUtils.getStsOriginalAccessKeyId(s3Auth.getSessionToken()); |
There was a problem hiding this comment.
originalAccessKeyId is extracted from the client-provided session token before OM validates the token signature. Since the same path is also used for failure audit messages, a malformed or unauthenticated request could record an arbitrary identity in this field. Would it make sense to mark it as client-provided/unverified, or only include it after successful validation?
Please describe your PR in detail:
TestAuditUtils), it was noticed certain inputs could cause the token parsing to fail that were not already covered, so this PR addresses that as well.What is the link to the Apache JIRA
https://issues.apache.org/jira/browse/HDDS-16110
How was this patch tested?