服务网络

使用 Snowpark Container Services 服务时,需要考虑三种网络类型:

  • 入口网络:如何从 Snowflake 外部连接到您的服务。

  • 出口网络:服务如何连接到 Snowflake 外部的资源。

  • Snowpark Container Services 中的服务间通信。

以下部分说明如何配置每种网络。

配置服务入口

要允许任何内容通过互联网与服务交互,请在服务规范文件中将服务侦听的网络端口声明为端点。这些端点控制入口。

默认情况下,服务端点是专用的。只有 服务函数服务到服务通信 可以向专用端点发出请求。您可以将端点声明为公共端点,以允许通过互联网向端点发出请求,如以下示例服务规范所示。

备注

创建公共端点是一项权限操作,服务的所有者角色必须对账户拥有 BIND SERVICE ENDPOINT 权限。

endpoints:
- name: <endpoint name>
  port: <port number>
  protocol : < TCP / HTTP >
  public: true
  corsSettings:                  # optional CORS configuration
    Access-Control-Allow-Origin: # required list of allowed origins
      - <origin>                 # for example, "http://example.com"
      - <origin>
        ...
    Access-Control-Allow-Methods: # optional list of HTTP methods
      - <method>
      - <method>
        ...
    Access-Control-Allow-Headers: # optional list of HTTP headers
      - <header-name>
      - <header-name>
        ...
    Access-Control-Expose-Headers: # optional list of HTTP headers
      - <header-name>
      - <header-name>
        ...

有关示例,请参阅 教程 1

当您公开端点时,Snowflake 会为公共端点分配唯一的主机名。Snowflake 将具有该主机名的传入请求发送到服务。

如果要在单个主机名后面公开多个服务端点,可以创建 网关。网关根据网关配置将入口请求路由到一个或多个服务端点。有关网关和创建网关场景的更多信息,请参阅 使用网关将入口请求路由到多个端点

入口连接超时

入口端点的超时时间为 90 秒。如果入口端点的连接在 90 秒内无活动,Snowflake 将终止该连接。如果您的应用程序需要更长连接时间,请使用轮询或 WebSockets。

入口网页浏览器身份验证注销

如果您正在构建一个作为服务运行的 Web 应用程序,可以选择允许用户通过重定向到 /sfc-endpoint/logout 来从您的应用注销。

注销后,用户需要重新对 Snowflake 进行身份验证,才能访问服务的公共端点。

入口和 Web 应用程序安全性

您可以使用公共端点支持(网络入口)创建用于 Web 托管的 Snowpark Container Services。为了提高安全性,Snowflake 采用代理服务来监控从客户端到服务的传入请求以及从服务到客户端的传出响应。本节介绍代理的作用以及它如何影响部署到 Snowpark Container Services 的服务。

备注

在本地测试服务时,您没有使用 Snowflake 代理,因此在本地运行服务的体验与在 Snowpark Container Services 中部署的体验之间存在差异。查看本节并更新本地设置以更好地进行测试。

例如:

  • 如果请求使用了被禁止的 HTTP 方法,代理不会转发传入的 HTTP 请求。

  • 如果响应中的 Content-Type 标头指出响应包含可执行文件,则代理会向客户端发送 403 响应。

此外,代理还可以在请求和响应中注入新的标头并更改现有标头,同时兼顾容器和数据安全性。

例如,在收到请求后,服务可能会在响应中,将 HTML、JavaScript、CSS 以及其他网页内容发送到客户端浏览器。浏览器中的网页是服务的一部分,充当用户界面。出于安全原因,如果服务有限制(例如,限制与其他站点建立网络连接),您可能还希望服务网页具有同样的限制。

默认情况下,服务访问互联网的权限存在限制。在大多数情况下,浏览器还应限制客户端应用程序访问互联网和潜在的数据共享行为。如果设置外部访问集成 (EAI) 以允许服务访问 example.com (请参阅 配置服务出口 ),服务网页也应该能够通过浏览器访问 example.com

Snowflake 代理通过在响应中添加 Content-Security-Policy (CSP) 标头,对服务和网页应用同样的网络限制。默认情况下,代理会在响应中添加基线 CSP,以防范常见的安全威胁。浏览器安全性旨在尽最大努力在功能和安全性之间取得平衡,确保这个基准适用于您的用例是大家共同的责任。此外,如果服务配置为使用 EAI,代理将对网页从 EAI 到 CSP 应用同样的网络规则。此 CSP 使浏览器中的网页能够访问与服务相同的站点。

