自从 Permit.io 初创以来,我们就认识到构建一个安全可靠的授权服务取决于它如何与软件开发生命周期集成。为此,除了为用户提供全面的授权即服务产品外,我们还大力投资于解决在自动化CI/CD流水线的同时保持跨各种环境的一致权限管理的挑战。
我们采用这种全面的授权方法的主要目标是确保这些流程不仅无缝衔接,而且对任何开发团队来说都易于访问和高效。
通过将 GitHub Actions 与我们的 API 集成,我们创建了一个支持大规模开发组织的模型。这篇博客将带您了解我们如何利用这些工具自动化工作空间中的环境管理,使其可以被 CI/CD 管道访问。
了解您的架构以实现 CI/CD创建 GitHub Actions 的第一步(也许也是最重要的一步)是检查你的系统架构,并理解你希望在 CI/CD 中优化的结构。
在构建 Permit.io 时,我们建立了一个系统,允许开发人员将其授权外部化到我们的混合云服务中。虽然产品的核心是让应用程序代码决定用户可以或不可以做什么,但它也设计支持软件开发组织中的常见层级结构。
这在Permit的工作空间层级中显而易见:
Production
和 Development
分支,但用户可以创建任意数量的分支。理解CI/CD流程的结构是优化流程的一半。环境-项目模型旨在提供灵活性和控制,贯穿开发的多个阶段。其核心在于,它允许我们的用户:
如前所述,此模型在需要动态创建、测试和合并环境的场景中特别有用,使其非常适合基于 PR 的工作流。
有了这个模型在心中,让我们来识别自动化和流程优化的挑战。
工作流摩擦:识别挑战为了全面支持授权服务与现有用户环境和架构的无缝集成,我们需要识别权限系统与软件开发系统之间的事件和连接点。
在最基本的层面上,对于每个拉取请求(PR),需要在Permit中创建一个新的环境。这允许将配置与生产环境和预发布环境隔离,运行测试以确保分支和环境的安全性,并将更改合并到生产环境,所有这些操作都几乎不需要人工干预。
这个过程包括以下步骤:
手动管理这些任务可能会出错且耗时,这迫使我们寻找一种可靠的方法来自动化它们。考虑到 CI/CD,我们希望简化前两个步骤的持续集成以及最后步骤的持续部署和交付。
现在我们了解了需求,让我们创建我们的 GitHub Actions:
创建自定义 GitHub Actions如上所述,我们的 GitHub Actions 包含三个工作流,可完全自动化环境管理过程:
new-env.yaml
: 当打开或更新 PR 时,创建一个新的环境。
run-pdp.yaml
: 在新创建的环境中运行测试。
merging.yaml
: 将环境更改合并到生产环境,然后删除特定于 PR 的环境。这些工作流利用Permit的API动态管理环境,提供了一个流畅且无误的过程。您可以在以下代码仓库中查看此工作流的实际操作:https://github.com/permitio/pink-mobile-demo-app/tree/main/.github/workflows
让我们来看一下代码并理解其步骤 -
new-env.yaml
)当新的 PR 打开或更新时,我们会触发一个工作流,负责在 Permit 中创建一个新的环境。我们将使用 Permit 的复制环境 API 来复制生产设置,确保所有环境的一致性。
触发工作流:
运行我们工作流的第一步是通过代码中的事件触发它。我们可以通过以下命令来实现这一点:
name: demo-new-env on: pull_request: types: [opened, reopened]
进入全屏模式 退出全屏模式
这将确保我们的工作流被触发。在下一步中,我们将用一些变量来设置它。
设置环境:
定义项目ID为环境变量。这将在后续的API调用中使用。
该项目是环境将要创建的项目。在生产环境中,你可以从GitHub变量中获取它。
env: PROJECT_ID: 1238e459351a8470
进入全屏模式 退出全屏模式
检查创建的相关性
为了确保我们不会为不涉及权限更改的PR在Permit中打开冗余环境,您需要使用 Permissions
标签标记PR。这将作为创建环境的条件:
jobs: demo-new-env: if: github.event.pull_request.labels.*.name 中包含 'permissions'
进入全屏模式 退出全屏模式
提取分支名称:
接下来,提取分支名称。我们需要它来命名新的环境:
- name: 提取分支名称 run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT id: extract_branch
进入全屏模式 退出全屏模式
创建新环境:
在 Permit 中创建一个新的环境。这是通过提交环境详情来完成的,包括从分支名称派生出的一个唯一密钥:
- name: 创建新环境 run: | response=$(curl -X POST \\ <https://api.permit.io/v2/projects/$>{{ env.PROJECT_ID }}/envs \\ -H 'Authorization: Bearer ${{ secrets.PROJECT_API_KEY }}' \\ -H 'Content-Type: application/json' \\ -d '{ "key": "pr-${ steps.extract_branch.outputs.branch }", "name": "pr-${{ steps.extract_branch.outputs.branch }}" }') echo "ENV_ID=$(echo "$response" | jq -r '.id')" >> $GITHUB_ENV echo "新环境 ID: $(echo "$response" | jq -r '.id')"
进入全屏模式 退出全屏模式
获取环境API密钥:
工作流将获取新创建环境的API密钥,该密钥将在后续的工作流中使用:
- name: 获取新环境的API密钥 run: | response=$(curl -X GET \\ <https://api.permit.io/v2/api-key/$>{{ env.PROJECT_ID }}/${{ env.ENV_ID }} \\ -H 'Authorization: Bearer ${{ secrets.PROJECT_API_KEY }}') ENV_API_KEY=$(echo "$response" | jq -r '.secret') echo "ENV_API_KEY=$ENV_API_KEY" >> $GITHUB_ENV echo "新环境的API密钥: $ENV_API_KEY"
进入全屏模式 退出全屏模式
run-pdp.yaml
)对于我们在持续集成中的下一步,我们希望让流水线在新创建的环境中测试代码。Permit架构的一个关键方面是使用与应用程序一起运行的本地策略决策点(PDP)。
在此工作流中,我们希望在 GitHub Actions 中运行 PDP,这样测试就可以调用它了。我们还将利用这一步在 Permit 系统中设置一些模拟数据:
触发工作流:
此工作流会在 PR 同步时运行,确保任何更新都经过测试:
name: demo-run-pdp-and-tests on: pull_request: types: [同步]
进入全屏模式 退出全屏模式
获取环境ID和API密钥:
接下来,我们将获取上一个工作流中创建的现有环境ID:
- name: 获取环境ID和API密钥 run: | response=$(curl -s -X GET <https://api.permit.io/v2/projects/$>{{ env.PROJECT_ID }}/envs \\ -H 'Authorization: Bearer ${{ secrets.PROJECT_API_KEY }}' \\ -H 'Content-Type: application/json') EXISTING_ID=$(echo "$response" | jq -r '.[] | select(.key == "pr-${ steps.extract_branch.outputs.branch }") | .id') echo "EXISTING_ID=$EXISTING_ID" >> $GITHUB_ENV
进入全屏模式 退出全屏模式
运行本地 PDP 实例:
然后,需要使用 Docker 启动 PDP 的本地实例,以便对新创建的环境进行测试:
- 名称: 运行本地PDP 操作: docker run -d -p 7766:7000 --env PDP_API_KEY=${ env.ENV_API_KEY } --env PDP_DEBUG=true permitio/pdp-v2:latest
进入全屏模式 退出全屏模式
执行测试:
最后,我们可以使用环境的API密钥对本地PDP实例执行测试:
- name: 运行测试 run: PERMIT_TOKEN=${ env.ENV_API_KEY } PDP_URL=localhost:7766 npm run test
进入全屏模式 退出全屏模式
merging.yaml
)我们自定义的 GitHub Actions 的最后一步是确保部署和交付过程高效且顺畅。在这里,我们将触发合并工作流,以确保我们安全地将创建的环境集成到 Permit 的生产环境中。
触发工作流:
此工作流在 PR 关闭时触发,表示是时候合并并清理了:
name: demo-merging on: pull_request: types: [closed]
进入全屏模式 退出全屏模式
获取生产环境和PR环境的ID:
接下来,获取生产环境和特定于 PR 的环境的 ID:
- name: 获取生产环境和PR环境的ID run: | response=$(curl -s -X GET <https://api.permit.io/v2/projects/$>{{ env.PROJECT_ID }}/envs \\ -H 'Authorization: Bearer ${{ secrets.PROJECT_API_KEY }}' \\ -H 'Content-Type: application/json') PROD_ID=$(echo "$response" | jq -r '.[] | select(.key == "production") | .id') echo "PROD_ID=$PROD_ID" >> $GITHUB_ENV
进入全屏模式 退出全屏模式
合并和删除PR环境:
最后,将特定于 PR 的环境合并到生产环境中,然后删除 PR 环境,确保没有残留的环境:
- name: 合并并删除 PR 环境 run: | curl -X POST <https://api.permit.io/v2/projects/$>{{ env.PROJECT_ID }}/envs/${{ env.EXISTING_ID }}/copy \\ -H 'Authorization: Bearer ${{ secrets.PROJECT_API_KEY }}' \\ -H 'Content-Type: application/json' \\ -d '{ "target_env": { "existing": "${{ env.PROD_ID }}" } }' curl -X DELETE \\ <https://api.permit.io/v2/projects/$>{{ env.PROJECT_ID }}/envs/${{ env.EXISTING_ID }} \\ -H 'Authorization: Bearer ${{ secrets.PROJECT_API_KEY }}'
进入全屏模式 退出全屏模式
我们的自定义 GitHub Actions看看我们刚刚创建的这三个步骤,我们可以很容易地看到这个操作是如何将我们授权服务的整个流程整合到用户的架构中的。这是我们使用自定义的 GitHub Actions 处理这些步骤的方式:
环境创建:通过 new-env.yaml
工作流自动化了为每个拉取请求(PR)创建新环境的过程。当相关PR被打开或更新时,此操作会触发在Permit中创建一个新的环境。通过使用Permit的API,我们在新环境中复制生产设置,确保在不同阶段的一致性。还添加了一个条件,以避免为与权限更改无关的PR创建不必要的环境,使用标签系统过滤相关PR。
环境测试:run-pdp.yaml
工作流解决了对新创建的环境进行测试的需求。一旦新环境设置完毕,工作流会通过 Docker 启动一个本地的 Policy Decision Point (PDP) 实例。这使得集成和产品测试可以针对环境运行,确保权限设置准确无误后再将更改合并到生产环境。这种自动化测试可以防止错误,并确保只有经过充分测试的更改才能推进。
merging.yaml
工作流将 PR 特定的环境合并到生产环境中,简化部署流程。合并完成后,工作流会删除 PR 特定的环境,确保没有不必要的环境残留,从而减少混乱并保持干净的开发环境。通过自动化这些步骤——环境创建、测试、合并和清理——我们显著减少了人工干预,减少了错误,并加快了整个CI/CD流程。
结论通过将 GitHub Actions 与 Permit.io API 集成,我们成功地简化了 CI/CD 流程,并使环境模型对开发团队更加易用和高效。这种方法不仅减少了人工操作,还降低了错误的风险,提供了更顺畅和可靠的部署过程。
对于任何希望优化其 CI/CD 管道的团队来说,Permit.io 灵活的环境模型结合 GitHub Actions 提供了一种强大的解决方案,可以自动并安全地管理您的开发工作流程。
您可以在我们的文档中了解更多关于如何处理项目与环境的信息,或者亲自尝试Permit.io!
如果你有任何问题,可以加入我们的 Slack 社区 ,那里有数千名开发者正在构建和实施授权功能。