注意
本文档适用于 Ceph 开发版本。
Ceph中的STS
安全令牌服务(STS)是AWS中的一个网络服务,它返回一组临时安全凭证,用于对联合用户进行身份验证。https://docs.aws.amazon.com/STS/latest/APIReference/Welcome.html.
Ceph对象网关实现了STS API的一个子集,这些API提供临时凭证,用于身份和访问管理。
STS REST API
Ceph对象网关中实现了以下STS REST API:
AssumeRole: 返回一组可用于跨账户访问的临时凭证。临时凭证的权限将由与角色关联的策略和与AssumeRole API关联的策略共同允许。
- 参数:
RoleArn(String/必需): 要假设的角色ARN。
RoleSessionName(String/必需): 假设角色会话的标识符。
Policy(String/可选): JSON格式的IAM策略。
DurationSeconds(Integer/可选): 会话的持续时间(秒)。
ExternalId(String/可选): 当角色在另一个账户中被假设时可能使用的唯一ID。
SerialNumber(String/可选): 与进行AssumeRole调用用户关联的多因素认证(MFA)设备的ID。
TokenCode(String/可选): 如果被假设的角色的信任策略需要MFA,则由MFA设备提供的值。
AssumeRoleWithWebIdentity: 为通过OpenID Connect /OAuth2.0 身份提供者由网络/移动应用程序进行身份验证的用户返回一组临时凭证。
- 参数:
RoleArn(String/必需): 要假设的角色ARN。
RoleSessionName(String/必需): 假设角色会话的标识符。
Policy(String/可选): JSON格式的IAM策略。
DurationSeconds(Integer/可选): 会话的持续时间(秒)。
ProviderId(String/可选): IDP域名完全限定主机部分的域名。仅适用于OAuth2.0令牌(不适用于OpenID Connect令牌)。
WebIdentityToken(String/必需): OpenID Connect/OAuth2.0令牌,应用程序在用IDP对其用户进行身份验证后获得。
在调用AssumeRoleWithWebIdentity之前,需要在RGW中为应用程序认证的OpenID Connect提供者实体创建一个实体。
IDP和角色之间的信任是通过向角色的信任策略添加条件来创建的,该条件仅允许满足给定条件的应用程序访问。
'''{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Federated":["arn:aws:iam:::oidc-provider/<URL of IDP>"]},"Action":["sts:AssumeRoleWithWebIdentity"],"Condition":{"StringEquals":{"<URL of IDP> :app_id":"<aud>"}}}]}'''
The app_id
上述条件中的值必须与传入令牌的“aud”声明匹配。
使用条件中“sub”声明的策略示例的形式如下:
"{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Federated\":[\"arn:aws:iam:::oidc-provider/<URL of IDP>\"]},\"Action\":[\"sts:AssumeRoleWithWebIdentity\"],\"Condition\":{\"StringEquals\":{\"<URL of IDP> :sub\":\"<sub>\"\}\}\}\]\}"
类似地,使用条件中“azp”声明的策略示例的形式如下:
"{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Federated\":[\"arn:aws:iam:::oidc-provider/<URL of IDP>\"]},\"Action\":[\"sts:AssumeRoleWithWebIdentity\"],\"Condition\":{\"StringEquals\":{\"<URL of IDP> :azp\":\"<azp>\"\}\}\}\]\}"
每个联合用户都会创建一个对应的影子用户。用户ID是从传入的网页令牌的“sub”字段派生的。<tenant>$<user-namespace>$<sub>
其中user-namespace对于使用oidc提供者进行身份验证的用户是“oidc”。
RGW现在支持会话标签,这些标签可以传递在Web令牌中到AssumeRoleWithWebIdentity调用。有关会话标签的更多信息可以在这里找到STS中基于属性的访问控制的会话标签.
STS配置
对于STS集成,需要添加以下可配置选项:
[client.{your-rgw-name}]
rgw_sts_key = {sts key for encrypting the session token}
rgw_s3_auth_use_sts = true
注意:
默认情况下,STS和S3 API共存于同一命名空间,并且Ceph对象网关中的S3和STS API都可以通过同一端点访问。
The
rgw_sts_key
需要是一个由恰好16个字符组成的十六进制字符串。
示例
为了让示例正常工作,请确保用户
TESTER
拥有roles
能力分配:radosgw-admin caps add --uid="TESTER" --caps="roles=*"
以下是一个AssumeRole API调用的示例,它显示了创建角色、向其分配策略(允许访问S3资源)、假设角色以获取临时凭证以及使用这些凭证访问S3资源的步骤。在这个示例中,
TESTER1
假设了TESTER
创建的角色,以访问TESTER
拥有的S3资源,import boto3 iam_client = boto3.client('iam', aws_access_key_id=<access_key of TESTER>, aws_secret_access_key=<secret_key of TESTER>, endpoint_url=<IAM URL>, region_name='' ) policy_document = '''{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":["arn:aws:iam:::user/TESTER1"]},"Action":["sts:AssumeRole"]}]}''' role_response = iam_client.create_role( AssumeRolePolicyDocument=policy_document, Path='/', RoleName='S3Access', ) role_policy = '''{"Version":"2012-10-17","Statement":{"Effect":"Allow","Action":"s3:*","Resource":"arn:aws:s3:::*"}}''' response = iam_client.put_role_policy( RoleName='S3Access', PolicyName='Policy1', PolicyDocument=role_policy ) sts_client = boto3.client('sts', aws_access_key_id=<access_key of TESTER1>, aws_secret_access_key=<secret_key of TESTER1>, endpoint_url=<STS URL>, region_name='', ) response = sts_client.assume_role( RoleArn=role_response['Role']['Arn'], RoleSessionName='Bob', DurationSeconds=3600 ) s3client = boto3.client('s3', aws_access_key_id = response['Credentials']['AccessKeyId'], aws_secret_access_key = response['Credentials']['SecretAccessKey'], aws_session_token = response['Credentials']['SessionToken'], endpoint_url=<S3 URL>, region_name='',) bucket_name = 'my-bucket' s3bucket = s3client.create_bucket(Bucket=bucket_name) resp = s3client.list_buckets()
以下是一个AssumeRoleWithWebIdentity API调用的示例,其中有一个外部应用程序,该应用程序的用户通过OpenID Connect/OAuth IDP(本例中为Keycloak)进行身份验证,假设一个角色以获取临时凭证并根据角色的权限策略访问S3资源。
import boto3 iam_client = boto3.client('iam', aws_access_key_id=<access_key of TESTER>, aws_secret_access_key=<secret_key of TESTER>, endpoint_url=<IAM URL>, region_name='' ) oidc_response = iam_client.create_open_id_connect_provider( Url=<URL of the OpenID Connect Provider, ClientIDList=[ <Client id registered with the IDP> ], ThumbprintList=[ <Thumbprint of the IDP> ] ) policy_document = '''{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Federated":["arn:aws:iam:::oidc-provider/localhost:8080/auth/realms/demo"]},"Action":["sts:AssumeRoleWithWebIdentity"],"Condition":{"StringEquals":{"localhost:8080/auth/realms/demo:app_id":"customer-portal"}}}]}''' role_response = iam_client.create_role( AssumeRolePolicyDocument=policy_document, Path='/', RoleName='S3Access', ) role_policy = '''{"Version":"2012-10-17","Statement":{"Effect":"Allow","Action":"s3:*","Resource":"arn:aws:s3:::*"}}''' response = iam_client.put_role_policy( RoleName='S3Access', PolicyName='Policy1', PolicyDocument=role_policy ) sts_client = boto3.client('sts', aws_access_key_id=<access_key of TESTER1>, aws_secret_access_key=<secret_key of TESTER1>, endpoint_url=<STS URL>, region_name='', ) response = client.assume_role_with_web_identity( RoleArn=role_response['Role']['Arn'], RoleSessionName='Bob', DurationSeconds=3600, WebIdentityToken=<Web Token> ) s3client = boto3.client('s3', aws_access_key_id = response['Credentials']['AccessKeyId'], aws_secret_access_key = response['Credentials']['SecretAccessKey'], aws_session_token = response['Credentials']['SessionToken'], endpoint_url=<S3 URL>, region_name='',) bucket_name = 'my-bucket' s3bucket = s3client.create_bucket(Bucket=bucket_name) resp = s3client.list_buckets()
如何获取OpenID Connect提供者IDP的指纹
取OpenID connect提供者的URL并在其后添加
/.well-known/openid-configuration
以获取获取IDP配置文档的URL。例如,如果IDP的URL是http://localhost:8000/auth/realms/quickstart,则获取文档的URL是http://localhost:8000/auth/realms/quickstart/.well-known/openid-configuration使用以下curl命令从步骤1中描述的URL获取配置文档:
curl -k -v \ -X GET \ -H "Content-Type: application/x-www-form-urlencoded" \ "http://localhost:8000/auth/realms/quickstart/.well-known/openid-configuration" \ | jq .
从步骤2的响应中,使用“jwks_uri”的值来获取IDP的证书,使用以下代码:
curl -k -v \ -X GET \ -H "Content-Type: application/x-www-form-urlencoded" \ "http://$KC_SERVER/$KC_CONTEXT/realms/$KC_REALM/protocol/openid-connect/certs" \ | jq .
将上述响应中
x5c
的结果复制到一个文件certificate.crt
,并在其开头添加-----BEGIN CERTIFICATE-----
并在其末尾添加-----END CERTIFICATE-----
。使用以下OpenSSL命令获取证书指纹:
openssl x509 -in certificate.crt -fingerprint -noout
上述步骤5的命令结果将是一个SHA1指纹,如下所示:
SHA1 Fingerprint=F7:D7:B3:51:5D:D0:D3:19:DD:21:9A:43:A9:EA:72:7A:D6:06:52:87
从上述结果中删除冒号以获取最终的指纹,该指纹可以在创建IAM中的OpenID Connect提供者实体时作为输入:
F7D7B3515DD0D319DD219A43A9EA727AD6065287
RGW中的角色
更多关于角色操作的信息可以在这里找到Role.
RGW中的OpenID Connect提供者
更多关于OpenID Connect提供者实体操作的信息可以在这里找到RGW中的OpenID Connect提供者.
RGW与Keycloak的集成
集成RGW与Keycloak的步骤可以在这里找到将 Keycloak 与 RadosGW 集成.
STSLite
STSLite基于STS构建,相关文档可以在这里找到STS Lite.
由 Ceph 基金会带给您
Ceph 文档是一个社区资源,由非盈利的 Ceph 基金会资助和托管Ceph Foundation. 如果您想支持这一点和我们的其他工作,请考虑加入现在加入.