konippi/create-github-app-token-aws-kms
GitHub: konippi/create-github-app-token-aws-kms
使用 AWS KMS 安全地为 GitHub App 生成安装访问令牌,避免私钥泄露。
Stars: 13 | Forks: 0
# 创建 GitHub App 令牌(AWS KMS)
[](https://github.com/konippi/create-github-app-token-aws-kms/actions/workflows/ci.yml)
[](https://opensource.org/licenses/MIT)
GitHub Action,用于使用 AWS KMS 对 JWT 进行签名来创建 GitHub App 安装访问令牌。
一旦导入 KMS,私钥永远不会离开 HSM 边界 —— JWT 签名被委托给 KMS 的 `Sign` API,无需在 GitHub Secrets 中存储私钥。这遵循了 [GitHub 的官方建议](https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/managing-private-keys-for-github-apps#storing-private-keys),建议将私钥存储在密钥管理服务中并在运行时进行签名。
## 工作原理
```
sequenceDiagram
participant WF as Workflow
participant STS as AWS STS
participant Action as This Action
participant KMS as AWS KMS
participant GH as GitHub API
WF->>STS: 1. configure-aws-credentials (OIDC)
STS-->>WF: Temporary credentials (env vars)
WF->>Action: 2. Run action
Action->>KMS: 3. Sign(JWT signing input)
KMS-->>Action: 4. Signature bytes
Action->>Action: 5. Assemble JWT
Action->>GH: 6. JWT → Installation access token
GH-->>Action: 7. Scoped access token
Action->>WF: 8. Output token
Note over Action,GH: Post step
Action->>GH: 9. Revoke token
```
## 用法
### 基本用法(当前仓库)
```
permissions:
id-token: write
contents: read
steps:
- uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4.3.1
with:
role-to-assume: arn:aws:iam::123456789012:role/github-app-token-signer
aws-region: ap-northeast-1
role-duration-seconds: 900 # Minimum 15 min — this action only needs KMS for a few seconds
- uses: konippi/create-github-app-token-aws-kms@eb864f78285e18e84befd731e09fcc6e3fb7a4db # v1
id: app-token
with:
app-id: ${{ vars.APP_ID }}
kms-key-id: ${{ vars.KMS_KEY_ID }}
permission-contents: read
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
token: ${{ steps.app-token.outputs.token }}
```
### 针对特定仓库的令牌
```
- uses: konippi/create-github-app-token-aws-kms@eb864f78285e18e84befd731e09fcc6e3fb7a4db # v1
id: app-token
with:
app-id: ${{ vars.APP_ID }}
kms-key-id: ${{ vars.KMS_KEY_ID }}
owner: my-org
repositories: |
repo-a
repo-b
permission-contents: read
permission-pull-requests: write
```
### 针对组织中所有仓库的令牌
```
- uses: konippi/create-github-app-token-aws-kms@eb864f78285e18e84befd731e09fcc6e3fb7a4db # v1
id: app-token
with:
app-id: ${{ vars.APP_ID }}
kms-key-id: ${{ vars.KMS_KEY_ID }}
owner: my-org
permission-contents: read
```
## 输入参数
| 输入项 | 是否必需 | 描述 |
|--------|----------|------|
| `app-id` | 是 | GitHub App ID |
| `kms-key-id` | 是 | AWS KMS 密钥 ID、密钥 ARN、别名名称(`alias/...`)或别名 ARN |
| `owner` | 否 | GitHub App 安装所有者。默认为当前仓库所有者 |
| `repositories` | 否 | 仓库列表(逗号或换行分隔)。默认为当前仓库 |
| `permission-*` | **至少一个** | 权限范围(例如 `permission-contents: read`)。参见 [权限](#permissions) |
| `skip-token-revoke` | 否 | 如果为 `true`,任务完成后不会吊销令牌。默认值:`false` |
| `github-api-url` | 否 | GitHub REST API URL。默认值:`${{ github.api_url }}` |
### 权限
必须至少设置一个 `permission-` 输入。可用权限如下:
`permission-actions`、`permission-administration`、`permission-checks`、`permission-contents`、`permission-deployments`、`permission-environments`、`permission-issues`、`permission-members`、`permission-metadata`、`permission-packages`、`permission-pages`、`permission-pull-requests`、`permission-repository-hooks`、`permission-secret-scanning-alerts`、`permission-secrets`、`permission-security-events`、`permission-statuses`、`permission-vulnerability-alerts`、`permission-workflows`
取值:`read`、`write` 或 `admin`(根据适用情况)。
## 输出
| 输出 | 描述 |
|------|------|
| `token` | GitHub 安装访问令牌 |
| `installation-id` | GitHub App 安装 ID |
| `app-slug` | GitHub App 标识符 |
## AWS 配置
此操作需要三个 AWS 资源。如果已存在用于 GitHub Actions 的 IAM OIDC 提供程序,则只需两个。
### 1. IAM OIDC 提供程序
如果尚未为 `token.actions.githubusercontent.com` 创建,请跳过此步骤。
```
aws iam create-open-id-connect-provider \
--url https://token.actions.githubusercontent.com \
--client-id-list sts.amazonaws.com
```
### 2. KMS 密钥
创建一个具有 `EXTERNAL` 起源的 RSA 2048 密钥(以便可以导入自有密钥材料):
```
aws kms create-key \
--key-spec RSA_2048 \
--key-usage SIGN_VERIFY \
--origin EXTERNAL \
--description "GitHub App JWT signing key"
```
然后将 GitHub App 私钥导入该 KMS 密钥。密钥材料必须为 PKCS#8 DER 二进制格式:
```
# 将 GitHub App PEM 转换为 PKCS#8 DER
openssl pkcs8 -topk8 -inform PEM -outform DER -in github-app-private-key.pem -out private-key.der -nocrypt
```
接着包装并导入密钥材料。详见 [AWS 导入密钥材料文档](https://docs.aws.amazon.com/kms/latest/developerguide/importing-keys.html) 和 [将非对称密钥迁移到 AWS KMS](https://aws.amazon.com/blogs/security/how-to-migrate-asymmetric-keys-from-cloudhsm-to-aws-kms/)。
附加仅允许使用特定算法进行 `kms:Sign` 的密钥策略:
```
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowSignOnly",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/github-app-token-signer"
},
"Action": "kms:Sign",
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:SigningAlgorithm": "RSASSA_PKCS1_V1_5_SHA_256"
}
}
}
]
}
```
### 3. IAM 角色 + 信任策略
创建一个 IAM 角色,并使用 [提供程序特定的 OIDC 声明](https://aws.amazon.com/about-aws/whats-new/2026/01/aws-sts-supports-validation-identity-provider-claims) 配置信任策略(自 2026 年 1 月起可用):
```
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
"token.actions.githubusercontent.com:repository_id": "YOUR_REPO_ID",
"token.actions.githubusercontent.com:job_workflow_ref": "your-org/your-repo/.github/workflows/deploy.yml@refs/heads/main"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:your-org/your-repo:*"
}
}
}
]
}
```
## 降级方案
如果 AWS KMS 不可用(区域故障或服务中断),可以临时切换到 [actions/create-github-app-token](https://github.com/actions/create-github-app-token),并将私钥存储在 GitHub Secrets 中。这会降低安全姿态,但可防止 CI/CD 完全中断。
## 许可证
[MIT](LICENSE)
标签:AWS KMS, AWS STS, GitHub Action, GitHub App, GitHub官方推荐, IAM角色, JWT签名, OIDC, 安全令牌, 安装访问令牌, 密钥不落地, 密钥轮换, 密钥零暴露, 权限最小化, 硬件安全模块, 签名委托, 自动化令牌发放, 自动化攻击, 运行时签名