Skip to content
Closed
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
dc250d0
Skelton STS API endpoint implemented by Claude
len548 May 29, 2025
731a3e0
Move STS endpoint service to webadmin by Claude Code. s3g is not work…
len548 Jun 17, 2025
ff3a1df
Combined /secret and /sts endpoints into one servlet, but still failing.
len548 Jun 18, 2025
2952260
Renamed package name (s3sts -> sts)
len548 Jun 18, 2025
f44a2d3
Add skeleton STS API on 9878 S3 Gateway
len548 Jun 19, 2025
f61e8cb
Add authentication to only allow admins to call assume-role API
len548 Jun 23, 2025
bfd10a4
unit test, improve error handlings, and add TODOs
len548 Jul 13, 2025
1738429
removed unused lines and metrics
len548 Jul 13, 2025
edff7ce
Added a desgin doc
len548 Jul 16, 2025
6065b94
Corrected misinformation on the design doc
len548 Jul 16, 2025
b7038fa
Move a design doc to HDDS-13323 branch
len548 Jul 16, 2025
ad8260f
WIP: refactoring STS into webadmin port 19878 [skip ci]
len548 Jul 18, 2025
4475770
WIP: new third port in S3 Gateway for STS [skip ci]
len548 Jul 23, 2025
593fc4c
WIP: fixed to establish a third port [skip ci] with sts endpoint not …
len548 Jul 24, 2025
05a9b7a
Refactored webadmin port to house both s3secret and sts endpoints.
len548 Jul 30, 2025
19dcdb3
Address CI tests
len548 Aug 4, 2025
47f232a
removed unused sts config keys and fixed TestSTS
len548 Aug 7, 2025
ccc683f
Added 19878 port number to ozonesecure and modified web.xml
len548 Aug 17, 2025
f09633d
Fixed checkstyle
len548 Aug 17, 2025
bf98d1b
Address intergration test failure
len548 Aug 18, 2025
720876e
Merge branch 'master' of github.com:apache/ozone into HDDS-13345-sts-…
len548 Aug 18, 2025
7e64053
Fixed checkstyle
len548 Aug 19, 2025
75a5b2e
Add filter to disable STS API
len548 Aug 23, 2025
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
234 changes: 234 additions & 0 deletions hadoop-hdds/docs/content/design/sts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
---
title: Security Token Service (STS) for Ozone
summary: Allows clients to generate temporary S3 credentials using a REST API.
date: 2025-07-16
jira: HDDS-13323
status: implementing
author: Ren Koike
---
<!--
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.
-->
# Introduction

S3 credentials used to communicate with Ozone S3 APIs are based on the kerberos credential used to run the ozone CLI to generate the S3 credential. There is a configuration to specify a S3 Administrator (or default to OM administrators) who can generate S3 credentials for other kerberos principals.

Historically the Ozone community has had an interest in having a REST API to be able to programmatically be able to generate S3 credentials.

