保护 Azure Functions

对于 Web 或云托管应用程序来说,无服务器函数的安全开发、部署和操作的规划在诸多方面都几乎相同。 Azure 应用服务提供函数应用的托管基础结构。 本文介绍了运行函数代码的安全策略,以及应用服务如何帮助你保护函数。

应用服务的各个平台组件(包括 Azure VM、存储、网络连接、Web 框架、管理和集成功能)都得到了积极保护和加强。 应用服务持续进行严格的符合性检查,以确保:

  • 你的应用资源与其他客户的 Azure 资源隔离开来,从而受到保护
  • 定期更新 VM 实例和运行时软件,以解决新发现的漏洞。
  • 你的应用与其他 Azure 资源(例如 SQL 数据库)之间的密钥(例如连接字符串)通信一直在 Azure 中进行,不跨越任何网络边界。 存储密钥时始终对其加密。
  • 通过应用服务连接功能(例如混合连接)进行的所有通信均已加密。
  • 与 Azure PowerShell、Azure CLI、Azure SDK、REST API 等远程管理工具的连接均已加密。
  • 24 小时威胁管理可保护基础结构和平台免受恶意软件、分布式拒绝服务 (DDoS)、中间人 (MITM) 和其他威胁的危害。

安全操作

本部分将指导你尽可能安全地配置和运行函数应用。

Defender for Cloud

Defender for Cloud 与门户中的函数应用集成。 它免费提供了对潜在配置相关安全漏洞的快速评估。 在专用计划中运行的函数应用也可以使用 Defender for Cloud 的增强安全功能,但需支付额外费用。

日志和监视器

检测攻击的一种方法是进行活动监视和日志分析。 Functions 与 Application Insights 相集成,可收集函数应用的日志、性能和错误数据。 Application Insights 可自动检测性能异常,并且包含了强大的分析工具来帮助你诊断问题并了解函数的使用方式。 若要了解详细信息,请参阅监视 Azure Functions

Functions 还与 Azure Monitor 日志集成,使你能够将函数应用日志与系统事件合并,以便更轻松地进行分析。 你可以使用诊断设置将函数的平台日志和指标流式导出配置到你选择的目标位置,例如 Log Analytics 工作区。 若要了解更多信息,请参阅使用 Azure Monitor 日志监视 Azure Functions

对于企业级威胁检测和响应自动化,请将日志和事件流式传输到 Log Analytics 工作区。 然后,可以将 Microsoft Sentinel 连接到此工作区。

需要 HTTPS

默认情况下,客户端可以使用 HTTP 或 HTTPS 连接到函数终结点。 应将 HTTP 重定向到 HTTPS,因为 HTTPS 使用 SSL/TLS 协议来提供安全连接,该连接经过了加密和身份验证。 若要了解如何操作,请参阅实施 HTTPS

需要 HTTPS 时,还需要最新的 TLS 版本。 若要了解如何操作,请参阅实施 TLS 版本

有关详细信息,请参阅保护连接 (TLS)

函数访问密钥

Functions 允许使用密钥来增大开发期间访问 HTTP 函数终结点的难度。 除非 HTTP 触发的函数中的 HTTP 访问级别设置为 anonymous,否则请求中必须包含 API 访问密钥。

尽管密钥提供默认的安全机制,但可能需要考虑使用其他选项来保护生产环境中的 HTTP 终结点。 例如,在公共应用中分发共享机密通常不是一个好做法。 如果从公共客户端调用函数,则可能需要考虑实施另一种安全机制。 有关详细信息,请参阅在生产环境中保护 HTTP 终结点

续订函数密钥值时,必须手动将更新的密钥值重新分发给调用你的函数的所有客户端。

授权范围(函数级别)

函数级密钥有两个访问权限作用域:

  • 函数:这些密钥仅适用于定义它们的特定函数。 这些密钥用作 API 密钥时,只允许访问该函数。

  • 主机:主机范围的密钥可用于访问函数应用中的所有函数。 这些密钥用作 API 密钥时,可以访问函数应用中的任何函数。

命名每个密钥方便引用,并且在函数和主机级别存在名为“default”的默认密钥。 函数密钥优先于主机密钥。 如果为两个密钥定义的名称相同,则使用函数密钥。

