发布于: Oct 19, 2022

原型实现

此部分中如未做特殊说明,均使用 Linux 环境,并安装 Amazon CLI 工具。关于 Amazon CLI 的安装,请参考官方文档[4]。对于所使用到的 Amazon Web Services api 说明,请参考在线帮助[5]。该原型使用宁夏区域(cn-northwest-1)资源。
需要说明的是,该方法同样适用于海外的其它区域,您无需修改代码,只需要注意替换相关资源的 ARN 为海外区域的 ARN 即可。
该原型将模拟一名最终用户,以 IoT 证书作为自己的用户凭证,完成验证后可以访问 Amazon S3 存储桶中以自己名字命名的目录(读写权限),但无法对其它目录拥有写权限。

根据本文“概念对应关系”章节中的内容,首先需要在 Amazon Web Services IoT 服务中创建出“公司”、“最终用户”、“用户授权组”的对应的载体,即:ThingType、Thing 和 ThingGroup,以及用户用来作为自身凭据的 x.509 证书。

  1. 创建 ThingType(公司)
aws iot create-thing-type \
--thing-type-name "AWS" \
--thing-type-properties "thingTypeDescription=testing, searchableAttributes=login,emailAddress,assumeRole"

  1. 创建 Thing(最终用户)

aws iot create-thing --cli-input-json file://user-liuwp001-s3.json

其中,文件 user-liuwp001-s3.json 用于描述 Thing 的相关信息,示例如下:

{
  “thingName”: “liuwp001-s3”,
  “thingTypeName”: “AWS”,
  "attributes": {
    "JobRole": "PSA",
    "Company": "AWS",
    "FamilyName": "Liu",
"GivenName": "WP",
"emailAddress": "xxxxxxxx",
    "assumeRole": "S3User"
  }
}
JSON

其中的 thingName 就是用户在应用系统中的用户名,也是后续 S3 存储桶中用户目录的目录名。而属性信息其实就是用户自身的注册信息,它们将会以 Thing 属性的形式被保留在 Amazon Web Services IoT 服务中。

  1. 创建 ThingGroup(授权组)

aws iot create-thing-group --cli-input-json file://s3-access.json

其中,文件 s3-access.json 用于描述该 ThingGroup 的相关信息,示例如下:

{
    "thingGroupName": "s3-access",
    "thingGroupProperties": {
        "thingGroupDescription": "This group is for s3 access based on different user.",
        "attributePayload": {
            "attributes": {
                "securityLevel": "High"
            },
            "merge": true
        }
    }
}
JSON

  1. Thing 创建证书

执行以下命令时,THING_NAME 、证书保存的目录都可以根据自己的需要进行设定。

THING_NAME=user-liuwp001-s3

aws iot create-keys-and-certificate --set-as-active \
    --public-key-outfile ~/iot-cert/$THING_NAME/$THING_NAME.public.key \
    --private-key-outfile ~/iot-cert/$THING_NAME/$THING_NAME.private.key \
    --certificate-pem-outfile ~/iot-cert/$THING_NAME/$THING_NAME.certificate.pem
JSON

上述命令成功执行后会返回所生成证书的 ARN,执行以下命令将证书关联到之前创建的 Thing 上:

aws iot attach-thing-principal --thing-name $THING_NAME --principal <YOUR_CERT_ARN>

生成的证书文件需要交付到最终用户手中。

根据前文权限设计中的介绍,本方案中有两处权限需要设置:Amazon Web Services IAM Role Amazon Web Services IoT

  1.  Amazon Web Services IAM 中进行权限设置:

关于 Amazon Web Services IAM Role 的详细概念说明可以参考官方文档[6],本文不再赘述。下面着重介绍如何创建出符合本文设定场景的 IAM Role

此处创建的 IAM Role 需要被 Amazon Web Services IoT credentials(见本文图3)服务所调用。因此,这个 Role 的信任实体应当设置为 credentials.iot.amazonaws.com。执行以下命令创建 IAM Role,请注意将 <YOUR_ROLE_NAME> 根据需要进行替换。

aws iam create-role --role-name <YOUR_ROLE_NAME> --assume-role-policy-document file://trustpolicy.json

其中 trustpolicy.json 的内容示例如下:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "credentials.iot.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
JSON

Role 创建出来后需要和 IAM 策略相关联,以便授予对应权限。本文中最终用户通过 IoT 证书所获得的权限是访问专门的 S3 存储桶(只读),仅对以自己名字命名的目录拥有读写权限。通过以下方式创建用于描述 IAM 策略的 json 文件,在 IAM 策略中接受 credentials-iot:ThingName 变量。

 

使用过程中注意将 <YOUR_BUCKET> <BUCKET_PREFIX> 根据需要进行替换。

cat >s3-access-policy.json <<eof
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws-cn:s3:::<YOUR_BUCKET>",
            "Condition": {
                "StringLike": {
                    "s3:prefix": [
                        "<BUCKET_PREFIX>/${credentials-iot:ThingName}/*",
                        "<BUCKET_PREFIX>/${credentials-iot:ThingName}/"
                    ]
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": "s3:GetObject",
            "Resource": "arn:aws-cn:s3::: <YOUR_BUCKET>/*"
        },
        {
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": [
                "arn:aws-cn:s3::: <YOUR_BUCKET>/<BUCKET_PREFIX>/${credentials-iot:ThingName}",
                "arn:aws-cn:s3::: <YOUR_BUCKET>/<BUCKET_PREFIX>/${credentials-iot:ThingName}/*"
            ]
        }
    ]
}
eof
JSON

