注意

本文档适用于 Ceph 开发版本。

STS中基于属性的访问控制的会话标签

会话标签是键值对,可以在委托用户时传递(目前仅支持作为传递给 AssumeRoleWithWebIdentity 的网页令牌的一部分)。会话标签随 STS 返回的会话凭证(临时凭证)一起传递作为 aws:PrincipalTag。这些 Principal 标签包括作为网页令牌一部分传递的会话标签以及附加到正在假设的角色上的标签。请注意,标签必须始终指定在以下命名空间中:https://aws.amazon.com/tags。

IDP 在网页令牌中传递的会话标签的示例如下:

{
    "jti": "947960a3-7e91-4027-99f6-da719b0d4059",
    "exp": 1627438044,
    "nbf": 0,
    "iat": 1627402044,
    "iss": "http://localhost:8080/auth/realms/quickstart",
    "aud": "app-profile-jsp",
    "sub": "test",
    "typ": "ID",
    "azp": "app-profile-jsp",
    "auth_time": 0,
    "session_state": "3a46e3e7-d198-4a64-8b51-69682bcfc670",
    "preferred_username": "test",
    "email_verified": false,
    "acr": "1",
    "https://aws.amazon.com/tags": [
        {
            "principal_tags": {
                "Department": [
                    "Engineering",
                    "Marketing"
                ]
            }
        }
    ],
    "client_id": "app-profile-jsp",
    "username": "test",
    "active": true
}

在这里描述了配置 Keycloak 以在网页令牌中传递标签的步骤:将 Keycloak 与 RadosGW 集成.

如果委托用户传递的网页令牌包含会话标签,则信任策略必须具有 'sts:TagSession' 权限,否则 AssumeRoleWithWebIdentity 操作将失败。具有 sts:TagSession 的信任策略的示例如下:

{
        "Version":"2012-10-17",
        "Statement":[
        {
            "Effect":"Allow",
            "Action":["sts:AssumeRoleWithWebIdentity","sts:TagSession"],
            "Principal":{"Federated":["arn:aws:iam:::oidc-provider/localhost:8080/auth/realms/quickstart"]},
            "Condition":{"StringEquals":{"localhost:8080/auth/realms/quickstart:sub":"test"}}
        }]
    }

标签键

以下是在角色的信任策略或角色的权限策略中可以使用的标签键:

1. aws:RequestTag: 此键用于比较请求中传递的键值对与角色信任策略中的键值对。在 AssumeRoleWithWebIdentity 的情况下,IDP 在网页令牌中传递的会话标签可以作为角色信任策略中的 aws:RequestTag,根据此策略可以允许委托用户假设角色。

使用 aws:RequestTag 的角色信任策略的示例如下:

{
        "Version":"2012-10-17",
        "Statement":[
        {
            "Effect":"Allow",
            "Action":["sts:AssumeRoleWithWebIdentity","sts:TagSession"],
            "Principal":{"Federated":["arn:aws:iam:::oidc-provider/localhost:8080/auth/realms/quickstart"]},
            "Condition":{"StringEquals":{"aws:RequestTag/Department":"Engineering"}}
        }]
    }

2. aws:PrincipalTag: 此键用于比较附加到主体的键值对与策略中的键值对。在 AssumeRoleWithWebIdentity 的情况下,一旦用户通过身份验证,IDP 在网页令牌中传递的会话标签将作为临时凭证中的 Principal 标签出现,这些标签可以作为角色权限策略中的 aws:PrincipalTag。

使用 aws:PrincipalTag 的角色权限策略的示例如下:

{
        "Version":"2012-10-17",
        "Statement":[
        {
            "Effect":"Allow",
            "Action":["s3:*"],
        "Resource":["arn:aws:s3::t1tenant:my-test-bucket","arn:aws:s3::t1tenant:my-test-bucket/*"],
            "Condition":{"StringEquals":{"aws:PrincipalTag/Department":"Engineering"}}
        }]
    }

3. iam:ResourceTag: 此键用于比较附加到资源的键值对与策略中的键值对。在 AssumeRoleWithWebIdentity 的情况下,附加到角色的标签可以与信任策略中的进行比较,以允许用户假设角色。Role.

使用 aws:ResourceTag 的角色信任策略的示例如下:

{
        "Version":"2012-10-17",
        "Statement":[
        {
            "Effect":"Allow",
            "Action":["sts:AssumeRoleWithWebIdentity","sts:TagSession"],
            "Principal":{"Federated":["arn:aws:iam:::oidc-provider/localhost:8080/auth/realms/quickstart"]},
            "Condition":{"StringEquals":{"iam:ResourceTag/Department":"Engineering"}}
        }]
    }

