Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
e96df8e
HDDS-13887. [STS] Protobuf Plumbing for AssumeRole Requests (#9254)
fmorg-git Nov 12, 2025
281a5b3
HDDS-13848. [STS] Artifacts for Ranger to authorize STS token (#9214)
fmorg-git Nov 14, 2025
7eaebe6
HDDS-13888. [STS] Introduce S3AssumeRoleRequest and S3AssumeRoleRespo…
fmorg-git Nov 14, 2025
b0ae8b5
Merge branch 'master' into HDDS-13323-sts
Nov 14, 2025
a8c8688
HDDS-13909. [STS] Introduce STSTokenIdentifier class (#9277)
fmorg-git Nov 17, 2025
b79a8dd
HDDS-13724. [STS] Part 1 - Create utility to convert IAM policy to gr…
fmorg-git Nov 18, 2025
9d3c32f
HDDS-13950. [STS] Introduce STSTokenSecretManager to sign STS tokens …
fmorg-git Nov 19, 2025
b4ff104
HDDS-13925. [STS] Part 2 - Create utility to convert IAM policy to gr…
fmorg-git Nov 25, 2025
c63f444
HDDS-13961. [STS] Encrypt secretAccessKey in session token (#9344)
fmorg-git Dec 2, 2025
934f4c1
HDDS-13926. [STS] Part 3 - Create utility to convert IAM policy to gr…
fmorg-git Dec 4, 2025
3685237
HDDS-13997. [STS] Plumbing for passing STS token through S3 api proce…
fmorg-git Dec 5, 2025
8f7ec10
HDDS-14066. [STS] Database updates for revoked STS tokens (#9420)
fmorg-git Dec 5, 2025
3d17704
HDDS-14067. [STS] Plumbing and CLI utility to revoke STS token (#9435)
fmorg-git Dec 8, 2025
2062a06
HDDS-13942. [STS] Part 4 - Create utility to convert IAM policy to gr…
fmorg-git Dec 9, 2025
ae4bdb3
HDDS-14091. [STS] Deny access if STS token is found in revoked table …
fmorg-git Dec 17, 2025
0818652
HDDS-14011. [STS] Ranger interactions for STS tokens (assumeRole and …
fmorg-git Dec 19, 2025
a47b0b4
HDDS-14067. [STS] Plumbing and CLI utility to revoke STS token (#9507)
fmorg-git Dec 31, 2025
0b2db9c
HDDS-14373. [STS] Revoked STS token logic tweaks (#9604)
fmorg-git Jan 8, 2026
c63f009
HDDS-14094. [STS] Background service to remove revoked tokens that ar…
fmorg-git Jan 9, 2026
2cf4e91
HDDS-14364. [STS] Revoked permanent credential must render all associ…
fmorg-git Jan 19, 2026
bf1453d
HDDS-13345. STS port and endpoint skeleton (#9343)
len548 Jan 19, 2026
56da388
HDDS-14150. [STS] Connect STS Endpoint to Backend Processing (#9673)
fmorg-git Jan 27, 2026
bb2b540
HDDS-14514. [STS] Revamp error handling in endpoint to conform to AWS…
fmorg-git Jan 28, 2026
0f3b26b
HDDS-14420. [STS] Add audit logging to endpoint and OzoneManager for …
fmorg-git Jan 30, 2026
4b450b4
HDDS-14472. [STS] Refactor constants and validation methods to shared…
fmorg-git Jan 30, 2026
7991b3a
HDDS-14538. [STS] Leader OM should generate access key and secret and…
fmorg-git Feb 4, 2026
6ff9712
HDDS-14681. [STS] Support StringLike Condition operator in IAM sessio…
fmorg-git Feb 20, 2026
f9bec4b
HDDS-14711. [STS] Ensure accessKeyId is valid for sessionToken (#9820)
fmorg-git Feb 26, 2026
e63936b
HDDS-14716. [STS] Use MalformedPolicyDocument error code for IAM Sess…
fmorg-git Feb 27, 2026
f7c62ae
Merge remote-tracking branch 'origin/master' into HDDS-13323-sts
adoroszlai Mar 12, 2026
5a4e49f
HDDS-14779. [STS] Part 1 - IAM Session Policy and ListBucket improvem…
fmorg-git Apr 1, 2026
538a8f2
HDDS-14801. [STS] Part 2 - IAM Session Policy and ListBucket improvem…
fmorg-git Apr 2, 2026
2a855ae
HDDS-14808. [STS] Part 4 - IAM Session Policy and ListBucket improvem…
fmorg-git Apr 13, 2026
1f723f7
HDDS-14851. [STS] Better Handling for PayloadTooLarge and Small Perf …
fmorg-git Apr 14, 2026
9b3577e
HDDS-14847. [STS] Expose ExpiredToken Error (#9935)
fmorg-git Apr 14, 2026
9504881
HDDS-14809. [STS] Part 5 - IAM Session Policy and ListBucket improvem…
fmorg-git Apr 21, 2026
1810c0d
HDDS-14861. [STS] Fix Latent S3 API issue when ListBuckets Missing a …
fmorg-git Apr 21, 2026
37a224b
HDDS-14899. [STS] Updates to ACLs in IamSessionPolicyResolver (#9977)
fmorg-git May 1, 2026
603a8ab
Merge remote-tracking branch 'upstream/master' into HDDS-13323-sts
May 13, 2026
5665462
HDDS-14935. [STS] Handle Latent Inconsistencies in S3 API Acl Checks …
fmorg-git May 27, 2026
fd0ae5c
HDDS-15137. [STS] Ensure each S3 API has an associated S3 Action (#10…
fmorg-git Jun 12, 2026
9f23333
HDDS-15182. Avoid extra read for modification time on CopyObject/Copy…
fmorg-git Jun 24, 2026
11f957c
HDDS-15194. [STS] Update IamSessionPolicyResolver to return S3 Action…
fmorg-git Jun 28, 2026
ef10673
HDDS-15771. [STS] Add s3Action for expected bucket owner condition ch…
fmorg-git Jul 8, 2026
79b8227
HDDS-15861. [STS] Actions must not be sent in RequestContext to Autho…
fmorg-git Jul 16, 2026
dc3b37d
HDDS-15984. [STS] Improve s3:prefix Condition handling and reject uns…
fmorg-git Jul 31, 2026
26380fd
Merge remote-tracking branch 'upstream/master' into HDDS-13323-sts
Aug 1, 2026
c41e9d6
Merge remote-tracking branch 'upstream/master' into HDDS-13323-sts
Aug 10, 2026
fd45502
HDDS-14810. [STS] Part 2 - STS Ranger Smoke Tests (#9902)
fmorg-git Aug 14, 2026
a48cf12
HDDS-14811. [STS] Part 3 - STS Ranger Smoke Tests (#9903)
fmorg-git Aug 17, 2026
113e3d0
HDDS-16187. [STS] Fix Latent S3 DeleteObjects Issue (#11019)
fmorg-git Aug 17, 2026
3a56b7f
HDDS-15325. [STS] Polaris Smoke Test (#10315)
fmorg-git Aug 18, 2026
2b5240b
Merge remote-tracking branch 'upstream/master' into HDDS-13323-sts
Aug 18, 2026
ff6f7e0
Merge remote-tracking branch 'upstream/master' into HDDS-13323-sts
Aug 19, 2026
d5a76c5
HDDS-16240. [STS] Remove /sts from endpoint to enhance compatibility …
fmorg-git Aug 21, 2026
5000f28
HDDS-16186. Move sts robot tests out of misc suite (#11042)
fmorg-git Aug 24, 2026
dc169f6
HDDS-16110. [STS] Update key in sts revocation table (#11095)
fmorg-git Aug 26, 2026
5a0707f
HDDS-16472. [STS] Tighten session policy validation (#11103)
fmorg-git Aug 29, 2026
30a353d
HDDS-16371. [STS] Better messaging for invalid endpoint path and prev…
fmorg-git Sep 3, 2026
0ab01a4
HDDS-16313. [STS] Handle linked bucket and session policies (#11196)
fmorg-git Sep 3, 2026
5bc5a1e
HDDS-16290. [STS] Implement GetCallerIdentity API (#11121)
fmorg-git Sep 4, 2026
556c15e
Merge remote-tracking branch 'origin/HDDS-13323-sts' into master
ChenSammi Sep 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,10 @@ public final class OzoneConfigKeys {
public static final String OZONE_CLIENT_ELASTIC_BYTE_BUFFER_POOL_MAX_SIZE =
"ozone.client.elastic.byte.buffer.pool.max.size";
public static final String OZONE_CLIENT_ELASTIC_BYTE_BUFFER_POOL_MAX_SIZE_DEFAULT = "16GB";

public static final String OZONE_S3G_STS_HTTP_ENABLED_KEY =
"ozone.s3g.sts.http.enabled";
public static final boolean OZONE_S3G_STS_HTTP_ENABLED_DEFAULT = false;

/**
* There is no need to instantiate this class.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,8 @@ public final class OzoneConsts {
public static final String S3_GETSECRET_USER = "S3GetSecretUser";
public static final String S3_SETSECRET_USER = "S3SetSecretUser";
public static final String S3_REVOKESECRET_USER = "S3RevokeSecretUser";
public static final String S3_REVOKESTSTOKEN_USER = "S3RevokeSTSTokenUser";
public static final String S3_STS_TEMP_ACCESS_KEY_ID = "tempAccessKeyId";
public static final String RENAMED_KEYS_MAP = "renamedKeysMap";
public static final String UNRENAMED_KEYS_MAP = "unRenamedKeysMap";
public static final String MULTIPART_UPLOAD_PART_NUMBER = "partNumber";
Expand Down
69 changes: 69 additions & 0 deletions hadoop-hdds/common/src/main/resources/ozone-default.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2116,6 +2116,54 @@
will be used for http authentication.
</description>
</property>

<property>
<name>ozone.s3g.sts.http.enabled</name>
<value>false</value>
<tag>OZONE, S3GATEWAY</tag>
<description>
The boolean which enables the Ozone S3Gateway STS endpoint.
</description>
</property>
<property>
<name>ozone.s3g.sts.http-bind-host</name>
<value>0.0.0.0</value>
<tag>OZONE, S3GATEWAY</tag>
<description>
The bind host for the S3 Gateway STS HTTP server.
If this optional address is set, it overrides only the hostname portion of
ozone.s3g.sts.http-address.
If not set, the value of ozone.s3g.http-bind-host is used.
</description>
</property>
<property>
<name>ozone.s3g.sts.http-address</name>
<value>0.0.0.0:9880</value>
<tag>OZONE, S3GATEWAY</tag>
<description>
The HTTP address for the S3 Gateway STS endpoint.
</description>
</property>
<property>
<name>ozone.s3g.sts.https-bind-host</name>
<value>0.0.0.0</value>
<tag>OZONE, S3GATEWAY</tag>
<description>
The bind host for the S3 Gateway STS HTTPS server.
If this optional address is set, it overrides only the hostname portion of
ozone.s3g.sts.http-address.
If not set, the value of ozone.s3g.https-bind-host is used.
</description>
</property>
<property>
<name>ozone.s3g.sts.https-address</name>
<value>0.0.0.0:9881</value>
<tag>OZONE, S3GATEWAY</tag>
<description>
The HTTPS address for the S3 Gateway STS endpoint.
</description>
</property>

<property>
<name>ozone.s3g.metrics.percentiles.intervals.seconds</name>
<value>60</value>
Expand Down Expand Up @@ -5211,6 +5259,27 @@
<description>Interval for cleaning up orphan snapshot local data versions corresponding to snapshots</description>
</property>

<property>
<name>ozone.om.sts.token.cleanup.service.interval</name>
<value>3h</value>
<tag>OZONE, OM, PERFORMANCE, SECURITY</tag>
<description>
A background service that periodically scans the s3RevokedStsTokenTable and deletes
revocation entries whose cutoff is older than the maximum STS token lifetime (12 hours).
This property controls how often the cleanup service runs. Unit could be defined with
postfix (ns,ms,s,m,h,d).
</description>
</property>
<property>
<name>ozone.om.sts.token.cleanup.service.timeout</name>
<value>15m</value>
<tag>OZONE, OM, PERFORMANCE, SECURITY</tag>
<description>
A timeout value for the revoked STS token cleanup service. If this is set
greater than 0, the service will stop waiting for the deletion
completion after this time. Unit could be defined with postfix (ns,ms,s,m,h,d).
</description>
</property>
<property>
<name>ozone.scm.ratis.events.max.limit</name>
<value>100</value>
Expand Down
6 changes: 6 additions & 0 deletions hadoop-hdds/dev-support/checkstyle/checkstyle.xml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@
<property name="matchAcrossLines" value="true"/>
<property name="message" value="Use Objects.requireNonNull instead of Preconditions.checkNotNull"/>
</module>
<module name="RegexpMultiline">
<property name="format"
value="@Override\s+public\s+(?:(?:final|synchronized)\s+)*OMRequest\s+preExecute\s*\([^\)]*\)\s*(?:throws\s+[^{]+)?\s*\{(?!(?:(?!\/\*|\*\/)[\s\S]|\/\*(?:(?!\*\/)[\s\S])*\*\/){0,400}?(?:^|\r?\n|(?&lt;=\{))[ \t]*(?!\*|\/)(?:return\s+|final\s+(?:[a-zA-Z0-9_]+\s+)*[a-zA-Z0-9_]+[ \t]*=[ \t]*)?(?:\([a-zA-Z0-9_]+\)\s*)?super\s*\.\s*preExecute\s*\()"/>
<property name="matchAcrossLines" value="true"/>
<property name="message" value="preExecute() overrides must call super.preExecute(ozoneManager) and its result must be final or returned"/>
</module>
<module name="TreeWalker">
<module name="SuppressWarningsHolder"/>
<module name="SuppressionCommentFilter"/>
Expand Down
51 changes: 38 additions & 13 deletions hadoop-hdds/docs/content/design/ozone-sts.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ solutions that want to aggregate data across multiple cloud providers.

# 3. How Ozone STS Works

The initial implementation of Ozone STS supports only the [AssumeRole](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html)
API from the AWS specification. A new STS endpoint `/sts` on port `9880` (port `9881` for https) will be created to service STS requests in the S3 Gateway.
The initial implementation of Ozone STS supports the [AssumeRole](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html)
and [GetCallerIdentity](https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html)
APIs from the AWS specification. A new STS endpoint on port `9880` (port `9881` for https) will be created to service STS requests in the S3 Gateway at the root path (`/`).
We use a separate port for STS to align with AWS so we don't have conflicts at a later time. This means we have:
- Admin port for Ozone specific S3 admin operations
- STS port for STS APIs, analogous to AWS' separate STS endpoint
Expand All @@ -66,6 +67,11 @@ return value of the AssumeRole call will be temporary credentials consisting of
an IAM policy is specified, the temporary credential will have the permissions comprising the intersection of the role permissions
and the IAM policy permissions. **Note:** If the IAM policy is specified and does not grant any permissions, then
the generated temporary credentials won't have any permissions and will essentially be useless.
- [GetCallerIdentity](https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html) returns the account,
ARN, and user ID for the caller credentials used to sign the request. Ozone uses a static account ID of `123456789012`.
For permanent S3 credentials, `UserId` is the resolved Kerberos principal and `Arn` is `arn:aws:iam::123456789012:user/<kerberosShortName>`
where `<kerberosShortName>` is the short username of the Kerberos principal. For STS temporary credentials, `UserId` is
the `AssumedRoleId` and `Arn` is the assumed-role user ARN from the session token.

## 3.2 Limitations in AssumeRole API Support

Expand Down Expand Up @@ -117,6 +123,15 @@ team agreed that behavior is fine for actions, but does not work for Conditions,
restrict calls by sourceIp, and if we silently ignore this, the client may incorrectly think the temporary credentials
are restricted for use by that IP address, so the consensus was to reject the request for that scenario.

### 3.3.2 Additional Context on Linked Buckets

In Ozone, one may configure a chain of bucket links. In the scenario where one desires to call the AssumeRole API where the resource
is a linked bucket, ensure the Ranger policies for the role have the proper permissions for each link in the chain as well
as the source bucket. For example, if there is a source bucket S, that is linked to bucket A, which is linked to bucket B,
and you want the token to be able to issue operations against linked bucket B, ensure that the role has read access to bucket B,
read access to bucket A, and the requisite access for bucket S (such as read on keys for GetObject, create/write on keys for PutObject, etc.).
The role must have at least read access to the volume(s) where these buckets live as well.

## 3.4 SessionToken Format

As mentioned above, one of the return values from the AssumeRole call will be the sessionToken. To support not
Expand All @@ -139,17 +154,26 @@ was included with the AssumeRole request, the String return value will also incl
would further limit the scope of the permissions, resources and actions granted by the role in Ranger, such that the temporary
credential will have the permissions and actions comprising the intersection of the role permissions and actions and the sessionPolicy permissions and actions.
- HMAC-SHA256 signature - used to ensure the sessionToken was created by Ozone and was not altered since it was created.
- creation time of the token (via `OMTokenProto#issueDate`, exposed as `STSTokenIdentifier#getCreationTime()`)
- expiration time of the token (via `ShortLivedTokenIdentifier#getExpiry()`)
- UUID of the OzoneManager secret key used to sign the sessionToken and encrypt the secretAccessKey (via `ShortLivedTokenIdentifier#getSecretKeyId()`)
- assumedRoleId - the generated identifier of the role from the AssumeRole call response (this is used for GetCallerIdentity api)
- assumedRoleUserArn - the arn from the AssumeRole call response (this is used for GetCallerIdentity api)

## 3.5 STS Token Revocation

In the rare event temporary credentials need to be revoked (ex. for security reasons), a table in the OzoneManager RocksDB will be created
to store revoked tokens, and a command-line utility will be created to add tokens to the table. A background cleaner service
will be created to run every 3 hours to delete revoked tokens that have been in the table for more than 12 hours. The
input parameter for the command-line utility will be the sessionToken - this value is returned in plain text as a result
of the AssumeRole call (mentioned above). In this way, specific STS tokens can be revoked as opposed to all tokens. Furthermore,
AWS doesn't have a standard API to revoke tokens therefore we are creating our own system.
to store revocation cutoffs per originalAccessKeyId, and a command-line utility will be created to add entries to the table.
A background cleaner service will be created to run every 3 hours to delete revocation entries whose cutoff is more than 12 hours old.

The command-line utility accepts only `originalAccessKeyId`. The OM stores revocations by keying the table on
`originalAccessKeyId` and storing the revocation cutoff time in milliseconds as the value. When the command is issued,
all STS tokens created by that `originalAccessKeyId` whose signed `creationTime` is strictly before the cutoff are
revoked. Tokens created at or after the cutoff remain valid.

Before writing a revocation entry, the OM verifies that `originalAccessKeyId` corresponds to a real Kerberos identity by
checking that an S3 secret exists for it. This prevents bogus entries from filling the table. Non-admins may only
revoke their own `originalAccessKeyId`; S3 and tenant admins may revoke other principals.

Additionally, if the Kerberos identity of the user that created the STS token is revoked via the `ozone s3 revokesecret`
command, then all the existing and unexpired STS tokens that user created will be revoked.
Expand Down Expand Up @@ -196,14 +220,14 @@ The format of this String is entirely up to the Ranger team. What is required f
subsequent S3 API calls are made that use STS tokens. In order to achieve this, the sessionPolicy String from Ranger will
be included in the sessionToken response to the AssumeRole API call (as mentioned above), and Ozone will supply this String
to Ranger whenever STS tokens are used on S3 API calls via a new `RequestContext.sessionPolicy` field in the
`IAccessAuthorizer#checkAccess(IOzoneObj, RequestContext)` call. Another requirement from the Ozone side is to pass the action (without the s3: prefix) corresponding to the S3 api call into the `RequestContext.s3Action` field.
`IAccessAuthorizer#checkAccess(IOzoneObj, RequestContext)` call. Another requirement from the Ozone side is to pass the action (without the s3: prefix) corresponding to the S3 API call into the `RequestContext.s3Action` field.

### 3.6.2 Additional Context on Permissions and Actions

In a prior iteration of this design, only permissions corresponding to Ozone `ACLType` (i.e. read, write, create, read_acl, etc.) were included in Ranger roles and session policies.
However, after testing against AWS, it was found that ACLs used by Ozone and Ranger are not granular enough. For example, read on volume, read on bucket, and write on key can be used by either the S3 PutObjectTagging api (requiring `s3:PutObjectTagging` action) or the S3 DeleteObjectTagging api (requiring `s3:DeleteObjectTagging` action).
Similarly, because the S3 PutObject api (`s3:PutObject` action) requires read on volume, read on bucket, and create and write on key, someone with `s3:PutObject` access could previously also call the S3 PutObjectTagging api, even though they did not have access to the `s3:PutObjectTagging` action (as an example).
AWS does not allow an STS token that is restricted for one action to issue calls to an api that is associated with a different action. To prevent having more access than requested (or different access than requested), ACL permissions can be constrained further by S3 actions.
However, after testing against AWS, it was found that ACLs used by Ozone and Ranger are not granular enough. For example, read on volume, read on bucket, and write on key can be used by either the S3 PutObjectTagging API (requiring `s3:PutObjectTagging` action) or the S3 DeleteObjectTagging API (requiring `s3:DeleteObjectTagging` action).
Similarly, because the S3 PutObject API (`s3:PutObject` action) requires read on volume, read on bucket, and create and write on key, someone with `s3:PutObject` access could previously also call the S3 PutObjectTagging API, even though they did not have access to the `s3:PutObjectTagging` action (as an example).
AWS does not allow an STS token that is restricted for one action to issue calls to an API that is associated with a different action. To prevent having more access than requested (or different access than requested), ACL permissions can be constrained further by S3 actions.

To do this constraining, the `RequestContext.s3Action` field is introduced so that if populated, the RangerOzoneAuthorizer would further restrict the permissions according to the action.
Additionally, the OzoneGrant would contain a Set<String> representing the S3 actions that are allowed for an inline policy. If all actions are allowed, then the Set<String> would be empty or null.
Expand All @@ -217,11 +241,12 @@ created in Ranger as per the Prerequisites above.
- This authorized user (having permanent S3 credentials) makes the AssumeRole STS call to Ozone.
- If successful, Ozone responds with the temporary credentials.
- A client makes S3 API calls with the temporary credentials for up to as long as the credentials last.
- When Ozone receives an S3 api call using temporary credentials, it will use the Kerberos identity associated with the
- When Ozone receives an S3 API call using temporary credentials, it will use the Kerberos identity associated with the
originalAccessKeyId in the session token and perform the following checks:
- Ensure that if the accessKeyId starts with "ASIA", that a sessionToken was included in the `x-amz-security-token` header
- Ensure the sessionToken is not expired
- Ensure the sessionToken is not revoked via a `keyMayExist` check in OzoneManager RocksDB
- Ensure the STS credentials are not revoked by looking up the revocation cutoff for the token's originalAccessKeyId
and comparing it against the token's signed creationTime
- Validate the HMAC-SHA256 signature in the sessionToken
- Decrypt the secretAccessKey from the sessionToken and validate the AWS signature
- Authorize the call with either RangerOzoneAuthorizer or OzoneNativeAuthorizer
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.hadoop.ozone.shell.s3;

import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
import org.apache.hadoop.ozone.client.OzoneClient;
import org.apache.hadoop.ozone.shell.OzoneAddress;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;

/**
* Executes revocation of STS tokens.
*
* <p>This command records a revocation cutoff for the given original access key ID in the OM's
* revoked STS token table. Subsequent S3 requests using STS tokens created before that cutoff
* will be rejected once the revocation state has propagated.</p>
*/
@Command(name = "revokeststoken",
description = "Revoke S3 STS tokens for the given original access key ID")
public class RevokeSTSTokenHandler extends S3Handler {

@Option(names = {"-o", "--original-access-key-id"},
required = true,
description = "Original long-lived access key ID whose STS tokens should be revoked")
private String originalAccessKeyId;

@Option(names = "-y",
description = "Continue without interactive user confirmation")
private boolean yes;

@Override
protected boolean isApplicable() {
return securityEnabled();
}

@Override
protected void execute(OzoneClient client, OzoneAddress address)
throws IOException {

if (!yes) {
out().print(
"Enter 'y' to confirm STS token revocation for originalAccessKeyId '" + originalAccessKeyId + "': ");
out().flush();
final Scanner scanner = new Scanner(new InputStreamReader(System.in, StandardCharsets.UTF_8));
final String confirmation = scanner.next().trim().toLowerCase();
if (!"y".equals(confirmation)) {
out().println("Revoke STS token operation cancelled.");
return;
}
}

client.getObjectStore().revokeSTSToken(originalAccessKeyId);
out().println("STS tokens revoked for originalAccessKeyId '" + originalAccessKeyId + "'.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
subcommands = {
GetS3SecretHandler.class,
SetS3SecretHandler.class,
RevokeS3SecretHandler.class
RevokeS3SecretHandler.class,
RevokeSTSTokenHandler.class
})
public class S3Shell extends Shell {

Expand Down
Loading
Loading