Snowflake 提供 CORS 支持,您可在服务规范中对其进行配置。

Snowflake 代理会返回服务规范中定义的 CORS 设置。请注意,代理会删除服务返回的任何 CORS 标头。

以下 CORS 标头为默认设置:

  • Access-Control-Expose-Headers 标头始终会报告以下标头名称,此外还包括端点服务规范中配置的标头信息。

    • X-Frame-Options

    • Cross-Origin-Opener-Policy

    • Cross-Origin-Resource-Policy

    • X-Content-Type-Options

    • Cross-Origin-Embedder-Policy

    • Content-Security-Policy-Report-Only

    • Content-Security-Policy

  • Access-Control-Max-Age 设置为两小时。

  • Access-Control-Allow-Credentials 设置为“true”。

此外,Snowflake 会将 Vary 标头的值设为 Origin,以告知浏览器:根据 Origin 的值不同,Access-Control-Allow-Origin 的返回值可能会变化。

需要 Authorization 标头才能发出 CORS 请求。您可以在此标头 (Authorization: "Snowflake Token=\"${patToken}\"") 中指定编程访问令牌 (PAT)。有关生成编程访问令牌的信息,请参阅 用于身份验证的编程访问令牌

以下各节介绍了 Snowflake 代理如何处理对服务的传入请求,并修改服务对客户端的传出响应。

传入服务的请求

当请求到达时,代理会先执行以下操作,然后再将请求转发到服务:

  • 采用禁止的 HTTP 方法的传入请求: 如果传入 HTTP 请求使用以下任意被禁止的 HTTP 方法,代理不会将请求转发到服务:

    • TRACE

    • CONNECT

  • 标头擦除: Snowflake 代理会移除以下请求标头(如果存在):

    • X-SF-SPCS-Authorization

    • Authorization:只有在包含 Snowflake 令牌时才会被移除;否则会传递给您的服务。

传出到客户端的响应

Snowflake 代理会先将这些修改应用于服务发送的响应,然后再将响应转发到客户端。

  • 标头清理: Snowflake 代理会删除这些响应标头(如果存在):

    • X-XSS-Protection

    • Server

    • X-Powered-By

    • Public-Key-Pins

  • CORS 标头操作: 请参阅 入口和 CORS 注意事项

  • Content-Type 响应标头: 如果服务响应包含 Content-Type 标头以及以下任何 MIME 类型值(指示可执行文件),Snowflake 代理不会将该响应转发到客户端。相反,代理会发送一个 403 Forbidden 响应。

    • application/x-msdownload:Microsoft 可执行文件。

    • application/exe:通用可执行文件。

    • application/x-exe:另一个通用可执行文件。

    • application/dos-exe:DOS 可执行文件。

    • application/x-winexe:Windows 可执行文件。

    • application/msdos-windows:MS-DOS Windows 可执行文件。

    • application/x-msdos-program:MS-DOS 可执行文件。

    • application/x-sh:Unix shell 脚本。

    • application/x-bsh:Bourne shell 脚本。

    • application/x-csh:C shell 脚本。

    • application/x-tcsh:Tcsh shell 脚本。

    • application/batch:Windows 批处理文件。

  • X-Frame-Options 响应标头: 为防止点击劫持攻击,Snowflake 代理将此响应标头设置为 DENY,以防止其他网页使用 iframe 访问服务网页。

  • Cross-Origin-Opener-Policy (COOP) 响应标头: Snowflake 将 COOP 响应标头设置为 same-origin 以防止引用跨域窗口访问服务选项卡。

  • Cross-Origin-Resource-Policy (CORP) 响应标头: Snowflake 将 CORP 标头设置为 same-origin 以防止外部站点加载入口端点公开的资源(例如,在 iframe 中)。

  • X-Content-Type-Options 响应标头: Snowflake 代理将此标头设置为 nosniff,以确保客户端不会更改服务在响应中指出的 MIME 类型。

  • Cross-Origin-Embedder-Policy (COEP) 响应标头: Snowflake 代理将 COEP 响应标头设置为 credentialless,这意味着在加载跨域对象(如图像或脚本)时,如果远程对象不支持跨域资源共享 (CORS) 协议,Snowflake 在加载时不会发送凭据。

  • Content-Security-Policy-Report-Only 响应标头: Snowflake 代理将此响应标头替换为新值,指示客户端向 Snowflake 发送 CSP 报告。

  • Content-Security-Policy (CSP) 响应标头: 默认情况下,Snowflake 代理会添加以下基线 CSP,以防止常见的 Web 攻击。

    default-src 'self' 'unsafe-inline' 'unsafe-eval' blob: data:; object-src 'none'; connect-src 'self'; frame-ancestors 'self';
    

    有两个内容安全策略注意事项:

    • 除了代理添加的基线内容安全策略外,服务本身还可以在响应中显式添加 CSP。服务可能会选择通过添加更严格的 CSP 来增强安全性。例如,服务可能会添加以下 CSP 以仅允许来自 self 的脚本。

      script-src 'self'
      

      在发送给客户端的结果响应中,将有两个 CSP 标头。收到响应后,客户端浏览器将应用最严格的内容安全策略,其中包括每个策略指定的其他限制。

    • 如果配置外部访问集成 (EAI) 以允许服务访问外部站点 (配置服务出口),Snowflake 代理会创建一个 CSP,以允许网页访问该站点。例如,假设与 EAI 关联的网络规则允许服务出口访问 example.com。然后,Snowflake 代理将添加此 CSP 响应标头:

      default-src 'self' 'unsafe-inline' 'unsafe-eval' http://example.com https://example.com blob: data:; object-src 'none'; connect-src 'self' http://example.com https://example.com wss://example.com; frame-ancestors 'self';
      

      浏览器遵循响应中收到的内容访问策略。在此示例中,浏览器允许应用程序访问 example.com, 但不允许访问其他站点。