With Amazon AWS, there is a central service which has the ability to generate [Security Tokens that span resources across services](https://docs.aws.amazon.com/STS/latest/APIReference/welcome.html).

This document covers a basic proposal that describes how Ozone can offer a stand alone STS service that can be used by users to use REST APIs to retrieve. This can be later extended to integrate with a centralized STS service.

## Requirements

### Functional requirements

1. Allow privileged users to generate temporary S3 credentials with:
* Limited duration
* Restricted to specific bucket/prefix paths
* Restricted to specific S3 operations
* Issuing credentials either to self or another identity
2. Authenticate the AssumeRoleKerberos call using Kerberos
3. Authorize the credential issuance via Ranger
4. Store temporary credentials securely in Ozone Manager
5. Validate S3 API calls using the temporary credentials against stored permissions
6. Verify all operations against Ranger policies
7. Expire the credentials depending on the configured duration
8. Should work with external stores such as vault (currently Ozone supports this for S3 credentials)

### Non functional requirements

1. Support in the order of 20k credentials


### Non Goals

1. Support for native ACLs

## API Spec

Ozone will serve Rest endpoints over the webui ports currently in place.

Clients will need to authenticate with Kerberose before calling the AssumeRoleKerberos endpoint. The AssumeRoleKerberos endpoint will allow a client to Assume a Role specified in Ranger if the user principal used is part of the Role list of users. Each invocation will include a list of bucket:prefix:action list. This list has to be a subset of what the Role in Ranger has access to.

Ozone will call Ranger to authorize the AssumeRoleKerberos request. Once authorized, Ozone will generate S3 credentials and store the S3 credentials, role and resources requested.

When the client invokes S3 APIs using the S3 credentials passed in, Ozone will call Ranger with the requested bucketr:path:action along with the original bucket:prefix:action requested for AssumeRoleKerberos. Ranger will authorize the S3 request if it is compliantcomplaint with the original AssumeRoleKerberos request.
```json
{
"api": "Apache Ozone S3 Gateway",
"endpoint": "/sts/AssumeRoleKerberos",
"method": "POST",
"authentication": {
"type": "Kerberos",
"description": "Client must be authenticated via Kerberos SPNEGO before making this request"
},
"request": {
"content-type": "application/json",
"body": {
"roleName": {
"type": "string",
"description": "The name of the role in Ranger that the client wishes to assume",
"required": true
},
"resourcePermissions": {
"type": "array",
"description": "List of bucket:prefix:action permissions being requested",
"required": true,
"items": {
"type": "object",
"properties": {
"bucket": {
"type": "string",
"description": "The bucket name",
"required": true
},
"prefix": {
"type": "string",
"description": "The object key prefix",
"required": true
},
"action": {
"type": "string",
"description": "The S3 action (READ, WRITE, DELETE, etc.)",
"required": true,
"enum": ["READ", "WRITE", "DELETE", "LIST", "ALL"]
}
}
}
},
"durationSeconds": {
"type": "integer",
"description": "Duration in seconds for which the credentials should be valid",
"required": false,
"default": 3600,
"minimum": 900,
"maximum": 43200
}
}
},
"process": {
"description": "Ozone will validate that the Kerberos-authenticated principal is authorized to assume the specified role in Ranger. It will also validate that the requested bucket:prefix:action permissions are a subset of what the role is allowed to access in Ranger.",
"steps": [
"1. Verify Kerberos authentication",
"2. Call Ranger to check if user principal is part of the specified role",
"3. Validate requested resourcePermissions against role permissions in Ranger",
"4. Generate temporary S3 credentials if authorized",
"5. Store credentials, role, and requested resources for future authorization"
]
},
"response": {
"success": {
"status": 200,
"content-type": "application/json",
"body": {
"credentials": {
"accessKeyId": {
"type": "string",
"description": "Temporary S3 access key ID"
},
"secretAccessKey": {
"type": "string",
"description": "Temporary S3 secret access key"
},
"sessionToken": {
"type": "string",
"description": "Temporary S3 session token"
},
"expiration": {
"type": "string",
"format": "date-time",
"description": "Expiration time of the temporary credentials"
}
},
"roleInfo": {
"roleName": {
"type": "string",
"description": "The name of the assumed role"
},
"roleId": {
"type": "string",
"description": "Unique identifier for the assumed role session"
}
},
"resourcePermissions": {
"type": "array",
"description": "List of bucket:prefix:action permissions granted",
"items": {
"type": "object",
"properties": {
"bucket": {
"type": "string",
"description": "The bucket name"
},
"prefix": {
"type": "string",
"description": "The object key prefix"
},
"action": {
"type": "string",
"description": "The S3 action granted"
}
}
}
}
}
},
"error": {
"unauthorized": {
"status": 403,
"content-type": "application/json",
"body": {
"code": "AccessDenied",
"message": "User is not authorized to assume the specified role or access the requested resources"
}
},
"badRequest": {
"status": 400,
"content-type": "application/json",
"body": {
"code": "InvalidRequest",
"message": "Description of the validation error"
}
},
"serverError": {
"status": 500,
"content-type": "application/json",
"body": {
"code": "InternalServerError",
"message": "An internal server error occurred"
}
}
}
},
"s3AuthorizationFlow": {
"description": "When S3 API requests are made using the temporary credentials, Ozone will validate them against the original requested permissions",
"steps": [
"1. Client makes S3 API request with temporary credentials",
"2. Ozone validates credentials and extracts original role and resourcePermissions",
"3. Ozone calls Ranger with the requested bucket:path:action and original resourcePermissions",
"4. Ranger authorizes the request if it complies with the original permissions",
"5. Ozone processes the S3 request if authorized"
]
}
}
```
Update:

1. Knox / S3 Admin will use ozone cli to get secret (already there)
2. **They will use AWS tokens returned in 1 to call AssumeRole (AWS style header validation authentication)**
1. **Optionally** also implement AssumeRoleKerberos (where there is no step 1\) (SNPEGO based authentication)
2. Ranger should validate if the user can generate secret and delegate access to bucket:path:action.
3. Some user uses secret to access bucket:path:action
1. We know the secret and user and which role they are assuming and which resource.
2. Ranger STS Token Resources : Requested Resources. Sub set check
Loading