要使上述内容生效,您需要将 'Department=Engineering' 标签附加到角色。

4. aws:TagKeys: 此键用于比较请求中的标签与策略中的标签。在 AssumeRoleWithWebIdentity 的情况下,这可以用于在允许用户假设角色之前检查角色信任策略中的标签键。

使用 aws:TagKeys 的角色信任策略的示例如下:

{
        "Version":"2012-10-17",
        "Statement":[
        {
            "Effect":"Allow",
            "Action":["sts:AssumeRoleWithWebIdentity","sts:TagSession"],
            "Principal":{"Federated":["arn:aws:iam:::oidc-provider/localhost:8080/auth/realms/quickstart"]},
            "Condition":{"ForAllValues:StringEquals":{"aws:TagKeys":["Department"]}}
        }]
    }

'ForAllValues:StringEquals' 测试请求中的每个标签键是否是策略中标签键的子集。因此,上述条件限制了请求中传递的标签键。

5. s3:ResourceTag: 此键用于比较 s3 资源(存储桶或对象)上存在的标签与角色权限策略中的标签。

使用 s3:ResourceTag 的角色权限策略的示例如下:

{
    "Version":"2012-10-17",
    "Statement":[
    {
        "Effect":"Allow",
        "Action":["s3:PutBucketTagging"],
        "Resource":["arn:aws:s3::t1tenant:my-test-bucket\","arn:aws:s3::t1tenant:my-test-bucket/*"]
    },
    {
        "Effect":"Allow",
        "Action":["s3:*"],
        "Resource":["*"],
        "Condition":{"StringEquals":{"s3:ResourceTag/Department":\"Engineering"}}
    }
}

要使上述内容生效,您需要将 'Department=Engineering' 标签附加到您希望应用此策略的存储桶(以及在对象上)。

使用标签的更多策略示例

1. 通过将传入请求中的标签与附加到角色的标签进行匹配来假设角色。aws:RequestTag 是 JWT(访问令牌)中的传入标签,iam:ResourceTag 是假设的角色上的标签:

{
        "Version":"2012-10-17",
        "Statement":[
        {
            "Effect":"Allow",
            "Action":["sts:AssumeRoleWithWebIdentity","sts:TagSession"],
            "Principal":{"Federated":["arn:aws:iam:::oidc-provider/localhost:8080/auth/realms/quickstart"]},
            "Condition":{"StringEquals":{"aws:RequestTag/Department":"${iam:ResourceTag/Department}"}}
        }]
    }

2. 通过将主体标签与 s3 资源标签进行匹配来评估角色的权限策略。aws:PrincipalTag 是随临时凭证一起传递的标签,s3:ResourceTag 是附加到 s3 资源(对象/存储桶)的标签:

{
    "Version":"2012-10-17",
    "Statement":[
    {
        "Effect":"Allow",
        "Action":["s3:PutBucketTagging"],
        "Resource":["arn:aws:s3::t1tenant:my-test-bucket\","arn:aws:s3::t1tenant:my-test-bucket/*"]
    },
    {
        "Effect":"Allow",
        "Action":["s3:*"],
        "Resource":["*"],
        "Condition":{"StringEquals":{"s3:ResourceTag/Department":"${aws:PrincipalTag/Department}"}}
    }
}

会话标签的属性

  1. 会话标签可以是多值的。(AWS 不支持多值会话标签)

  2. IDP 允许传递最多 50 个会话标签。

  3. 允许的键的最大大小为 128 个字符。

  4. 允许的值的最大大小为 256 个字符。

  5. 标签或值不能以 "aws:" 开头。

s3 资源标签

如上所述,'s3:ResourceTag' 键可用于在 RGW 中授权 s3 操作(AWS 不允许这样做)。

s3:ResourceTag 是一个用于引用已附加到对象或存储桶的标签的键。可以使用相同的 REST API 将标签附加到对象或存储桶。

以下表格显示了哪些 s3 资源标签类型(存储桶/对象)支持授权特定操作。

操作

标签类型

GetObject GetObjectTags DeleteObjectTags DeleteObject PutACLs InitMultipart AbortMultipart ListMultipart GetAttrs PutObjectRetention GetObjectRetention PutObjectLegalHold GetObjectLegalHold

对象标签

PutObjectTags GetBucketTags PutBucketTags DeleteBucketTags GetBucketReplication DeleteBucketReplication GetBucketVersioning SetBucketVersioning GetBucketWebsite SetBucketWebsite DeleteBucketWebsite StatBucket ListBucket GetBucketLogging GetBucketLocation DeleteBucket GetLC PutLC DeleteLC GetCORS PutCORS GetRequestPayment SetRequestPayment PutBucketPolicy GetBucketPolicy DeleteBucketPolicy PutBucketObjectLock GetBucketObjectLock GetBucketPolicyStatus PutBucketPublicAccessBlock GetBucketPublicAccessBlock DeleteBucketPublicAccessBlock

存储桶标签

GetACLs PutACLs

存储桶标签用于

PutObject CopyObject

源对象的

演示会话标签使用的示例代码

以下是为角色、存储桶及其中的对象标记以及在使用角色的信任策略和权限策略中的标签键的示例代码,假设 IDP 通过 JWT(访问令牌)传递了标签 'Department=Engineering'。

# -*- coding: utf-8 -*-

import boto3
import json
from nose.tools import eq_ as eq

access_key = 'TESTER'
secret_key = 'test123'
endpoint = 'http://s3.us-east.localhost:8000'

s3client = boto3.client('s3',
aws_access_key_id = access_key,
aws_secret_access_key = secret_key,
endpoint_url = endpoint,
region_name='',)

s3res = boto3.resource('s3',
        aws_access_key_id = access_key,
        aws_secret_access_key = secret_key,
        endpoint_url = endpoint,
        region_name='',)

iam_client = boto3.client('iam',
aws_access_key_id=access_key,
aws_secret_access_key=secret_key,
endpoint_url=endpoint,
region_name=''
)

bucket_name = 'test-bucket'
s3bucket = s3client.create_bucket(Bucket=bucket_name)

bucket_tagging = s3res.BucketTagging(bucket_name)
Set_Tag = bucket_tagging.put(Tagging={'TagSet':[{'Key':'Department', 'Value': 'Engineering'}]})
try:
    response = iam_client.create_open_id_connect_provider(
        Url='http://localhost:8080/auth/realms/quickstart',
        ClientIDList=[
            'app-profile-jsp',
            'app-jee-jsp'
        ],
        ThumbprintList=[
            'F7D7B3515DD0D319DD219A43A9EA727AD6065287'
    ]
    )
except ClientError as e:
    print ("Provider already exists")

policy_document = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Federated\":[\"arn:aws:iam:::oidc-provider/localhost:8080/auth/realms/quickstart\"]},\"Action\":[\"sts:AssumeRoleWithWebIdentity\",\"sts:TagSession\"],\"Condition\":{\"StringEquals\":{\"aws:RequestTag/Department\":\"${iam:ResourceTag/Department}\"}}}]}"
role_response = ""

print ("\n Getting Role \n")

try:
    role_response = iam_client.get_role(
        RoleName='S3Access'
    )
    print (role_response)
except ClientError as e:
    if e.response['Code'] == 'NoSuchEntity':
        print ("\n Creating Role \n")
        tags_list = [
            {'Key':'Department','Value':'Engineering'},
        ]
        role_response = iam_client.create_role(
            AssumeRolePolicyDocument=policy_document,
            Path='/',
            RoleName='S3Access',
            Tags=tags_list,
        )
        print (role_response)
    else:
        print("Unexpected error: %s" % e)

role_policy = "{\"Version\":\"2012-10-17\",\"Statement\":{\"Effect\":\"Allow\",\"Action\":\"s3:*\",\"Resource\":\"arn:aws:s3:::*\",\"Condition\":{\"StringEquals\":{\"s3:ResourceTag/Department\":[\"${aws:PrincipalTag/Department}\"]}}}}"

response = iam_client.put_role_policy(
            RoleName='S3Access',
            PolicyName='Policy1',
            PolicyDocument=role_policy
        )

sts_client = boto3.client('sts',
aws_access_key_id='abc',
aws_secret_access_key='def',
endpoint_url = endpoint,
region_name = '',
)


print ("\n Assuming Role with Web Identity\n")
response = sts_client.assume_role_with_web_identity(
RoleArn=role_response['Role']['Arn'],
RoleSessionName='Bob',
DurationSeconds=900,
WebIdentityToken='<web-token>')

s3client2 = 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='http://s3.us-east.localhost:8000',
region_name='',)

bucket_body = 'this is a test file'
tags = 'Department=Engineering'
key = "test-1.txt"
s3_put_obj = s3client2.put_object(Body=bucket_body, Bucket=bucket_name, Key=key, Tagging=tags)
eq(s3_put_obj['ResponseMetadata']['HTTPStatusCode'],200)

s3_get_obj = s3client2.get_object(Bucket=bucket_name, Key=key)
eq(s3_get_obj['ResponseMetadata']['HTTPStatusCode'],200)

由 Ceph 基金会带给您

Ceph 文档是一个社区资源,由非盈利的 Ceph 基金会资助和托管Ceph Foundation. 如果您想支持这一点和我们的其他工作,请考虑加入现在加入.