入口和 CORS 注意事项

默认情况下,浏览器会阻止一个服务器上的 Web 应用程序向另一个不同主机名的服务器发送请求。例如,如果您在 Snowpark Container Services 之外托管一个 Web 应用程序,而该应用程序需要与部署在 Snowpark Container Services 内的后端服务进行交互,则适用此限制。

CORS(跨源资源共享)使 Snowpark Container Services 能够告诉浏览器允许来自其环境外托管的 Web 应用程序的请求。您可以配置每个公共端点,指定它如何响应 CORS 预检请求和标准请求。

Snowflake 代理始终覆盖以下响应标头:

  • Access-Control-Allow-Origin

  • Access-Control-Allow-Methods

  • Access-Control-Allow-Headers

  • Access-Control-Expose-Headers

  • Access-Control-Max-Age

  • Access-Control-Allow-Credentials

当以下任一情况为 true 时,Snowflake 代理不会在响应中包含任何此类 CORS 标头:

  • 服务端点未配置 CORS。也就是说,服务规范中没有 corsSettings

  • 已为服务端点配置 CORS,但请求中的 Origin 标头与服务规范中指定的 Access-Control-Allow-Origin 字段不匹配

在服务规范中,您可以为每个公共端点配置 CORS 设置。当请求中的 origin 标头与规范中为端点指定的 Access-Control-Allow-Origin 字段相匹配时,代理就会在响应中包含规范中定义的 CORS 标头,并作如下调整:

  • Access-Control-Allow-Origin:返回请求中的 Origin 标头。

  • Access-Control-Expose-Headers:将您配置的允许标头列表与这些始终公开的标头合并:X-Frame-OptionsCross-Origin-Opener-PolicyCross-Origin-Resource-PolicyX-Content-Type-OptionsCross-Origin-Embedder-PolicyContent-Security-Policy-Report-OnlyContent-Security-Policy

  • Access-Control-Max-Age:设置为两小时。

  • Access-Control-Allow-Credentials:设置为“true”。

入口和 SSO 注意事项

当从互联网访问公共端点时,您可能会发现用户名/密码身份验证正常,但 SSO 导致空白页或错误:“OAuth client integration with the given client ID is not found.”

如果将旧版本的联合身份验证 (SSO) 用于 Snowflake,而不是使用 配置 Snowflake 以使用联合身份验证 中说明的较新安全集成版本,就会出现这种情况。执行以下操作以验证:

  1. 运行以下查询:

    SHOW PARAMETERS LIKE 'SAML_IDENTITY_PROVIDER' IN ACCOUNT;
    

    如果您设置了此参数,那么在某些时候您使用的是旧版本的联合身份验证。

  2. 如果设置了前面的参数,请运行以下查询以查看是否进行了 SAML 安全集成:

    SHOW INTEGRATIONS
      ->> SELECT * FROM $1 WHERE "type" = 'SAML2';
    

    如果您没有任何 SAML2 类型的集成,那么您使用的是旧版本的联合身份验证。