主密钥(管理员级别)

每个函数应用还有一个名为 _master 的管理员级主机密钥。 除了提供对应用中所有函数的主机级的访问权限外,主密钥还提供对运行时 REST API 的管理访问权限。 无法撤消此密钥。 设置 admin 访问级别时,请求必须使用主密钥;使用任何其他密钥会导致访问失败。

注意

由于主密钥在函数应用中授予提升的权限,不应与第三方共享此密钥或在本机客户端应用程序中分发此密钥。 选择管理访问级别时请慎重。

系统密钥

特定扩展可能需要系统管理的密钥才能访问 webhook 终结点。 系统密钥适合为内部组件调用的特定于扩展的函数终结点。 例如,事件网格触发器要求订阅在调用触发器终结点时使用系统密钥。 Durable Functions 还使用系统密钥调用 Durable 任务扩展 API

系统密钥的范围由扩展决定,但通常适用于整个函数应用。 系统密钥只能由特定扩展创建,并且不能显式设置其值。 与其他密钥一样,你可从门户或使用密钥 API 为密钥生成新值。

密钥之间的比较

下表比较了不同类型的访问密钥的用法:

操作 作用域 有效密钥
执行函数 特定函数 函数
执行函数 任何函数 函数或主机
调用管理员终结点 函数应用 主机(仅限 master)
调用 Durable 任务扩展 API 函数应用1 系统2
调用特定于扩展的 Webhook(内部) 函数应用1 系统2

1范围由扩展决定。
2按扩展设置的特定名称。

若要了解有关访问密钥的更多信息,请参阅 HTTP 触发器绑定文章

机密存储库

默认情况下,密钥存储在通过 AzureWebJobsStorage 设置提供的帐户中的 Blob 存储容器中。 可以使用 AzureWebJobsSecretStorageType 设置来重写此行为,将密钥存储在另一位置。

位置 说明
第二个存储帐户 blob 根据 AzureWebJobsSecretStorageSas 中的 SAS URL,将密钥存储在另一个存储帐户的 Blob 存储中。
文件系统 files 密钥保留在文件系统上,这是 Functions v1.x 中的默认值。
Azure Key Vault keyvault AzureWebJobsSecretStorageKeyVaultUri 中设置的密钥保管库用于存储密钥。
Kubernetes 机密 kubernetes AzureWebJobsKubernetesSecretName 中的资源集用于存储密钥。 仅当在 Kubernetes 中运行 Functions 运行时时才受支持。 在部署到 Kubernetes 时,Azure Functions Core Tools 会自动生成值。

将 Key Vault 用于密钥存储时,所需的应用设置取决于托管标识类型。 Functions 运行时版本 3.x 仅支持系统分配的托管标识。

设置名 系统分配 用户分配 应用注册
AzureWebJobsSecretStorageKeyVaultUri
AzureWebJobsSecretStorageKeyVaultClientId X
AzureWebJobsSecretStorageKeyVaultClientSecret X X
AzureWebJobsSecretStorageKeyVaultTenantId X X

身份验证/授权

虽然函数密钥可以为不需要的访问提供一些缓解措施,但真正保护函数终结点的唯一方法是实现对访问函数的客户端的主动身份验证。 然后,你可以根据身份做出授权决策。

启用应用服务身份验证/授权

借助应用服务平台可以使用 Azure Active Directory (AAD) 和多个第三方标识提供者对客户端进行身份验证。 可以使用此策略来实现函数的自定义授权规则,并且可以从函数代码处理用户信息。 若要了解详细信息,请参阅 Azure 应用服务中的身份验证和授权以及使用客户端标识

使用 Azure API 管理 (APIM) 对请求进行身份验证

APIM 为传入请求提供了各种 API 安全选项。 若要了解详细信息,请参阅 API 管理身份验证策略。 有了 APIM,可以配置函数应用以接受仅来自 APIM 实例 IP 地址的请求。 若要了解详细信息,请参阅 IP 地址限制

权限

与任何应用程序或服务一样,目标是以尽可能低的权限运行函数应用。

用户管理权限