基于该内容创建 IAM 策略,并关联到之前创建的 IAM Role 上:

# 创建 IAM Policy,并记录结果中的 ARN
aws iam create-policy --policy-name sobey-cctv-reporter --policy-document file://s3-access-policy.json
 
aws iam attach-role-policy --role-name <ROLE_NAME> --policy-arn <POLICY_ARN>

  1.  Amazon Web Services IoT 中进行权限设置:

Amazon Web Services IoT 不能直接使用 IAM Role,需要先在 Amazon Web Services IoT 服务中为这个 IAM Role 创建别名:

aws iot create-role-alias --role-alias <ROLE_ALIAS> --role-arn <IAM_ROLE_ARN> --credential-duration-seconds 3600

<ROLE_ALIAS>可根据需要自行定义,<IAM_ROLE_ARN> 为之前所创建的 IAM Role ARN

 

接下来,需要为 IoT 的证书关联一个 IoT 策略,以允许该证书通过刚刚创建的别名使用 IAM Role。创建策略命令如下:

aws iot create-policy --policy-name <Policy_NAME> --policy-document file:// <Policy_NAME>.json

其中 <Policy_NAME>.json 内容如下:

{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": "iot:AssumeRoleWithCertificate",
    "Resource": "<ALIAS_ARN>",
    "Condition": {
      "StringEquals": {
        "iot:Connection.Thing.Attributes[assumeRole]": "S3User",
        "iot:Connection.Thing.ThingTypeName": "AWS"
      },
      "Bool": {
        "iot:Connection.Thing.IsAttached": "true"
      }
    }
  }
}
JSON

策略中增加了 Condition 字段,以减少发生用户元数据错填、加错 ThingGroup 时错误的获取了相关权限的情况。

 

将创建好的 IoT 策略关联给之前创建的 ThingGroup,这样加入到 ThingGroup 中的所有 Thing 都会获得调用 IAM Role 的权限(被调用的 Role 通过 IoT 的角色别名进行了限制):

aws iot attach-policy --policy-name <POLICY_NAME> --target <THINGGROUP_ARN>

接下来只要将之前创建的 Thing 加入到这个 ThingGroup 中即可:

aws iot add-thing-to-thing-group --thing-name <YOUR_THING_NAME> --thing-group-name <GROUP_NAME>

最终用户在获得 IoT 证书后,可以通过该证书访问 Amazon Web Services IoT Credentials Provider,通过 Credentials Provider 访问 Amazon Web Services STS 服务以换取临时 credentials。

 

首先需要获得自己的 Amazon Web Services 账号内 IoT Credentials Provider 的 endpoint:

aws iot describe-endpoint --endpoint-type iot:CredentialProvider

返回结果的格式应为:xxxxxxxxx.credentials.iot.cn..amazonaws.com.cn

 通过标准的 curl 命令即可访问上述 endpoint,命令中需包含 Thing 证书、Thing 私钥、用于验证 Amazon Web Services IoT Core 服务器身份的根 CA 证书。根 CA 证书的获取可参考官方文档[7]。

 请求临时 credentials 命令如下:

curl –cert <THING_CERT> --key <THING_PRIVATE_KEY> -H "x-amzn-iot-thingname: <THING_NAME>" –cacert <AWS_ROOT_CA> https://<CREDENTIALS_ENDPOINT>/role-aliases/<ALIAS_NAME>/credentials > temptoken

在 temptoken 文件中可以找到所需的 access key id, secret access key。如安装了 jq 工具,也可通过如下方式设置环境变量:

export AWS_ACCESS_KEY_ID=$(jq -r ".credentials.accessKeyId" temptoken)
export AWS_SECRET_ACCESS_KEY=$(jq -r ".credentials.secretAccessKey" temptoken)
export AWS_SESSION_TOKEN=$(jq -r ".credentials.sessionToken" temptoken)

设置完成后,即可通过 Amazon CLI 或 SDK 工具操作 s3 存储桶中的对应目录。

实际应用过程中可能存在大量用户(Thing)的情况,为了快速查找相关用户,可以利用 Amazon Web Services IoT 提供的检索功能。

激活 Fleet Indexing 功能:

aws iot update-indexing-configuration \
--thing-indexing-configuration thingIndexingMode=REGISTRY_AND_SHADOW

根据需要检索,例如查找 Company 为 Amazon Web Services、assumeRole 为 S3User 的用户信息(即 Thing 信息):

aws iot search-index \
--query-string "attributes.Company:AWS AND attributes.assumeRole:S3User"

本文介绍了如何借助 Amazon Web Services IoT 服务实现用户的授权、认证管理,并以访问 S3 存储桶中的资源为例介绍了如何实现原型系统的搭建。该方案具有如下“三高一低”的特点:

  1. 低成本:方案中无需部署实体服务器,没有资源预部署的需求;
  2. 高可靠:验证、授权过程均由 Amazon Web Services 托管服务完成,其可靠性与 Amazon Web Services 平台的整体可靠性相同;
  3. 高安全:用户访问云上资源所需的凭证均为动态凭证,证书本身则没有访问 Amazon Web Services 云上资源的权限;
  4. 高灵活:通过 ThingGroup+变量 的方式实现灵活的授权管理,而无需为每个最终用户创建单独的权限策略。 

当然,实际应用环境中的需求远比本文介绍的原型更负责,您需要根据自己的实际需求进行调整。必要时可以联系与您接口的 Amazon
Web Services 人员做进一步的讨论。

相关文章