在这种情况下,解决方案是从旧版本联合身份验证迁移到新的集成式联合身份验证。有关更多信息,请参阅 迁移到 SAML2 安全集成

配置服务出口

应用程序代码可能需要访问互联网。默认情况下,应用程序容器没有访问互联网的权限。您需要使用 外部访问集成 (EAIs) 启用互联网访问。

通常,您希望账户管理员创建 EAIs 来管理允许通过服务(包括作业服务)进行的外部访问。然后,账户管理员可以向开发者用于运行服务的特定角色授予 EAI 使用量。

以下示例概述了创建 EAI 的步骤,这允许出口流量流向使用网络规则制定的特定目的地。然后,您可以在创建服务时引用 EAI 以允许对特定互联网目的地的请求。

示例

假设您希望应用程序代码将请求发送到以下目的地:

  • 向 translation.googleapis.com 发出 HTTPS 请求

  • 向 google.com 发出 HTTP 和 HTTPS 请求

按照以下步骤操作,使服务能够访问互联网上的这些域:

  1. 创建外部访问集成 (EAI)。这需要适当的权限。例如,您可以使用 ACCOUNTADMIN 角色来创建 EAI。这个过程分为两步:

    1. 使用 CREATE NETWORK RULE 命令创建一个或多个出口网络规则,列出您希望允许访问的外部目的地。您可以使用一个网络规则来完成此示例,但为便于说明,我们创建了两个网络规则:

      1. 创建名为 translate_network_rule 的网络规则:

        CREATE OR REPLACE NETWORK RULE translate_network_rule
          MODE = EGRESS
          TYPE = HOST_PORT
          VALUE_LIST = ('translation.googleapis.com');
        

        此规则允许 TCP 连接到 translation.googleapis.com 目的地。VALUE_LIST 属性中的域未指定可选端口号,因此将使用默认端口 443 (HTTPS)。这使应用程序可以连接到以 https://translation.googleapis.com/ 开头的任何 URL。

      2. 创建名为 google_network_rule 的网络规则:

        CREATE OR REPLACE NETWORK RULE google_network_rule
          MODE = EGRESS
          TYPE = HOST_PORT
          VALUE_LIST = ('google.com:80', 'google.com:443');
        

        这使应用程序可以连接到任何以 http://google.com/https://google.com/ 开头的 URL。

      备注

      对于 VALUE_LIST 参数,您必须提供完整的主机名。不支持通配符(例如,*.googleapis.com)。

      Snowpark Container Services 仅支持允许端口 22、80、443 和 1024+ 的网络规则。如果引用的网络规则允许访问其他端口,则服务创建将失败。如果您需要使用其他端口,请联系客户代表。

      备注

      要允许服务向互联网上的任何目的地发送 HTTP 或 HTTPS 请求,请指定“0.0.0.0”作为 VALUE_LIST 属性。以下网络规则允许在互联网上的任何位置发送“HTTP”和“HTTPS”请求。“0.0.0.0”仅支持端口 80 或 443。

      CREATE NETWORK RULE allow_all_rule
        TYPE = 'HOST_PORT'
        MODE= 'EGRESS'
        VALUE_LIST = ('0.0.0.0:443','0.0.0.0:80');
      
    2. 创建外部访问集成 (EAI),指定允许使用上述两个出口网络规则:

      CREATE EXTERNAL ACCESS INTEGRATION google_apis_access_integration
        ALLOWED_NETWORK_RULES = (translate_network_rule, google_network_rule)
        ENABLED = true;
      

      现在,账户管理员可以向开发者授予集成使用量,以允许他们运行可以访问互联网上特定目的地的服务。

      GRANT USAGE ON INTEGRATION google_apis_access_integration TO ROLE test_role;
      
  2. 按照以下示例,通过提供 EAI 创建服务。创建服务的所有者角色需要 EAI 的 USAGE 权限和引用密钥的 READ 权限。请注意,您不能使用 ACCOUNTADMIN 角色来创建服务。

    • 创建服务:

      USE ROLE test_role;
      
      CREATE SERVICE eai_service
        IN COMPUTE POOL MYPOOL
        EXTERNAL_ACCESS_INTEGRATIONS = (GOOGLE_APIS_ACCESS_INTEGRATION)
        FROM SPECIFICATION
        $$
        spec:
          containers:
            - name: main
              image: /db/data_schema/tutorial_repository/my_echo_service_image:tutorial
              env:
                TEST_FILE_STAGE: source_stage/test_file
              args:
                - read_secret.py
          endpoints:
            - name: read
              port: 8080
        $$;
      

      此示例 CREATE SERVICE 请求使用内联服务规范,并指定可选的 EXTERNAL_ACCESS_INTEGRATIONS 属性以纳入 EAI。EAI 指定允许从服务到特定目的地的出口流量的网络规则。

    • 执行作业服务:

      EXECUTE JOB SERVICE
        IN COMPUTE POOL tt_cp
        NAME = example_job_service
        EXTERNAL_ACCESS_INTEGRATIONS = (GOOGLE_APIS_ACCESS_INTEGRATION)
        FROM SPECIFICATION $$
        spec:
          container:
          - name: curl
            image: /tutorial_db/data_schema/tutorial_repo/alpine-curl:latest
            command:
            - "curl"
            - "http://google.com/"
        $$;
      

      此示例 EXECUTE JOB SERVICE 命令指定内联规范和可选的 EXTERNAL_ACCESS_INTEGRATIONS 属性以纳入 EAI。这允许从作业到 EAI 允许的网络规则中指定的目的地的出口流量。

