This is an automated email from the ASF dual-hosted git repository.

ChenSammi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone-site.git


The following commit(s) were added to refs/heads/master by this push:
     new 34e63c9381 HDDS-16502. Update STS End User Documentation (#557)
34e63c9381 is described below

commit 34e63c9381aaeacc6808ed9ae9407221d7f21a61
Author: fmorg-git <[email protected]>
AuthorDate: Sun Sep 20 22:26:36 2026 -0700

    HDDS-16502. Update STS End User Documentation (#557)
---
 .../03-operations/07-s3/02-sts.md                  | 244 +++++++++++++++++++--
 1 file changed, 227 insertions(+), 17 deletions(-)

diff --git a/docs/05-administrator-guide/03-operations/07-s3/02-sts.md 
b/docs/05-administrator-guide/03-operations/07-s3/02-sts.md
index 23d147d5e0..874b7fc074 100644
--- a/docs/05-administrator-guide/03-operations/07-s3/02-sts.md
+++ b/docs/05-administrator-guide/03-operations/07-s3/02-sts.md
@@ -107,8 +107,8 @@ Restart all Ozone Managers and all S3 Gateways after 
changing this property to h
 After enabling, the STS endpoint is available at one or more of the following 
URLs, depending on the `ozone.http.policy` value (`HTTP_ONLY`, `HTTPS_ONLY`, or 
`HTTP_AND_HTTPS`) and whether TLS is configured.  By default, the value is 
`HTTP_ONLY`:
 
 ```text
-http://<s3g-host>:9880/sts
-https://<s3g-host>:9881/sts
+http://<s3g-host>:9880
+https://<s3g-host>:9881
 ```
 
 The S3 object API remains on the existing S3G port (typically `9878`).
@@ -471,6 +471,8 @@ curl --silent --show-error --location -u admin:rangerR0cks! 
\
 
 ## Sample Ozone STS Usage
 
+Complete [Ranger Policy Setup](#ranger-policy-setup) if you have not already.
+
 ### Step 1: Obtain permanent credentials
 
 ```shell
@@ -485,13 +487,13 @@ export AWS_DEFAULT_REGION=<region such as us-east-1>
 
 ### Step 2: Create the reports bucket in Ozone and upload sample object
 
-`my-service-user` does not have permission to read the `s3v` volume or create 
buckets. Switch to a Kerberos identity with permission to read the s3v volume 
and create `report` bucket (you may need to create this user and assign it the 
proper permissions in Ranger policies), create the `reports` bucket referenced 
in the Ranger policies above, upload a sample object for `GetObject` tests in 
later steps, then switch back to `my-service-user`.
+`my-service-user` does not have permission to read the `s3v` volume or create 
buckets. Switch to a Kerberos identity with permission to read the s3v volume 
and create `reports` bucket (you may need to create this user and assign it the 
proper permissions in Ranger policies), create the `reports` bucket referenced 
in the Ranger policies above, upload a sample object for `GetObject` tests in 
later steps, then switch back to `my-service-user`.
 
 ```shell
 kinit <userWithPermissionToReadS3VVolumeAndCreateReportsBucket>
 ozone sh bucket create /s3v/reports
-printf 'sample data for GetObject test\n' > /tmp/file.parquet
-ozone sh key put /s3v/reports/data/file.parquet /tmp/file.parquet
+printf 'sample data for GetObject test\n' > /tmp/file.txt
+ozone sh key put /s3v/reports/data/file.txt /tmp/file.txt
 kinit my-service-user
 ```
 
@@ -504,7 +506,7 @@ CREDS=$(AWS_ACCESS_KEY_ID=$PERM_AWS_ACCESS_KEY_ID \
   AWS_SECRET_ACCESS_KEY=$PERM_AWS_SECRET_ACCESS_KEY \
   AWS_SESSION_TOKEN= \
   aws sts assume-role \
-  --endpoint-url http://<s3g-host>:9880/sts \
+  --endpoint-url http://<s3g-host>:9880 \
   --role-arn arn:aws:iam::123456789012:role/my-data-read-write-role \
   --role-session-name catalog-session \
   --duration-seconds 3600 \
@@ -524,13 +526,13 @@ Remember to replace `<s3g-host>` with the correct value 
for your server (for exa
 # Read allowed
 aws s3api get-object \
   --endpoint-url "$AWS_ENDPOINT_URL_S3" \
-  --bucket reports --key data/file.parquet /tmp/file.parquet
+  --bucket reports --key data/file.txt /tmp/file.txt
 
 # Write allowed as well
-printf 'new data for PutObject test\n' > /tmp/new.parquet
+printf 'new data for PutObject test\n' > /tmp/new.txt
 aws s3api put-object \
   --endpoint-url "$AWS_ENDPOINT_URL_S3" \
-  --bucket reports --key data/new.parquet --body /tmp/new.parquet
+  --bucket reports --key data/new.txt --body /tmp/new.txt
 ```
 
 ### Step 5: Assume a role with an inline session policy
@@ -546,7 +548,7 @@ CREDS=$(AWS_ACCESS_KEY_ID=$PERM_AWS_ACCESS_KEY_ID \
   AWS_SECRET_ACCESS_KEY=$PERM_AWS_SECRET_ACCESS_KEY \
   AWS_SESSION_TOKEN= \
   aws sts assume-role \
-  --endpoint-url http://<s3g-host>:9880/sts \
+  --endpoint-url http://<s3g-host>:9880 \
   --role-arn arn:aws:iam::123456789012:role/my-data-read-write-role \
   --role-session-name scoped-read \
   --policy "$SESSION_POLICY" \
@@ -566,27 +568,235 @@ Remember to replace `<s3g-host>` with the correct value 
for your server (for exa
 # Read allowed
 aws s3api get-object \
   --endpoint-url "$AWS_ENDPOINT_URL_S3" \
-  --bucket reports --key data/file.parquet /tmp/file.parquet
+  --bucket reports --key data/file.txt /tmp/file.txt
 
 # Write denied since session policy only allowed GetObject
 aws s3api put-object \
   --endpoint-url "$AWS_ENDPOINT_URL_S3" \
-  --bucket reports --key data/new.parquet --body /tmp/new.parquet
+  --bucket reports --key data/new.txt --body /tmp/new.txt
 # → AccessDenied
 ```
 
-### Revoke a session token
+### Revoking session tokens
+
+Ozone STS provides the ability to revoke STS tokens via command-line 
interface, such that all tokens created by the user before the time the command 
was issued will be revoked.
+STS tokens created after the command is run will still work fine.
+Only the user identity corresponding to originalAccessKeyId or an S3/tenant 
admin may revoke:
+
+```shell
+ozone s3 revokeststoken -o "$PERM_AWS_ACCESS_KEY_ID" -y
+```
+
+Revoking a user's permanent secret also invalidates all outstanding STS tokens 
for that user (irrespective of cutoff) and no new tokens can be created by that 
user:
+
+```shell
+ozone s3 revokesecret -u "$PERM_AWS_ACCESS_KEY_ID" -y
+```
+
+---
+
+## Sample Ozone STS Usage - Linked Buckets
+
+Ozone allows buckets to be linked. There can be a source bucket S, that is 
linked to bucket A, which is linked to bucket B, and so on.
+If you need to use a linked bucket when assuming the role, ensure the Ranger 
policies for the role have the proper permissions for each link in the chain as 
well as the source bucket.
+As an example, suppose we want to assume role on bucket B.  The role needs 
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 and write on keys for 
PutObject, etc.).
+The role also must have at least read access to the volume(s) where these 
buckets live as well.
+
+For this example, we'll use `reports` bucket as the source bucket, 
`reports-link-1` as bucket A and `reports-link-2` as bucket B.
+
+### Step 1: Configure Ranger policies
+
+Complete [Ranger Policy Setup](#ranger-policy-setup) if you have not already. 
That section covers the Ranger user, role, assume_role policy, and 
volume/bucket/key policies for the source `reports` bucket.
+
+Because S3 clients access `reports-link-2`, Ranger must also authorize each 
link in the resolution chain. Add a **bucket** policy for each link bucket 
(`reports-link-1` and `reports-link-2`) with at least `read` access and 
matching `action-matches` conditions for the S3 actions the role will perform:
+
+**Bucket `reports-link-1`** (link to source bucket `reports`):
+
+```shell
+curl --silent --show-error --location -u admin:rangerR0cks! \
+  --request POST \
+  --header "Content-Type: application/json" \
+  --header "accept: application/json" \
+  --data '{
+    "isEnabled": true,
+    "service": "'"${RANGER_SERVICE}"'",
+    "name": "read/write reports-link-1 bucket access",
+    "policyType": 0,
+    "policyPriority": 0,
+    "isAuditEnabled": true,
+    "resources": {
+      "volume": {
+        "values": ["s3v"],
+        "isExcludes": false,
+        "isRecursive": false
+      },
+      "bucket": {
+        "values": ["reports-link-1"],
+        "isExcludes": false,
+        "isRecursive": false
+      }
+    },
+    "policyItems": [{
+      "accesses": [{ "type": "read", "isAllowed": true }],
+      "roles": ["my-data-read-write-role"],
+      "conditions": [{ "type": "action-matches", "values": ["GetObject", 
"PutObject"] }],
+      "delegateAdmin": false
+    }],
+    "serviceType": "ozone",
+    "isDenyAllElse": false
+  }' \
+  "${RANGER_URL}/service/public/v2/api/policy"
+```
+
+**Bucket `reports-link-2`** (link to `reports-link-1`; this is the bucket name 
used in S3 API calls):
+
+```shell
+curl --silent --show-error --location -u admin:rangerR0cks! \
+  --request POST \
+  --header "Content-Type: application/json" \
+  --header "accept: application/json" \
+  --data '{
+    "isEnabled": true,
+    "service": "'"${RANGER_SERVICE}"'",
+    "name": "read/write reports-link-2 bucket access",
+    "policyType": 0,
+    "policyPriority": 0,
+    "isAuditEnabled": true,
+    "resources": {
+      "volume": {
+        "values": ["s3v"],
+        "isExcludes": false,
+        "isRecursive": false
+      },
+      "bucket": {
+        "values": ["reports-link-2"],
+        "isExcludes": false,
+        "isRecursive": false
+      }
+    },
+    "policyItems": [{
+      "accesses": [{ "type": "read", "isAllowed": true }],
+      "roles": ["my-data-read-write-role"],
+      "conditions": [{ "type": "action-matches", "values": ["GetObject", 
"PutObject"] }],
+      "delegateAdmin": false
+    }],
+    "serviceType": "ozone",
+    "isDenyAllElse": false
+  }' \
+  "${RANGER_URL}/service/public/v2/api/policy"
+```
+
+Key-level `read`, `create`, and `write` permissions remain on the source 
bucket `reports` only; link buckets do not store keys.
+
+Allow time for Ranger policy cache refresh (up to 30 seconds) before calling 
AssumeRole.
+
+### Step 2: Obtain permanent credentials
+
+```shell
+kinit my-service-user
+ozone s3 getsecret
+export PERM_AWS_ACCESS_KEY_ID=<awsAccessKey from output>
+export PERM_AWS_SECRET_ACCESS_KEY=<awsSecret from output>
+export AWS_ACCESS_KEY_ID=$PERM_AWS_ACCESS_KEY_ID
+export AWS_SECRET_ACCESS_KEY=$PERM_AWS_SECRET_ACCESS_KEY
+export AWS_DEFAULT_REGION=<region such as us-east-1>
+```
+
+### Step 3: Create the source bucket, bucket links, and sample object
+
+`my-service-user` does not have permission to read the `s3v` volume or create 
buckets. Switch to a Kerberos identity with permission to read the `s3v` volume 
and create buckets (you may need to create this user and assign it the proper 
permissions in Ranger policies), then:
+
+1. Create the source bucket `reports` and upload a sample object.
+2. Create bucket links so `reports-link-1` points to `reports`, and 
`reports-link-2` points to `reports-link-1`.
+
+```shell
+kinit <userWithPermissionToReadS3VVolumeAndCreateReportsBucket>
+ozone sh bucket create /s3v/reports
+printf 'sample data for GetObject test\n' > /tmp/file.txt
+ozone sh key put /s3v/reports/data/file.txt /tmp/file.txt
+ozone sh bucket link /s3v/reports /s3v/reports-link-1
+ozone sh bucket link /s3v/reports-link-1 /s3v/reports-link-2
+kinit my-service-user
+```
+
+For background on bucket links, see [Bucket 
Links](../../../core-concepts/namespace/buckets/links).
+
+### Step 4: Assume a role (full role permissions)
+
+AssumeRole must be invoked with the caller's permanent credentials 
(`PERM_AWS_*` from Step 2):
+
+```shell
+CREDS=$(AWS_ACCESS_KEY_ID=$PERM_AWS_ACCESS_KEY_ID \
+  AWS_SECRET_ACCESS_KEY=$PERM_AWS_SECRET_ACCESS_KEY \
+  AWS_SESSION_TOKEN= \
+  aws sts assume-role \
+  --endpoint-url http://<s3g-host>:9880 \
+  --role-arn arn:aws:iam::123456789012:role/my-data-read-write-role \
+  --role-session-name linked-bucket-session \
+  --duration-seconds 3600 \
+  --output json)
+
+export AWS_ACCESS_KEY_ID=$(echo "$CREDS" | jq -r .Credentials.AccessKeyId)
+export AWS_SECRET_ACCESS_KEY=$(echo "$CREDS" | jq -r 
.Credentials.SecretAccessKey)
+export AWS_SESSION_TOKEN=$(echo "$CREDS" | jq -r .Credentials.SessionToken)
+export AWS_ENDPOINT_URL_S3=http://<s3g-host>:9878
+```
+
+Remember to replace `<s3g-host>` with the correct value for your server (for 
example localhost).
+
+### Step 5: Use temporary credentials against the linked bucket
 
-Only the token creator or an S3/tenant admin may revoke:
+Access data through bucket `reports-link-2`. Ozone resolves the link chain to 
the source bucket `reports` transparently:
 
 ```shell
-ozone s3 revokeststoken -t "$(echo "$CREDS" | jq -r 
.Credentials.SessionToken)" -y
+# Read allowed (data stored in /s3v/reports/data/file.txt)
+aws s3api get-object \
+  --endpoint-url "$AWS_ENDPOINT_URL_S3" \
+  --bucket reports-link-2 --key data/file.txt /tmp/file.txt
+
+# Write allowed as well (object created in source bucket reports)
+printf 'new data for PutObject test\n' > /tmp/new.txt
+aws s3api put-object \
+  --endpoint-url "$AWS_ENDPOINT_URL_S3" \
+  --bucket reports-link-2 --key data/new.txt --body /tmp/new.txt
 ```
 
-Revoking a user's permanent secret also invalidates all outstanding STS tokens 
for that user:
+If Ranger policies omit read access on any link bucket in the chain, or omit 
the requisite key permissions on the source bucket `reports`, these calls 
return `AccessDenied` even though the S3 client targets `reports-link-2`.
+
+### Step 6: Assume a role with an inline session policy (optional)
+
+To scope temporary credentials to the linked bucket only, pass an inline 
session policy whose `Resource` references `reports-link-2`. AssumeRole must be 
invoked with the caller's **permanent** credentials:
+
+```shell
+SESSION_POLICY='{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"s3:GetObject","Resource":"arn:aws:s3:::reports-link-2/*"}]}'
+
+CREDS=$(AWS_ACCESS_KEY_ID=$PERM_AWS_ACCESS_KEY_ID \
+  AWS_SECRET_ACCESS_KEY=$PERM_AWS_SECRET_ACCESS_KEY \
+  AWS_SESSION_TOKEN= \
+  aws sts assume-role \
+  --endpoint-url http://<s3g-host>:9880 \
+  --role-arn arn:aws:iam::123456789012:role/my-data-read-write-role \
+  --role-session-name linked-bucket-scoped-read \
+  --policy "$SESSION_POLICY" \
+  --output json)
+
+export AWS_ACCESS_KEY_ID=$(echo "$CREDS" | jq -r .Credentials.AccessKeyId)
+export AWS_SECRET_ACCESS_KEY=$(echo "$CREDS" | jq -r 
.Credentials.SecretAccessKey)
+export AWS_SESSION_TOKEN=$(echo "$CREDS" | jq -r .Credentials.SessionToken)
+export AWS_ENDPOINT_URL_S3=http://<s3g-host>:9878
+```
 
 ```shell
-ozone s3 revokesecret -u my-service-user -y
+# Read allowed via reports-link-2
+aws s3api get-object \
+  --endpoint-url "$AWS_ENDPOINT_URL_S3" \
+  --bucket reports-link-2 --key data/file.txt /tmp/file.txt
+
+# Write denied since session policy only allowed GetObject
+aws s3api put-object \
+  --endpoint-url "$AWS_ENDPOINT_URL_S3" \
+  --bucket reports-link-2 --key data/new.txt --body /tmp/new.txt
+# → AccessDenied
 ```
 
 ---


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to