函数支持内置 Azure 基于角色的访问控制 (Azure RBAC)。 函数支持的 Azure 角色有参与者所有者读者

权限在函数应用级别有效。 参与者角色是执行大多数函数应用级任务所必需的。 你还需要有参与者角色以及监视读取者权限,才能在 Application Insights 中查看日志数据。 只有所有者角色才能删除函数应用。

按权限组织函数

应用程序设置中存储的连接字符串和其他凭据为函数应用中的所有函数提供了关联资源中相同的权限集。 请考虑将具有特定凭据访问权限的函数数量降至最少,具体方法是将不使用这些凭据的函数移动到单独的函数应用中。 你始终可以使用诸如函数链之类的技术在不同函数应用中的函数之间传递数据。

托管标识

借助 Azure Active Directory (Azure AD) 的托管标识,应用可以轻松访问其他受 Azure AD 保护的资源(如 Azure Key Vault)。 标识由 Azure 平台托管,无需设置或转交任何机密。 有关 Azure AD 中的托管标识的详细信息,请参阅 Azure 资源的托管标识

你的应用程序可以被授予两种类型的标识:

  • 系统分配的标识与你的应用程序相绑定,如果删除应用,标识也会被删除。 一个应用只能具有一个系统分配的标识。
  • 用户分配的标识是可以分配给应用的独立 Azure 资源。 一个应用可以具有多个用户分配的标识。

托管标识可用于替代来自某些触发器和绑定的连接的机密。 请参阅基于标识的连接

有关详细信息,请参阅如何使用应用服务和 Azure Functions 的托管标识

限制 CORS 访问

跨源资源共享 (CORS) 是一种允许在另一个域中运行的 Web 应用向 HTTP 触发器终结点发出请求的方法。 应用服务为在 HTTP 请求中处理所需的 CORS 标头提供了内置支持。 CORS 规则是在函数应用级别定义的。

虽然使用允许所有站点访问终结点的通配符很诱人,但这会破坏有助于防止跨站点脚本攻击的 CORS 目的。 相反,请为必须访问终结点的每个 Web 应用的域添加单独的 CORS 条目。

管理机密

为了能够连接到运行代码所需的各种服务和资源,函数应用需要能够访问机密,如连接字符串和服务密钥。 本节介绍如何存储函数所需的机密。

切勿在函数代码中存储机密。

应用程序设置

默认情况下,请将函数应用使用的连接字符串和机密以及绑定存储为应用程序设置。 这样,函数代码和函数使用的各种绑定就都可以使用这些凭据。 应用程序设置(密钥)名称用于检索实际值,即机密。

例如,每个函数应用都需要一个关联的存储帐户,运行时将使用该帐户。 默认情况下,与此存储帐户的连接存储在名为 AzureWebJobsStorage 的应用程序设置中。

应用设置和连接字符串以加密方式存储在 Azure 中。 只有在应用程序启动时,它们才会被解密,然后再注入到应用程序内存中。 加密密钥会定期轮换。 如果希望管理机密的安全存储,则应该将应用设置改为对 Azure Key Vault 的引用。

在本地计算机上开发功能时,默认情况下,还可以在 local.settings.json 文件中加密设置。 有关详细信息,请参阅加密本地设置文件

Key Vault 引用

虽然应用程序设置足以满足大多数功能,但你可能希望跨多个服务共享相同的机密。 在这种情况下,机密的冗余存储会导致更多潜在的漏洞。 一种更安全的方法是使用中央机密存储服务,并使用对该服务的引用而不是对机密本身的引用。

Azure Key Vault 是一项服务,可以提供集中式机密管理,并且可以完全控制访问策略和审核历史记录。 你可在应用程序设置中使用 Key Vault 引用来代替连接字符串或密钥。 若要了解详细信息,请参阅使用应用服务和 Azure Functions 的 Key Vault 引用

基于标识的连接

标识可用于代替机密来连接到某些资源。 这种方法的优点是不需要管理机密,而是提供更精细的访问控制和审核。

编写用于创建与支持 Microsoft Entra 身份验证的 Azure 服务的连接的代码时,可以选择使用标识而不是机密或连接字符串。 每个服务的文档中都介绍了这两种连接方法的详细信息。