使用专用连接的网络出口

您可能会选择通过 专用连接端点 来引导服务的出口流量,而不是通过公共互联网路由网络出口。

首先需要在 Snowflake 账户中创建专用连接端点。然后配置网络规则以允许传出流量使用 专用连接。设置外部访问集成 (EAI) 的过程与上一节中所述的过程相同。

备注

专用通信要求 Snowflake 和客户的云账户使用相同的云提供商和相同的区域。

例如,如果您想通过专用连接启用服务对 Amazon S3 桶的出站互联网访问,请执行以下操作:

  1. 启用自维护端点服务 (Amazon S3) 的专用链接连接。有关分步说明,请参阅 Amazon S3 的 AWS 专用链接 (https://docs.aws.amazon.com/AmazonS3/latest/userguide/privatelink-interface-endpoints.html)。

  2. 调用 SYSTEM$PROVISION_PRIVATELINK_ENDPOINT 系统函数,以在 Snowflake VNet 中预置专用连接端点。这使 Snowflake 能够使用专用连接连接到外部服务(在本示例中为 Amazon S3)。

    USE ROLE ACCOUNTADMIN;
    
    SELECT SYSTEM$PROVISION_PRIVATELINK_ENDPOINT(
      'com.amazonaws.us-west-2.s3',
      '*.s3.us-west-2.amazonaws.com'
    );
    
  3. 在云提供商账户中,批准该端点。在本示例中,对于 Amazon AWS,请参阅 AWS 文档中的 接受或拒绝连接请求 (https://docs.aws.amazon.com/vpc/latest/privatelink/configure-endpoint-service.html#accept-reject-connection-requests)。 另外,要批准 Azure 中的端点,请参阅 Azure 文档 (https://learn.microsoft.com/en-us/azure/private-link/manage-private-endpoint?tabs=manage-private-link-powershell#private-endpoint-connections)。

  4. 使用 CREATE NETWORK RULE 命令创建出口网络规则,指定您希望允许访问的外部目的地。

    CREATE OR REPLACE NETWORK RULE private_link_network_rule
      MODE = EGRESS
      TYPE = PRIVATE_HOST_PORT
      VALUE_LIST = ('<bucket-name>.s3.us-west-2.amazonaws.com');
    

    TYPE 参数值已设置为 PRIVATE_HOST_PORT。这表示网络规则允许传出网络流量使用 专用连接

  5. 创建 EAI 并使用它创建服务的其余步骤与上一节中说明的步骤相同(请参阅 配置服务出口)。

有关使用专用连接端点的更多信息,请参阅以下内容:

配置服务之间通信时的注意事项

有两个注意事项:

  • 服务实例的容器之间的通信: 如果一个服务实例运行多个容器,这些容器可以通过 localhost 相互通信(无需在服务规范中定义端点)。

  • 跨多个服务或多个服务实例的容器之间的通信: 属于不同服务(或同一服务的不同实例)的容器可以使用规范文件中定义的端点进行通信。有关更多信息,请参阅 服务到服务通信