sodonnel commented on code in PR #9223: URL: https://github.com/apache/ozone/pull/9223#discussion_r2486230588
########## hadoop-hdds/docs/content/design/ozone-sts.md: ########## @@ -0,0 +1,147 @@ +--- +title: AWS STS Design for Ozone S3 +summary: STS Support in Ozone +date: 2026-10-30 +jira: HDDS-13323 +status: implementing +author: Ren Koike, Fabian Morgan +--- +<!-- + Licensed 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. See accompanying LICENSE file. +--> + +# AWS STS Design for Ozone S3 + +# 1. Introduction + +S3 credentials used to communicate with Ozone S3 APIs are based on a Kerberos identity. + +Historically, the Ozone community has had interest in a REST API capable of programmatically generating +temporary S3 credentials. + +Amazon AWS has the [Security Token Service (STS)](https://docs.aws.amazon.com/STS/latest/APIReference/welcome.html) which +provides the ability to generate short-lived access to resources. + +The primary scope of this document is to detail the initial implementation of STS within the Ozone ecosystem. + +# 2. Why Use STS Tokens? + +Providing short-lived access to various resources in Ozone is useful in scenarios such as Data Lake +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 will be created to service STS requests in the S3 Gateway. + +## 3.1 Capabilities + +The Ozone STS implementation has the following capabilities: + +- Create temporary credentials that last from a minimum of 15 minutes to a maximum of 12 hours. The +return value of the AssumeRole call will be temporary credentials consisting of 3 components: + - accessKeyId - a generated String identifier beginning with the sequence "ASIA" + - secretAccessKey - a generated String password + - sessionToken - an opaque String identifier +- The temporary credentials will have the permissions associated with a role. Furthermore, an +[AWS IAM Session Policy](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session) can +**optionally** be sent in the AssumeRole API call to limit the scope of the permissions further. If +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. + +## 3.2 Limitations in IAM Session Policy Support + +The AWS IAM policy specification is vast and wide-ranging. The initial Ozone STS supports a limited +subset of its capabilities. The restrictions are outlined below: + +- The only supported prefix in ResourceArn is `arn:aws:s3:::` - all others will be rejected. **Note**: a ResourceArn +of `*` is supported as well. +- The only supported Condition operator is `StringEquals` - all others will be rejected. +- The only supported Condition attribute is `s3:prefix` - all others will be rejected. +- Only one Condition operator per Statement is supported - a Statement with more than one condition will be rejected. +- The only supported Effect is `Allow` - all others will be rejected. +- If a (currently) unsupported S3 action is requested, such as `s3:GetAccelerateConfiguration`, it will be silently ignored. +Similarly, an invalid S3 action will be silently ignored. +- Supported wildcard expansions in Actions are: `s3:*`, `s3:Get*`, `s3:Put*`, `s3:List*`, +`s3:Create*`, and `s3:Delete*`. +- If using OzoneNativeAuthorizer, bucket wildcards (ex. ResourceArn `arn:aws:s3:::*`, `arn:aws:s3:::bucket*` or `*`) will be rejected. +However, certain object wildcards be accepted. For example, ResourceArn `arn:aws:s3:::myBucket/*` and `arn:aws:s3:::myBucket/folder/logs/*` +will be accepted but `arn:aws:s3:::myBucket/file*.txt` +will not be accepted. + +A sample IAM policy that allows read access to all objects in the `example-bucket` bucket is shown below: +```JSON +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": "s3:GetObject", + "Resource": "arn:aws:s3:::example-bucket/*" + } + ] +} + +``` + +## 3.3 SessionToken Format + +As mentioned above, one of the return values from the AssumeRole call will be the sessionToken. To support not +storing temporary credentials server-side in Ozone, the sessionToken will comprise various components needed to validate +subsequent S3 calls that use the token. The sessionToken will have the following information encoded: + +- The originalAccessKeyId - this is the Kerberos identity of the user that created the sessionToken via the AssumeRole call. +When the temporary credentials are used to make S3 API calls, this Kerberos identity (in conjunction with the role permissions and +optional session policy) will be used to authorize the call. +- The roleArn - the role used in the original AssumeRole call +- The encrypted secretAccessKey - this will be used to validate the AWS signature when the temporary credentials are used +to make S3 API calls +- (Optional) sessionPolicy - when using the RangerOzoneAuthorizer, if Ranger successfully authorizes the AssumeRole call, +it will return a String representing the resources (i.e. buckets, keys, etc.) and permissions (i.e. ACLType) that the token +has been granted access to. This sessionPolicy will be included in the sessionToken sent back to the client so it can be sent to Ranger to +authorize subsequent S3 API calls that use the sessionToken. +- HMAC-SHA256 signature - used to ensure the sessionToken was created by Ozone and was not altered since it was created. +- The expiration time of the token (via `ShortLivedTokenIdentifier#getExpiry()`) +- The UUID of the secret key used to sign the sessionToken and encrypt the secretAccessKey (via `ShortLivedTokenIdentifier#getSecretKeyId()`) + +## 3.5 STS Token Revocation + +In the rare event temporary credentials need to be revoked (ex. for security reasons), a table in 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. Review Comment: If we don't store tokens server side, then how do we identify tokens that need to be revoked? My initial thought on this, was that revoking short lived tokens should be a very rare event, and if they do need to be revoked, the easiest solution is to roll the OM key used to generated the HMAC, rendering all tokens invalid. This does not allow for selective revocation, but it does provide a means to revoke everything in the event of a breach of some kind. Its a kind of simple solution. As soon as we implement a bad list, then you have to do a lookup on each call against RockDB it to see if the current token is in it. It would be a tiny amount of time and probably the bad list could be cached, but its still complexity we can maybe live without. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