某些 Azure Functions 触发器和绑定扩展可以使用基于标识的连接进行配置。 现在,这包括 Azure BlobAzure 队列扩展。 有关如何配置这些扩展以使用标识的详细信息,请参阅如何在 Azure Functions 中使用基于标识的连接

设置使用配额

考虑为在消耗计划中运行的函数设置使用配额。 如果对函数应用中函数的总执行量设置每日 GB-sec 限制,当达到该限制时,将停止执行。 这可能有助于缓解恶意代码执行函数。 若要了解如何估算函数的消耗量,请参阅估算消耗计划成本

数据验证

函数使用的触发器和绑定不提供任何额外的数据验证。 代码必须验证从触发器或输入绑定接收到的任何数据。 如果上游服务遭到入侵,你不希望未经验证的输入流经函数。 例如,如果函数将 Azure 存储队列中的数据存储在关系数据库中,则必须验证数据并对命令进行参数化处理以避免 SQL 注入攻击。

不要以为传入函数的数据已经过验证或清理。 最好是验证写入输出绑定的数据是否有效。

处理错误

虽然它看起来很基础,但这对于在函数中编写良好的错误处理来说非常重要。 未处理的错误从主机中涌现出来,然后由运行时处理。 不同绑定处理错误的方式不同。 有关详细信息,请参阅 Azure Functions 错误处理

禁用远程调试

请确保禁用远程调试,除非你正在主动调试函数。 可以在门户中函数应用“配置”的“常规设置”选项卡中禁用远程调试 。

限制 CORS 访问

Azure Functions 支持跨域资源共享 (CORS)。 CORS 在门户中以及通过 Azure CLI 进行配置。 CORS 允许的来源列表应用于函数应用级别。 启用 CORS 后,响应包含 Access-Control-Allow-Origin 标头。 有关详细信息,请参阅 跨域资源共享

请勿在允许的来源列表中使用通配符。 相反,你可以列出想要从中获取请求的特定域。

存储加密数据

Azure 存储可对存储帐户中的所有数据进行静态加密。 有关详细信息,请参阅静态数据的 Azure 存储加密

默认情况下,数据使用 Microsoft 管理的密钥进行加密。 为了进一步控制加密密钥,可以提供客户管理的密钥,用于对 blob 和文件数据进行加密。 这些密钥必须存在于 Azure Key Vault 中,以便 Functions 能够访问存储帐户。 若要了解详细信息,请参阅使用客户管理的密钥进行静态加密

函数应用通常依赖于其他资源,因此保护应用的一部分任务就是保护这些外部资源。 大多数函数应用都至少包含一个针对 Application Insights 和 Azure 存储的依赖项。 有关保护这些资源的指南,请参阅 Azure Monitor 的 Azure 安全基线存储的 Azure 安全基线

重要

存储帐户用于存储重要的应用数据,有时包括应用程序代码本身。 应限制其他应用和用户对存储帐户的访问。

还应参阅有关应用程序逻辑所依赖的任何资源类型(无论是触发器和绑定形式,还是来自函数代码)的指南。

保护部署

Azure Functions 工具集成可以简化将本地函数项目代码发布到 Azure 的过程。 在考虑 Azure Functions 拓扑的安全性时,请务必了解部署的工作方式。

部署凭据

部署应用服务需要一组部署凭据。 这些部署凭据用于保护函数应用部署。 部署凭据由应用服务平台管理,并静态加密。

部署凭据有两种类型:

  • 用户级凭据:一组适用于整个 Azure 帐户的凭据。 需要部署到任何订阅(Azure 帐户有权对其进行访问)中的任何应用的应用服务时,可以使用这组凭据。 这是在门户 GUI(例如应用的资源页的“概览”和“属性”)中呈现的默认组。 当通过基于角色的访问控制 (RBAC) 或共同管理员权限授予用户应用访问权限时,该用户便可使用其用户级别的凭据,直到被撤销访问权限。 请勿与其他 Azure 用户共享这些凭据。

  • 应用级凭据:一组适用于每个应用的凭据。 若要只部署到该应用,则可使用这组凭据。 每个应用的凭据在其创建时自动生成。 这些凭据不能手动进行配置,但可随时进行重置。 如果要通过 (RBAC) 授予用户访问应用级别凭据的权限,该用户必须是应用的参与者或更高级别身份(包括网站参与者内置角色)。 读者不可进行发布,因此无法访问这些凭据。

