背景
一些服务需要使用对象存储的sts策略,这点在云上都有现成的文档
验证可行性:搜了一下ceph文档,也支持sts策略,支持两种
外部的oidc提供和radosgw提供的鉴权来认证s3用户
思路
sts
- 启用ceph sts支持
- 创建用户
- 创建角色并配置AssumeRole策略
- 创建权限策略并应用到角色
- 生成临时凭证
- 使用临时凭证访问资源
实施
启用sts支持,写配置文件也行
bash
root@ceph-node01:/etc/ceph-cluster# ceph config set client.rgw.ceph-node01 rgw_s3_auth_use_sts true
# 验证
root@ceph-node01:/etc/ceph-cluster# ceph config get client.rgw.ceph-node01 rgw_s3_auth_use_sts
重启服务
bash
root@ceph-node01:/etc/ceph-cluster# systemctl status ceph-radosgw@rgw.ceph-node01.service
● ceph-radosgw@rgw.ceph-node01.service - Ceph rados gateway
Loaded: loaded (/lib/systemd/system/ceph-radosgw@.service; indirect; vendor preset: enabled)
Active: active (running) since Wed 2024-10-09 16:59:15 CST; 3s ago
Main PID: 26612 (radosgw)
Tasks: 602
CGroup: /system.slice/system-ceph\x2dradosgw.slice/ceph-radosgw@rgw.ceph-node01.service
└─26612 /usr/bin/radosgw -f --cluster ceph --name client.rgw.ceph-node01 --setuser ceph --setgroup ceph
Oct 09 16:59:15 ceph-node01 systemd[1]: Started Ceph rados gateway.
创建用户
bash
root@ceph-node01:/etc/ceph-cluster# radosgw-admin user create --uid="user1" --display-name="user1"
{
"user_id": "user1",
"display_name": "user1",
"email": "",
"suspended": 0,
"max_buckets": 1000,
"subusers": [],
"keys": [
{
"user": "user1",
"access_key": "1SCNEPTNI8NPJG5GP3N3",
"secret_key": "JNYYUMPR39WYy2hBebZuD5PYjbuj7pyDUBrLw6dX"
}
],
"swift_keys": [],
"caps": [],
"op_mask": "read, write, delete",
"default_placement": "",
"default_storage_class": "",
"placement_tags": [],
"bucket_quota": {
"enabled": false,
"check_on_raw": false,
"max_size": -1,
"max_size_kb": 0,
"max_objects": -1
},
"user_quota": {
"enabled": false,
"check_on_raw": false,
"max_size": -1,
"max_size_kb": 0,
"max_objects": -1
},
"temp_url_keys": [],
"type": "rgw",
"mfa_ids": []
}
创建角色
bash
root@ceph-node01:/data/ceph/sts# radosgw-admin role create --uid="user1" --role-name="S3AccessRole" --path="/" --assume-role-policy-doc='{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":["arn:aws:iam:::user/user1"]},"Action":["sts:AssumeRole"]}]}'
{
"RoleId": "235af27f-3a6b-49d9-bfde-fcd900d41ed7",
"RoleName": "S3AccessRole",
"Path": "/",
"Arn": "arn:aws:iam:::role/S3AccessRole",
"CreateDate": "2024-10-09T09:40:53.783Z",
"MaxSessionDuration": 3600,
"AssumeRolePolicyDocument": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"arn:aws:iam:::user/user1\"]},\"Action\":[\"sts:AssumeRole\"]}]}"
}
创建权限策略并应用到角色role
bash
radosgw-admin role-policy put --role-name="S3AccessRole" --policy-name="S3Policy" --policy-doc='{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::bucket1/*"
]
}
]
}'
获取临时凭证
示例,仅展示基本实现
python
import boto3
from datetime import datetime
import logging
import json
# logging.basicConfig(level=logging.DEBUG)
def json_serial(obj):
if isinstance(obj, datetime):
return obj.isoformat()
raise TypeError(f"Type {type(obj)} not serializable")
# 使用一个特权用户的ak sk查询所有的role的信息
iam_client = boto3.client('iam',
aws_access_key_id="3OxxXDZ8J3E",
aws_secret_access_key="TnBNg6ynNFIfxxs9z4bDDO0veIwwnce",
endpoint_url="http://xx:7480",
region_name="",)
policy_document = '''{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":["arn:aws:iam:::user/TESTER1"]},"Action":["sts:AssumeRole"]}]}'''
role_info = iam_client.get_role(RoleName="msAccess")
print(f"role_info {role_info}")
sts_client = boto3.client('sts',
aws_access_key_id="9G3PFWQxxEA887B30",
aws_secret_access_key="BONw0gO3vqqJxxdi1Ckb2YI8FGZ",
endpoint_url="http://xxx:7480",
region_name='',)
# RoleArn=role_response['Role']['Arn'],
sts_session = sts_client.assume_role(
RoleArn="arn:aws:iam:::role/msAccess",
RoleSessionName='BobSession',
DurationSeconds=3600)
# 获取临时ak sk token
print(f"临时ak {sts_session['Credentials']['AccessKeyId']}")
print(f"临时sk {sts_session['Credentials']['SecretAccessKey']}")
print(f"临时token {sts_session['Credentials']['SessionToken']}")
# 使用临时凭证请求object
s3client = boto3.client('s3',
aws_access_key_id =sts_session['Credentials']['AccessKeyId'],
aws_secret_access_key =sts_session['Credentials']['SecretAccessKey'],
aws_session_token =sts_session['Credentials']['SessionToken'],
endpoint_url="http://10.17.3.14:7480",)
png_resp = s3client.get_object(Bucket="meta-studio-prd", Key="000013.png")
print(f"返回 {png_resp}")
# print(png_resp['Body'].read())
with open(file="000013.png", mode="wb") as file:
file.write(png_resp['Body'].read())
一些常用命令
bash
# 列出角色
radosgw-admin role list --role-name=ROLE_NAME
# 删除附加到角色策略
radosgw-admin role policy delete --role-name=ROLE_NAME --policy-name=POLICY_NAME
radosgw-admin role policy delete --role-name=S3Access1 --policy-name=Policy1
# 删除角色
radosgw-admin role delete --role-name=ROLE_NAME
radosgw-admin role delete --role-name=S3Access1
# 更新附加到角色策略
radosgw-admin role-policy put --role-name=ROLE_NAME --policy-name=POLICY_NAME --policy-doc=PERMISSION_POLICY_DOCUMENT
radosgw-admin role-policy put --role-name=S3Access1 --policy-name=Policy1 --policy-doc=\{\"Version\":\"2012-10-17\",\"Statement\":\[\{\"Effect\":\"Allow\",\"Action\":\[\"s3:*\"\],\"Resource\":\"arn:aws:s3:::example_bucket\"\}\]\}
# 删除附加到角色的策略
radosgw-admin role policy delete --role-name=ROLE_NAME --policy-name=POLICY_NAME
radosgw-admin role policy delete --role-name=S3Access1 --policy-name=Policy1
# 更新角色的会话持续时间
radosgw-admin role update --role-name=ROLE_NAME --max-session-duration=7200
后续再补充其他的
reference
权限列表
https://docs.ceph.com/en/quincy/radosgw/s3/authentication/
aws的sts鉴权方式
https://docs.aws.amazon.com/zh_cn/IAM/latest/UserGuide/id_credentials_temp.html
assumeRole说明
https://docs.aws.amazon.com/zh_cn/STS/latest/APIReference/API_AssumeRole.html
sts概念示图
https://www.ibm.com/docs/zh/storage-ceph/6?topic=api-secure-token-service
python调用报错access denied参考