

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 在 PCS 中使用 Slurm REST API 进行身份验证 AWS
<a name="slurm-rest-api-authenticate"></a>

 AWS PCS 中的 Slurm REST API 使用 JSON 网络令牌 (JWT) 身份验证来确保对集群资源的安全访问。 AWS PCS 提供存储在 Secrets Manager 中的托管签名 AWS 密钥，您可以使用该密钥生成包含特定用户身份声明的 JWT 令牌。

## 先决条件
<a name="slurm-rest-api-authenticate-prerequisites"></a>

在使用 Slurm REST API 进行身份验证之前，请确保您已具备以下条件：
+ **集群配置：启**用 Slurm 25.05\$1 且启用 REST API 的 AWS PCS 集群。
+ **AWS 权限**：访问 S AWS ecrets Manager 以获取 JWT 签名密钥。
+ **用户信息**：用户名、POSIX 用户 ID 以及您的集群账户的一个或多个 POSIX 组 IDs 。
+ **网络访问：通过**允许端口 6820 的安全组在集群的 VPC 内进行连接。

## 过程
<a name="slurm-rest-api-authenticate-procedure"></a>

**检索 Slurm REST API 端点地址**

------
#### [ AWS 管理控制台 ]

1. 打开 AWS PCS 控制台，网址为[https://console.aws.amazon.com/pcs/](https://console.aws.amazon.com/pcs/)。

1. 从列表中选择您的集群。

1. 在集群配置详细信息中，找到终**端节点**部分。

1. 注意 **Slurm REST API (slurm** restd) 的私有 IP 地址和端口。

1. 您可以通过向该地址发送格式正确的 HTTP 请求来进行 API 调用。

------
#### [ AWS CLI ]

1. 使用查询您的集群状态`aws pcs get-cluster`。在响应的`endpoints`字段中查找`SLURMRESTD`端点。示例如下：

   ```
   "endpoints": [
         {
             "type": "SLURMCTLD",
             "privateIpAddress": "192.0.2.1",
             "port": "6817"
         },
         {
             "type": "SLURMRESTD",
             "privateIpAddress": "192.0.2.1",
             "port": "6820"
         }
     ]
   ```

1. 您可以通过向发送格式正确的 HTTP 请求来进行 API 调用 `http://<privateIpAddress>:<port>/`

------

**检索 JWT 签名密钥**

1. 打开 AWS PCS 控制台，网址为[https://console.aws.amazon.com/pcs/](https://console.aws.amazon.com/pcs/)。

1. 从列表中选择您的集群。

1. 在集群配置详细信息中，找到 “**调度程序身份验证**” 部分。

1. 注意 **JSON 网络令牌 (JWT) 密钥** ARN 和版本。

1. 使用从 Sec AWS CLI rets Manager 中检索签名密钥：

   ```
   aws secretsmanager get-secret-value --secret-id arn:aws:secretsmanager:region:account:secret:name --version-id version
   ```

**生成 JWT 令牌**

1. 使用以下必填声明创建 JWT：
   + `exp`— 自 1970 年以来 JWT 的到期时间（以秒为单位）
   + `iat`— 自 1970 年以来的当前时间（以秒为单位）
   + `sun`— 用于身份验证的用户名
   + `uid`— POSIX 用户 ID
   + `gid`— POSIX 群组 ID
   + `id`— 其他 POSIX 身份属性
     + `gecos`— 用户评论字段，通常用于存储人类可读的名称
     + `dir`— 用户的主目录
     + `shell`— 用户的默认外壳
     + `gids`— 用户所在的其他 POSIX 组 IDs 的列表

1. 使用从 Secrets Manager 中检索到的签名密钥对 JWT 进行签名。

1. 为令牌设置适当的到期时间。

**注意**  
作为`sun`索赔的替代方案，您可以提供以下任一信息：  
`username`
您通过`userclaimfield`中的定义的自定义字段名称 `AuthAltParameters Slurm custom settings`
`id`索赔中的一个`name`字段

**对 API 请求进行身份验证**

1. 使用以下方法之一将 JWT 令牌包含在您的 HTTP 请求中：
   + **不记名代币**-添加`Authorization: Bearer <jwt>`标题
   + **Slurm 标题 — 添加标题** `X-SLURM-USER-TOKEN: <jwt>`

1. 向 REST API 端点发出 HTTP 请求：

   以下是使用 curl 和`Authorized: Bearer`标头访问 `/ping` API 的示例。

   ```
   curl -X GET -H "Authorization: Bearer <jwt>" \
         http://<privateIpAddress>:6820/slurm/v0.0.43/ping
   ```

## JWT 生成示例
<a name="slurm-rest-api-authenticate-example"></a>

获取 AWS PCS 集群 JWT 签名密钥并将其存储为本地文件。将 **aw** s-region **、** secret-arn **和密**钥版本的值替换为适合您的集群的值。

```
#!/bin/bash
SECRET_KEY=$(aws secretsmanager get-secret-value \
  --region aws-region \
  --secret-id secret-arn \
  --version-stage secret-version \
  --query 'SecretString' \
  --output text)
echo "$SECRET_KEY" | base64 --decode > jwt.key
```

此 Python 示例说明了如何使用签名密钥生成 JWT 令牌：

```
#!/usr/bin/env python3

import sys
import os
import pprint
import json
import time
from datetime import datetime, timedelta, timezone
from jwt import JWT
from jwt.jwa import HS256
from jwt.jwk import jwk_from_dict
from jwt.utils import b64decode,b64encode
if len(sys.argv) != 3:
    sys.exit("Usage: gen_jwt.py [jwt_key_file] [expiration_time_seconds]")
SIGNING_KEY = sys.argv[1]
EXPIRATION_TIME = int(sys.argv[2])
with open(SIGNING_KEY, "rb") as f:
    priv_key = f.read()
signing_key = jwk_from_dict({
    'kty': 'oct',
    'k': b64encode(priv_key)
})
message = {
    "exp": int(time.time() + EXPIRATION_TIME),
    "iat": int(time.time()),
    "sun": "ec2-user",
    "uid": 1000,
    "gid": 1000,
    "id": {
        "gecos": "EC2 User",
        "dir": "/home/ec2-user",
        "gids": [1000],
        "shell": "/bin/bash"
    }
}
a = JWT()
compact_jws = a.encode(message, signing_key, alg='HS256')
print(compact_jws)
```

该脚本会将 JWT 打印到屏幕上。

```
abcdefgtjwttoken...
```