azure-search-openai-demo 多环境共享指南:使用 azd env refresh 与角色脚本实现团队协作部署
【免费下载链接】azure-search-openai-demoA sample app for the Retrieval-Augmented Generation pattern running in Azure, using Azure AI Search for retrieval and Azure OpenAI large language models to power ChatGPT-style and Q&A experiences.项目地址: https://gitcode.com/GitHub_Trending/az/azure-search-openai-demo
RAG 聊天应用(RAG chat)部署完成后,往往需要交给同事进行二次开发、联调或本地运行验证。本文以docs/sharing_environments.md为骨架,完整讲解如何通过azd env refresh将已部署的 Azure 环境共享给团队成员,并深入剖析scripts/roles.sh/scripts/roles.ps1角色分配脚本的底层实现与权限模型。读完本文,你将掌握从获取环境信息、同步 azd 环境变量到为同事完成 Azure RBAC 角色授予的完整协作流程。
适用场景与前置条件
该方案适用于以下场景:你已经按照 部署指南 成功部署了 RAG chat 解决方案,现在希望把同一套 Azure 部署环境(AI Search、Azure OpenAI、存储账号等资源)共享给一位同事,让 TA 能够在本地运行应用进行调试或继续开发。
共享过程涉及三个关键要素:
| 要素 | 说明 | 获取方式 |
|---|---|---|
| azd 环境名称(environment name) | azd up部署时创建的环境标识 | .azure/{环境名}/.env文件所在目录名 |
| 订阅 ID(subscription ID) | 资源所在的 Azure 订阅 | .azure/{环境名}/.env中的AZURE_SUBSCRIPTION_ID |
| 位置(location) | 资源组部署区域 | .azure/{环境名}/.env中的AZURE_LOCATION等值 |
参与者双方(原始部署者或新加入的同事)均可发起共享流程,但需要满足一个硬性前置条件:安装 Azure CLI,因为az命令(az role assignment create、az ad signed-in-user show)是整个流程的基础工具。
完整共享操作步骤
整个流程共 5 步,前 3 步完成 azd 环境同步,后 2 步完成身份与权限授予。
1. 初始化本地 azd 环境或克隆仓库
新同事需要先获得项目代码与 azd 环境。两种方式任选其一:
# 方式一:直接基于模板初始化(推荐,自动拉取最新模板) azd init -t azure-search-openai-demo # 方式二:克隆本仓库后进入目录 git clone https://gitcode.com/GitHub_Trending/az/azure-search-openai-demo无论采用哪种方式,后续命令都必须在包含
azure.yaml的项目根目录下执行(仓库根目录的 azure.yaml 是 azd 识别项目入口的关键文件)。
2. 刷新 azd 环境
新同事需要向原始部署者索要azd 环境名称、订阅 ID 和位置,这三个值都可以在原始部署者的.azure/{环境名}/.env文件中找到。然后执行:
azd env refresh -e {environment name}azd env refresh的作用是:从 Azure 云端读取该环境实际部署的资源信息,重新生成本地.env文件,把所有运行应用所需的设置(搜索服务端点、OpenAI 端点、存储账号连接串等)写入新同事本地的.azure/{环境名}/.env。这正是该命令在共享场景中的核心价值——无需手动复制粘贴一长串敏感配置,一条命令即可让同事的本地环境与云端部署完全对齐。
执行成功后,同事即可在本地运行应用(例如./app/start.sh或azd up的前置命令),但此时仍缺少访问 Azure 资源的身份权限。
3. 设置 AZURE_PRINCIPAL_ID
应用的本地运行依赖 Azure AI Search、Azure OpenAI 等服务的身份认证(基于 Microsoft Entra ID 的托管身份/用户身份),因此必须告诉部署环境"谁是当前用户"。获取当前用户的 Azure 对象 ID:
az ad signed-in-user show该命令会返回当前登录用户的id字段(即 object ID / principal ID)。然后二选一进行设置:
# 方式一:写入 azd 环境的 .env 文件(持久化,推荐) azd env set AZURE_PRINCIPAL_ID {用户 object ID} # 方式二:写入当前 shell 环境变量(仅本次终端会话有效) export AZURE_PRINCIPAL_ID={用户 object ID}AZURE_PRINCIPAL_ID在整个项目中意义重大:它不仅在部署阶段被写入 infra/main.parameters.json(参数值即${AZURE_PRINCIPAL_ID})用于 Bicep 部署时的角色分配,也在本地运行时被scripts/roles.sh作为az role assignment create的--assignee-object-id使用,还在文档级 ACL(scripts/manageacl.py)中标识文档的授权对象。
4. 运行角色分配脚本
这是整个共享流程中权限落地的关键一步。根据操作系统选择对应脚本:
# Linux / macOS(在项目根目录执行) ./scripts/roles.sh # Windows PowerShell ./scripts/roles.ps1脚本会自动为AZURE_PRINCIPAL_ID指向的用户,在部署所在资源组范围内创建 5 项 RBAC 角色分配(具体角色见下一节)。
权限注意:如果新同事没有在订阅中创建角色分配的权限(缺少
Microsoft.Authorization/roleAssignments/write这类权限),脚本会执行失败。此时需要由原始部署者(通常拥有足够权限)代为运行该脚本。脚本成功后,新同事即可正常在本地运行应用访问 Azure 资源。
角色分配脚本源码深度解析
scripts/roles.sh与scripts/roles.ps1是两个平台等价的实现,逻辑完全一致,我们以 roles.sh 为剖析对象。
脚本定义的 5 项 Azure 角色
脚本第一段定义了需要授予的全部内置角色 GUID,覆盖了 RAG chat 应用运行所需的三大类资源:OpenAI、存储(Blob)与 AI Search:
roles=( "5e0bd9bd-7b93-4f28-af87-19fc36ad61bd" # Cognitive Services OpenAI User "2a2b9908-6ea1-4ae2-8e65-a410df84e7d1" # Storage Blob Data Reader "ba92f5b4-2d11-453d-a403-e96b0029c9fe" # Storage Blob Data Contributor "1407120a-92aa-4202-b7e9-c0e197c71c8f" # Search Index Data Reader "8ebe5a00-799e-43f5-93ac-243d3dce84a7" # Search Index Data Contributor )| 角色 | 作用域资源 | 授予目的 |
|---|---|---|
| Cognitive Services OpenAI User | Azure OpenAI | 允许用户调用 OpenAI 模型(聊天补全、嵌入等),这是 RAG 问答链路的核心权限 |
| Storage Blob Data Reader | 存储账号 | 读取数据文档的原始 Blob 内容 |
| Storage Blob Data Contributor | 存储账号 | 写入/上传文档(如本地执行prepdocs数据摄取时) |
| Search Index Data Reader | Azure AI Search | 查询索引,供检索阶段读取 |
| Search Index Data Contributor | Azure AI Search | 写入索引(数据摄取时创建/更新索引) |
这 5 项角色恰好覆盖了 RAG 聊天应用从数据摄取(ingestion)到查询回答(query)的完整数据通路:写入侧需要 Contributor 权限,读取侧需要 Reader 权限。
脚本自动推导资源组与关键参数
脚本随后从 azd 环境读取部署参数,并做了资源组名称的自动兜底:
AZURE_RESOURCE_GROUP=$(azd env get-value AZURE_RESOURCE_GROUP) if [ -z "$AZURE_RESOURCE_GROUP" ]; then AZURE_ENV_NAME=$(azd env get-value AZURE_ENV_NAME) AZURE_RESOURCE_GROUP="rg-$AZURE_ENV_NAME" azd env set AZURE_RESOURCE_GROUP "$AZURE_RESOURCE_GROUP" fi AZURE_PRINCIPAL_ID=$(azd env get-value AZURE_PRINCIPAL_ID) AZURE_SUBSCRIPTION_ID=$(azd env get-value AZURE_SUBSCRIPTION_ID)这里的azd env get-value是 azd 提供的关键命令,作用是从.azure/{环境名}/.env中读取变量值。脚本做了两处容错设计:
- 资源组自动命名:若环境中未显式设置
AZURE_RESOURCE_GROUP,则按本项目约定自动生成rg-{环境名}(与 infra/main.bicep 中的资源组命名规则一致),并写回 azd 环境,保证后续命令可复用; - 统一数据源:
AZURE_PRINCIPAL_ID与AZURE_SUBSCRIPTION_ID均从 azd 环境读取——这也是为什么第 3 步必须先把AZURE_PRINCIPAL_ID写入.env(或azd env set),否则脚本中该变量为空会导致角色分配失败。
角色分配命令的执行细节
脚本核心循环使用 Azure CLI 的az role assignment create完成 5 次分配:
for role in "${roles[@]}"; do az role assignment create \ --role "$role" \ --assignee-object-id "$AZURE_PRINCIPAL_ID" \ --scope /subscriptions/"$AZURE_SUBSCRIPTION_ID"/resourceGroups/"$AZURE_RESOURCE_GROUP" \ --assignee-principal-type User done逐参数解读:
--role:内置角色定义 ID(GUID),即上文 5 项角色;--assignee-object-id:被授权主体的 object ID,即同事的AZURE_PRINCIPAL_ID;--scope:授权作用域,精确到资源组级别(/subscriptions/{订阅}/resourceGroups/{资源组}),遵循 Azure RBAC 的继承机制,该资源组下的所有资源(存储、搜索、OpenAI)都会继承这 5 项权限;--assignee-principal-type User:显式声明主体类型为用户,避免 CLI 对用户类型的二次解析。
底层实现提示:
azd up部署阶段其实已经在 infra/core/security/role.bicep 中通过Microsoft.Authorization/roleAssignments@2022-04-01资源为部署者(AZURE_PRINCIPAL_ID)创建过同样的角色分配。共享流程中的roles.sh则是把同一套角色体系复制给新用户,两者在 RBAC 层是等价的,只是触发时机不同(部署时 vs 共享时)。
共享后的可选扩展:文档级访问控制
角色脚本解决的是资源级权限(谁能访问整个搜索服务/存储账号)。如果你的部署启用了AZURE_USE_AUTHENTICATION与访问控制,并且需要文档级权限隔离(不同用户只能检索授权给自己的文档),还可以使用仓库提供的 manageacl.py 为文档添加oids(用户)或groups(组)ACL。共享环境时,同事同样可以借助该脚本完成索引 ACL 的启用与维护,例如:
# 启用索引文档级 ACL python ./scripts/manageacl.py --acl-action enable_acls这与roles.sh互补:roles.sh保证"能连上服务",manageacl.py保证"只能看到授权文档"。需要说明的是,文档级 ACL 属于可选的增强配置,基础共享流程(本文 5 步)不强制要求。
常见问题与排查建议
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
azd env refresh报错 | 环境名称拼写错误,或未登录正确的 Azure 订阅 | 用azd env list查看已有环境;az login确认登录账号 |
roles.sh提示变量为空 | .env中缺少AZURE_PRINCIPAL_ID/AZURE_SUBSCRIPTION_ID | 回到第 3 步用azd env set写入,或用azd env get-value检查 |
| 角色分配权限不足(403/AuthorizationFailed) | 当前用户无Microsoft.Authorization/roleAssignments/write权限 | 由原始部署者代为运行脚本,或将同事提升为资源组"用户访问管理员"角色 |
| 本地运行仍提示 401 | 应用以用户身份调用 Azure 服务,但AZURE_PRINCIPAL_ID未指向当前登录用户 | 重新执行az ad signed-in-user show确认 object ID 与登录用户一致 |
| 认证开启时无法登录应用 | 未执行 auth_init.py 的认证设置,或重定向 URI 未更新 | 参考 login_and_acl.md 完成应用注册与管理员同意授予 |
小结
共享部署环境的本质可以概括为三件事:用azd env refresh同步环境配置、用AZURE_PRINCIPAL_ID声明身份、用roles.sh/roles.ps1落地 RBAC 权限。这套流程不涉及重新部署资源,成本极低,却能让团队成员在几分钟内获得与部署者完全一致的本地运行体验。结合docs/login_and_acl.md(认证与 ACL 进阶)、deploy_troubleshooting.md(部署排障)与 localdev.md(本地开发),即可构建一套完整的团队级 RAG 应用协作开发环境。
【免费下载链接】azure-search-openai-demoA sample app for the Retrieval-Augmented Generation pattern running in Azure, using Azure AI Search for retrieval and Azure OpenAI large language models to power ChatGPT-style and Q&A experiences.项目地址: https://gitcode.com/GitHub_Trending/az/azure-search-openai-demo
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考