目前,部署凭据不支持 Key Vault。 若要了解如何管理部署凭据,请参阅为 Azure 应用服务配置部署凭据

禁用 FTP

默认情况下,每个函数应用都启用了 FTP 终结点。 使用部署凭据访问 FTP 终结点。

不建议使用 FTP 来部署函数代码。 FTP 部署是手动的,需要同步触发器。 若要了解详细信息,请参阅 FTP 部署

如果不打算使用 FTP,则应在门户中禁用它。 如果选择使用 FTP,则应实施 FTPS

保护 scm 终结点

每个函数应用都有一个对应的 scm 服务终结点,供高级工具 (Kudu) 服务用于部署和其他应用服务scm。 函数应用的 scm 终结点始终是 https://<FUNCTION_APP_NAME.scm.chinacloudsites.cn> 格式的 URL。 如果使用网络隔离保护函数,还必须考虑此终结点。

具有独立的 scm 端点使你可以控制针对隔离或在虚拟网络中运行的函数应用的部署和其他高级工具功能。 scm 终结点支持基本身份验证(使用部署凭据)和使用 Azure 门户凭据进行单一登录。 若要了解详细信息,请参阅访问 Kudu 服务

持续安全性验证

由于开发过程中的每一步都需要考虑安全性,因此在持续部署环境中实现安全性验证也是有意义的。

网络安全

通过限制对函数应用的网络访问,可以控制谁可以访问函数终结点。 函数利用应用服务基础结构,使函数能够访问资源而无需使用可通过 internet 路由的地址,或将 internet 访问限制为函数终结点。 若要了解有关这些网络选项的详细信息,请参阅 Azure Functions 网络选项

设置访问限制

访问限制使你可以定义允许/拒绝规则列表,以控制应用的流量。 规则按优先顺序进行评估。 如果没有定义规则,则应用将接受来自任何地址的流量。 若要了解更多信息,请参阅 Azure 应用服务访问限制

保护存储帐户

创建函数应用时,必须创建或链接到支持 Blob、队列和表存储的常规用途的 Azure 存储帐户。 可以将此存储帐户替换为服务终结点或专用终结点所保护的存储帐户。 有关详细信息,请参阅将存储帐户限制在虚拟网络中

专用站点访问

Azure 专用终结点是一种网络接口,你可通过该接口私密安全地连接到由 Azure 专用链接提供支持的服务。 专用终结点使用虚拟网络中的专用 IP 地址,从而将该服务有效地引入虚拟网络。

可以将专用终结点用于高级应用服务计划中托管的函数。

如果要调用专用终结点,则必须确保 DNS 查找解析到专用终结点。 可以使用以下方式之一强制执行此行为:

  • 与 Azure DNS 专用区域集成。 如果虚拟网络没有自定义 DNS 服务器,则会自动执行此操作。
  • 管理 DNS 服务器中由你的应用使用的专用终结点。 为此,你需要知道专用终结点地址,然后用 A 记录将你尝试连接的终结点指向该地址。
  • 将你自己的 DNS 服务器配置为转发到 Azure DNS 专用区域。

若要了解详细信息,请参阅为 Web 应用使用专用终结点

在隔离环境中部署函数应用

Azure 应用服务环境 (ASE) 提供了用于运行函数的专用宿主环境。 ASE 允许配置单个前端网关,可以使用它对所有传入请求进行身份验证。 有关详细信息,请参阅为应用服务环境配置 Web 应用程序防火墙 (WAF)

使用网关服务

利用网关服务(例如 Azure 应用程序网关),可以设置 Web 应用程序防火墙 (WAF)。 WAF 规则用于监视或阻止检测到的攻击,从而为函数提供额外的保护层。 若要设置 WAF,函数应用需要在 ASE 中运行或使用专用终结点(预览版)。 若要了解详细信息,请参阅使用专用终结点