Snowpark Container Services: considerações adicionais sobre serviços¶
Execução de SQL¶
O contêiner do aplicativo pode se conectar ao Snowflake e executar SQL. Este tópico descreve como o código do contêiner obtém as informações necessárias para se conectar ao Snowflake, incluindo as credenciais de autenticação, o contexto de banco de dados e esquema do serviço e o warehouse usado para executar as instruções SQL.
Opções de configuração de credenciais¶
A Snowflake recomenda que os contêineres de aplicativo usem credenciais fornecidas pelo Snowflake para autenticação no Snowflake ao executar SQL. É possível usar outras credenciais conectando-se por meio de uma integração de acesso externo (External Access Integration, EAI), mas a conexão por meio de uma EAI considera que o serviço está sendo executado fora do Snowflake e usa uma conexão de internet para se conectar ao Snowflake.
You have three options to connect to Snowflake from a service container:
Usar as credenciais de usuário de serviço fornecidas pelo Snowflake: o Snowflake fornece a cada serviço credenciais chamadas de «credenciais de serviço». Um serviço usa essas credenciais para se conectar ao Snowflake como usuário do serviço.
Usar as credenciais de autor da chamada fornecidas pelo Snowflake (direitos do autor da chamada): quando você configura seu serviço com direitos do autor da chamada, o Snowflake também fornece credenciais para que o serviço se conecte ao Snowflake como o usuário que faz a chamada.
Use other credentials: In this case, you use an external access integration (EAI) that allows your service to connect to Snowflake’s internet endpoint by using valid authentication credentials. This option requires an administrator to create the EAI, and then grant the USAGE privilege on the integration to the service owner role.
Nota
Se você usar integrações de acesso externo para acessar o Snowflake, poderá enviar informações potencialmente confidenciais pela Internet.
Para obter exemplos de código que usa vários drivers do Snowflake para se conectar ao Snowflake, consulte Amostras de conexão com o Snowflake.
Usando as credenciais de usuário do serviço fornecidas pelo Snowflake¶
Ao usar credenciais de serviço fornecidas pelo Snowflake, esteja ciente dos seguintes efeitos:
Every object in Snowflake has an owner role, which is the role that is used to create the object. A service’s owner role determines the capabilities that the service is allowed when it interacts with Snowflake. These capabilities include executing SQL, accessing stages, and performing service-to-service networking.
When you create a service, Snowflake also creates a service user that is specific to that service. That service user has access to only two roles: the service owner role and the “PUBLIC” role. The default role for the service user is the service owner role.
When you start a service, including job services, Snowflake performs several actions. In each of your application containers, Snowflake enables the container code to use drivers for connecting to Snowflake and executing SQL, which is similar to any other code on your computer connecting to Snowflake. The following list shows the actions that Snowflake performs when you start a service:
Provides credentials (an OAuth token) in the container in a file that is named
/snowflake/session/token. The container code uses these credentials to authenticate as the service user. This OAuth token can’t be used outside Snowpark Container ServicesSets the following environment variables for you to configure a Snowflake client in your service code:
SNOWFLAKE_ACCOUNT: This variable is set to the account locator for the Snowflake account that the service is currently running under.
SNOWFLAKE_HOST: This variable provides the hostname that is used to connect to Snowflake.
Quando você cria uma conexão com o Snowflake como usuário do serviço, o código do contêiner deve usar SNOWFLAKE_HOST, SNOWFLAKE_ACCOUNT e o token OAuth. O token OAuth não pode ser usado sem também usar SNOWFLAKE_HOST.
Exemplo
Em Tutorial 2 (consulte main.py), o código lê as variáveis de ambiente conforme mostrado no exemplo a seguir:
SNOWFLAKE_ACCOUNT = os.getenv('SNOWFLAKE_ACCOUNT')
SNOWFLAKE_HOST = os.getenv('SNOWFLAKE_HOST')
The code passes these variables to a connection creation code for the Snowflake client of choice. The container uses these credentials to create a new session, with the service’s owner role as the session’s primary role, to run queries. The following example shows the minimum code that you need to create a Snowflake connection in Python:
def get_login_token():
with open('/snowflake/session/token', 'r') as f:
return f.read()
conn = snowflake.connector.connect(
host = os.getenv('SNOWFLAKE_HOST'),
account = os.getenv('SNOWFLAKE_ACCOUNT'),
token = get_login_token(),
authenticator = 'oauth'
)
Be aware of the following details about this OAuth token:
Snowflake refreshes the content of the
/snowflake/session/tokenfile every few minutes. Every token is valid for up to one hour. After a container connects to Snowflake successfully, the expiration time doesn’t apply to the connection, as is the case with any sessions that users create directly.This OAuth token is valid only within the specific Snowflake service. You can’t copy the OAuth token and use it outside the service.
If you use the OAuth token to connect, it creates a new session. The OAuth token is not associated with any existing SQL session.
Nota
A significant difference between executing stored procedures and executing a service is that stored procedures run in the same session as the SQL that runs the procedures. But every time a container establishes a new connection, you create a new session.
Para visualizar as consultas emitidas por um usuário de serviço específico, você pode usar a função ACCOUNTADMIN para visualizar o histórico de consultas. O nome de usuário do usuário de serviço aparece nos seguintes formatos:
Para um serviço criado antes do lançamento do servidor 8.35, o nome de usuário do serviço tem o formato
SF$SERVICE$unique-id.Para um serviço criado após o lançamento do servidor 8.35, o nome de usuário do serviço é o mesmo que o nome do serviço.
Nota
A service’s owner role is the role that created the service. You can define one or more service roles to manage access to the endpoints that the service exposes. For more information, see Gerenciar privilégios relacionados ao serviço.
Sobre o uso das credenciais de autor da chamada fornecidas pelo Snowflake (direitos do autor da chamada)¶
In certain application scenarios, you might need to execute queries by using the context of the end user rather than the service user as explained in the preceding section. The caller’s rights feature is used in this context.
For example, suppose that you create a service that exposes a public endpoint for a web application that displays a dashboard that uses data stored in Snowflake. You grant other users in your Snowflake account access to the dashboard by granting them the service role. When a user signs in, the dashboard displays only the data that user is authorized to access.
However, because containers by default execute queries by using the service user and the service’s owner role, the dashboard shows the data that the service’s owner role has access to, regardless of which end user connected to the endpoint. As a result, the dashboard isn’t limited to the data the end user is authorized to access, allowing the signed-in user to see data they shouldn’t have access to.
To limit the dashboard to show only data that is accessible to the signed in user, the application containers must execute SQL by using privileges granted to the end user. You can enable this by using caller’s rights in the application.
Nota
The caller’s rights feature is supported only when accessing a service using network ingress. The feature isn’t available when using a service function to access the service.
No momento, o recurso de direitos do chamador não é compatível com Snowflake Native App (aplicativos com contêineres).
Configure caller’s rights for your service¶
Configuring caller’s rights for your application is a two-step procedure.
In the service specification, set the
executeAsCallertotrue, in as shown in the following specification fragment:spec: containers: ... capabilities: securityContext: executeAsCaller: true
This setting tells Snowflake that the application intends to use caller’s rights and causes Snowflake to insert the
Sf-Context-Current-User-Tokenheader in every incoming request before sending the request to the application container. This user token facilitates query execution as the calling user. If not specified,executeAsCallerdefaults tofalse.Specifying the
executeAsCalleroption doesn’t affect the service’s ability to execute queries as the service user and service’s owner role. WithexecuteAsCallerenabled, the service has the option to connect to Snowflake both as a calling user and as a service user.To establish a Snowflake connection on behalf of the calling user, update your application code to create a login token that includes both the OAuth token that Snowflake provided to the service and the user token from the
Sf-Context-Current-User-Tokenheader.O token de login deve seguir este formato:
<service-oauth-token>.<Sf-Context-Current-User-Token>.This update is demonstrated in the following Python code fragment:
# Environment variables below will be automatically populated by Snowflake. SNOWFLAKE_ACCOUNT = os.getenv("SNOWFLAKE_ACCOUNT") SNOWFLAKE_HOST = os.getenv("SNOWFLAKE_HOST") def get_login_token(): with open("/snowflake/session/token", "r") as f: return f.read() def get_connection_params(ingress_user_token = None): # start a Snowflake session as ingress user # (if user token header provided) if ingress_user_token: logger.info("Creating a session on behalf of the current user.") token = get_login_token() + "." + ingress_user_token else: logger.info("Creating a session as the service user.") token = get_login_token() return { "account": SNOWFLAKE_ACCOUNT, "host": SNOWFLAKE_HOST, "authenticator": "oauth", "token": token } def run_query(request, query): ingress_user_token = request.headers.get('Sf-Context-Current-User-Token') # ingress_user_token is None if header not present connection_params = get_connection_params(ingress_user_token) with Session.builder.configs(connection_params).create() as session: # use the session to execute a query.
No exemplo acima:
A função
get_login_tokenlê o arquivo em que o Snowflake copiou o token OAuth para ser usado pelo contêiner.The
get_connection_paramsfunction constructs a token by concatenating the OAuth token and the user token from theSf-Context-Current-User-Tokenheader. The function includes this token in a dictionary of parameters that the application uses to connect to Snowflake.
Nota
When a service uses caller’s rights, it can connect to Snowflake as multiple users. You are responsible for managing access to resources that arn’t managed by Snowflake.
For example, in Streamlit apps, the st.connection object automatically caches the connection by using st.cache_resource in the global state, making it accessible across Streamlit sessions that are started by different users. When you use caller’s rights, consider using st.session_state to store connections on a per-session basis to avoid sharing connections between users.
For an example with step-by-step instructions, see Create a service with caller’s rights enabled.
Acesso a um serviço com direitos de chamador configurados¶
Configuring caller’s rights means that your service is establishing a Snowflake connection on behalf of the caller. How you log in to the service’s ingress endpoints, either programmatically or by using a browser, remains the same. After log in, the following behaviors and optionsapply:
Accessing a public endpoint using a browser: After you log into an endpoint, the service establishes a connection to** Snowflake on behalf of the calling user using the default role of the user. If there is no default role configured for the user, the PUBLIC role is used.
Accessing a public endpoint programmatically: When logging into an endpoint programmatically using JWT token, you can optionally set the
scopeparameter to specify the role to activate
Currently, after a service establishes a caller’s right connection to Snowflake on behalf of the caller, switching roles is not supported. If your application needs to use different roles to access different objects, you must change the user’s default secondary roles property.
To set up the user to have all secondary roles active by default, use the ALTER USER command to set the DEFAULT_SECONDARY_ROLES property of the user to (“ALL”), as shown in the following example:
ALTER USER my_user SET DEFAULT_SECONDARY_ROLES = ( 'ALL' );
Gerenciamento de concessões do chamador para um serviço¶
When a service creates a caller’s rights session, the session operates as the calling user, not as the service user. When an operation is performed by using this session, Snowflake applies a sequence oftwo permissions checks:
The first permissions check is performed as if the user created the session directly. This check is part of thenormal permission checks that Snowflake performs for the user.
The second permissions check verifies that the service is allowed to perform the operation on behalf of a user. Snowflake verifies this by ensuring that the service’s owner role was granted the necessary caller grants.
Em uma sessão de direitos do chamador, tanto a verificação de permissão normal quanto a verificação da função proprietária do serviço devem permitir a operação; isso é chamado de direitos restritos do chamador. Por padrão, o serviço não tem permissão para fazer nada em nome de um usuário. Você deve conceder explicitamente concessões de chamador ao serviço para que ele possa ser executado com os privilégios do chamador.
For example, suppose a user U1 uses a role R1 that has the SELECT privilege on the table T1. When U1 logs into the public endpoint of your
service (example_service), which is configured to use the caller’s rights, the service then establishes a connection with Snowflake on
behalf of U1.
Para permitir que o serviço consulte a tabela T1 em nome de U1, você precisa conceder à função de proprietário do serviço os seguintes privilégios:
Privilégios para resolver o nome da tabela, concedendo uma concessão ao chamador que permita que o serviço seja executado com o privilégio USAGE no banco de dados e no esquema dessa tabela.
Privilégios para usar um warehouse para executar consultas, concedendo uma concessão ao chamador que permite que o serviço seja executado com o privilégio USAGE em um warehouse.
Privilégios para consultar a tabela concedendo uma concessão de chamador que permite que o serviço seja executado com o privilégio SELECT na tabela
T1.
O exemplo a seguir mostra como conceder a função de proprietário do serviço com esses privilégios:
-- Permissions to resolve the table's name.
GRANT CALLER USAGE ON DATABASE <db_name> TO ROLE <service_owner_role>;
GRANT CALLER USAGE ON SCHEMA <schema_name> TO ROLE <service_owner_role>;
-- Permissions to use a warehouse
GRANT CALLER USAGE ON WAREHOUSE <warehouse_name> TO ROLE <service_owner_role>;
-- Permissions to query the table.
GRANT CALLER SELECT ON TABLE T1 TO ROLE <service_owner_role>;
Qualquer função em sua conta que tenha o privilégio global MANAGE CALLER GRANT pode conceder concessões de chamador. Para obter mais informações sobre as concessões do chamador, consulte GRANT CALLER e Direitos restritos do chamador.
Exemplo¶
For an example of a service that uses the caller’s rights feature when executing SQL queries on behalf of the users is provided. For more information, see Create a service with caller’s rights enabled.
Connect to Snowflake by using other credentials¶
Você pode usar outras formas de autenticação para conectar-se ao Snowflake, não apenas o token OAuth fornecido pelo Snowflake. Para fazer isso, crie uma integração de acesso externo (EAI) que permita que seu contêiner se conecte ao Snowflake como se o contêiner estivesse sendo executado fora do Snowflake e conectando-se pela Internet. Ao conectar-se dessa forma, você não precisa configurar o host usado pelo cliente.
Nota
Como essas conexões atravessam um EAI, a autenticação do Snowflake também aplica políticas de rede. Caso sua empresa exija políticas de rede, não será possível se conectar com outras credenciais.
Por exemplo, a conexão a seguir especifica o nome de usuário e a senha para autenticação:
conn = snowflake.connector.connect(
account = '<acct-name>',
user = '<user-name>',
password = '<password>'
)
To use a default hostname, you need external access integration with a network rule that allows access from your service to the
Snowflake internet hostname for your account. For example, if your account name is MYACCOUNT in the organization MYORG, the hostname is
myorg-myaccount.snowflakecomputing.com. For more information, see Configuração da saída da rede. Privatelink hostnames are not supported
Crie uma regra de rede que corresponda ao nome de host da Snowflake API da sua conta:
CREATE OR REPLACE NETWORK RULE snowflake_egress_access MODE = EGRESS TYPE = HOST_PORT VALUE_LIST = ('myorg-myaccount.snowflakecomputing.com');
Crie uma integração que use a regra de rede anterior:
CREATE EXTERNAL ACCESS INTEGRATION snowflake_egress_access_integration ALLOWED_NETWORK_RULES = (snowflake_egress_access) ENABLED = TRUE;
Configuration of the database and schema context for executing SQL¶
Além de fornecer as credenciais, o Snowflake fornece o contexto de banco de dados e esquema no qual o serviço é criado. O código do contêiner pode usar essa informação para executar SQL no mesmo contexto de banco de dados e esquema que o serviço.
Esta seção explica dois conceitos:
A lógica que o Snowflake usa para determinar o banco de dados e o esquema no qual criar seu serviço.
O método pelo qual o Snowflake transmite essas informações aos seus contêineres, permitindo assim que o código do contêiner execute SQL no mesmo banco de dados e contexto de esquema.
O Snowflake usa o nome do serviço para determinar o banco de dados e o esquema no qual criar um serviço:
Exemplo 1: nos seguintes comandos CREATE SERVICE e EXECUTE JOB SERVICE, o nome do serviço não especifica explicitamente um nome de banco de dados e esquema. O Snowflake cria o serviço e o serviço de trabalho no banco de dados e esquema atuais.
-- Create a service. CREATE SERVICE test_service IN COMPUTE POOL ... -- Execute a job service. EXECUTE JOB SERVICE IN COMPUTE POOL tutorial_compute_pool NAME = example_job_service ...
Exemplo 2: nos seguintes comandos CREATE SERVICE e EXECUTE JOB SERVICE, o nome do serviço inclui um nome de banco de dados e esquema. Snowflake cria o serviço e serviço do trabalho no banco de dados (
test_db) e esquema (test_schema) especificados, independentemente do esquema atual.-- Create a service. CREATE SERVICE test_db.test_schema.test_service IN COMPUTE POOL ... -- Execute a job service. EXECUTE JOB SERVICE IN COMPUTE POOL tutorial_compute_pool NAME = test_db.test_schema.example_job_service ...
Quando o Snowflake inicia um serviço, ele fornece informações de banco de dados e esquema para os contêineres em execução usando as seguintes variáveis de ambiente:
SNOWFLAKE_DATABASE
SNOWFLAKE_SCHEMA
O código do contêiner pode usar variáveis de ambiente no código de conexão para determinar qual banco de dados e esquema usar, conforme mostrado neste exemplo:
conn = snowflake.connector.connect(
host = os.getenv('SNOWFLAKE_HOST'),
account = os.getenv('SNOWFLAKE_ACCOUNT'),
token = get_login_token(),
authenticator = 'oauth',
database = os.getenv('SNOWFLAKE_DATABASE'),
schema = os.getenv('SNOWFLAKE_SCHEMA')
)
Exemplo
No Tutorial 2, você cria um serviço de trabalho do Snowflake que se conecta ao Snowflake e executa instruções SQL. As etapas a seguir resumem como o código do tutorial usa as variáveis de ambiente:
Na configuração comum (consulte a seção Configuração comum), você cria recursos, incluindo um banco de dados e um esquema. Você também define o banco de dados e o esquema atuais para a sessão:
USE DATABASE tutorial_db; ... USE SCHEMA data_schema;
Depois de criar um serviço de trabalho (executando EXECUTE JOB SERVICE), o Snowflake inicia o contêiner e define as seguintes variáveis de ambiente no contêiner para o banco de dados e o esquema atuais da sessão:
SNOWFLAKE_DATABASE é definido como “TUTORIAL_DB”
SNOWFLAKE_SCHEMA é definido como “DATA_SCHEMA”
O código do trabalho (consulte
main.pyno Tutorial 2) lê estas variáveis de ambiente:SNOWFLAKE_DATABASE = os.getenv('SNOWFLAKE_DATABASE') SNOWFLAKE_SCHEMA = os.getenv('SNOWFLAKE_SCHEMA')
O código do trabalho define o banco de dados e o esquema como o contexto no qual executar as instruções SQL (função
run_job()emmain.py):{ "account": SNOWFLAKE_ACCOUNT, "host": SNOWFLAKE_HOST, "authenticator": "oauth", "token": get_login_token(), "warehouse": SNOWFLAKE_WAREHOUSE, "database": SNOWFLAKE_DATABASE, "schema": SNOWFLAKE_SCHEMA } ...
Nota
SNOWFLAKE_ACCOUNT, SNOWFLAKE_HOST, SNOWFLAKE_DATABASE, SNOWFLAKE_SCHEMA são variáveis de ambiente que o Snowflake gera para o contêiner do aplicativo, mas SNOWFLAKE_WAREHOUSE não é (o código do aplicativo do Tutorial 2 criou essa variável porque o Snowflake não passa um nome de warehouse para um contêiner).
Como especificar o warehouse para seu contêiner¶
Se seu serviço se conectar ao Snowflake para executar uma consulta em um warehouse do Snowflake, você terá as seguintes opções para especificar um warehouse:
Especifique um warehouse no código do seu aplicativo. Especifique um warehouse como parte da configuração da conexão ao iniciar uma sessão do Snowflake para executar consultas no seu código. Para obter um exemplo, consulte Tutorial 2.
Specify a default warehouse when creating a service. Specify the optional QUERY_WAREHOUSE parameter in the CREATE SERVICE or EXECUTE JOB SERVICE command to provide a default warehouse. If your application code doesn’t provide a warehouse as part of connection configuration, Snowflake uses the default warehouse. Use the ALTER SERVICE command to change the default warehouse.
Nota
O warehouse especificado usando o parâmetro QUERY_WAREHOUSE é o padrão somente para o usuário do serviço. Quando o serviço se conecta ao Snowflake em nome de outro usuário, no contexto do cenário de direitos do autor da chamada, o Snowflake usa o warehouse padrão do usuário.
If you specify a warehouse by using both methods, the warehouse that is specified in the application code is used.
Access service user query history¶
You can find queries executed by your service as the service user by filtering the Exibição QUERY_HISTORY or QUERY_HISTORY function where user_type is SNOWFLAKE_SERVICE.
Exemplo 1: Busca de consultas executadas por um serviço.
SELECT *
FROM snowflake.account_usage.query_history
WHERE user_type = 'SNOWFLAKE_SERVICE'
AND user_name = '<service_name>'
AND user_database_name = '<service_db_name>'
AND user_schema_name = '<service_schema_name>'
order by start_time;
Na cláusula WHERE:
user_name = '<service_name>': você especifica o nome do serviço como o nome do usuário porque um serviço executa consultas como o usuário do serviço, e o nome do usuário do serviço é o mesmo que o nome do serviço.user_type = 'SNOWFLAKE_SERVICE'euser_name = '<service_name>': isso limita o resultado da consulta para recuperar apenas as consultas executadas por um serviço.user_database_nameeuser_schema_name: para um usuário do serviço, esses são o banco de dados e o esquema do serviço.
Você pode obter os mesmos resultados chamando a função QUERY_HISTORY.
SELECT *
FROM TABLE(<service_db_name>.information_schema.query_history())
WHERE user_database_name = '<service_db_name>'
AND user_schema_name = '<service_schema_name>'
AND user_type = 'SNOWFLAKE_SERVICE'
AND user_name = '<service_name>'
order by start_time;
Na cláusula WHERE:
user_type = 'SNOWFLAKE_SERVICE'euser_name = '<service_name>'limitam o resultado da consulta para recuperar apenas as consultas executadas por um serviço.Os nomes
user_database_nameeuser_schema_name(para um usuário de serviço) são o banco de dados e o esquema do serviço.
Exemplo 2: buscar consultas executadas por serviços e as informações de serviço correspondentes.
SELECT query_history.*, services.*
FROM snowflake.account_usage.query_history
JOIN snowflake.account_usage.services
ON query_history.user_name = services.service_name
AND query_history.user_schema_id = services.service_schema_id
AND query_history.user_type = 'SNOWFLAKE_SERVICE'
A consulta une as exibições QUERY_HISTORY e SERVICES para recuperar informações sobre as consultas e os serviços que executaram as consultas. Observe o seguinte:
Para consultas executadas por serviços,
query_history.user_nameé o nome do usuário do serviço, que é o mesmo que o nome do serviço.A consulta une as exibições usando os IDs de esquema (não o nome do esquema) para garantir que você se refira ao mesmo esquema, porque se você remover e recriar um esquema, o ID do esquema será alterado, mas o nome permanecerá o mesmo.
Você pode adicionar filtros opcionais à consulta. Por exemplo:
Filtre
query_historypara recuperar apenas serviços que executaram consultas específicas.Filtre
servicespara recuperar apenas consultas executadas por serviços específicos.
Exemplo 3: Para cada serviço, busque informações do usuário do serviço.
SELECT services.*, users.*
FROM snowflake.account_usage.users
JOIN snowflake.account_usage.services
ON users.name = services.service_name
AND users.schema_id = services.service_schema_id
AND users.type = 'SNOWFLAKE_SERVICE'
A consulta une as exibições SERVICES e USERS no esquema ACCOUNT_USAGE para recuperar serviços e informações do usuário do serviço. Observe o seguinte:
Quando um serviço executa consultas, ele as executa como usuário do serviço e o nome do usuário do serviço é o mesmo que o nome do serviço. Portanto, você especifica a condição de junção:
users.name = services.service_name.Os nomes de serviço são exclusivos apenas dentro de um esquema. Portanto, a consulta especifica a condição de junção (
users.schema_id = services.service_schema_id) para garantir que cada usuário do serviço seja correspondido ao serviço específico ao qual pertence (e não a qualquer outro serviço com o mesmo nome em execução em esquemas diferentes).
Configuração do ingresso na rede¶
Para permitir que qualquer coisa interaja com seu serviço pela internet, você declara as portas de rede nas quais seu serviço está escutando como pontos de extremidade no arquivo de especificação de serviço. Esses pontos de extremidade controlam a entrada.
Por padrão, os pontos de extremidade de serviço são privados. Somente funções de serviço e comunicações serviço a serviço podem fazer solicitações aos pontos de extremidade privados. Você pode declarar um ponto de extremidade como público para permitir solicitações a um ponto de extremidade da internet. A criação de um ponto de extremidade público é uma operação privilegiada, e a função de proprietário do serviço deve ter o privilégio BIND SERVICE ENDPOINT na conta.
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>
...
Para obter um exemplo, consulte Tutorial 1.
Tempo limite da conexão de entrada¶
Os pontos de extremidade de entrada têm um tempo limite de 90 segundos. Se não houver atividade em uma conexão com um ponto de extremidade de entrada por 90 segundos, o Snowflake encerrará a conexão. Caso seu aplicativo precise de uma conexão por mais tempo, use a sondagem ou o WebSockets.
Logout de autenticação do navegador Web de entrada¶
Se estiver criando um aplicativo Web executado como um serviço, você tem a opção de permitir que os usuários façam logout do aplicativo, direcionando-os para /sfc-endpoint/logout.
Depois de fazer o logout, o usuário precisará se autenticar novamente no Snowflake para acessar o ponto de extremidade público do serviço.
Entrada e segurança de aplicativos da web¶
Você pode criar um serviço Snowpark Container Services para hospedagem na web usando o suporte do ponto de extremidade público (entrada de rede). Para maior segurança, Snowflake emprega um serviço de proxy para monitorar solicitações recebidas de clientes para o seu serviço e respostas de saída do seu serviço para os clientes. Esta seção explica o que o proxy faz e como ele afeta um serviço implantado no Snowpark Container Services.
Nota
Ao testar um serviço localmente, você não está usando o proxy Snowflake e, portanto, haverá diferenças entre sua experiência ao executar um serviço localmente e quando implantado no Snowpark Container Services. Revise esta seção e atualize sua configuração local para melhores testes.
Por exemplo:
O proxy não encaminha uma solicitação HTTP recebida se a solicitação usar um método HTTP banido.
O proxy envia uma resposta 403 ao cliente se o cabeçalho Content-Type na resposta indicar que a resposta contém um executável.
Além disso, o proxy também pode injetar novos cabeçalhos e alterar os cabeçalhos existentes na solicitação e na resposta, tendo em mente o seu contêiner e a segurança de dados.
Por exemplo, ao receber uma solicitação, seu serviço pode enviar HTML, JavaScript, CSS e outros conteúdos de uma página da Web para o navegador do cliente na resposta. A página da web no navegador faz parte do seu serviço, atuando como interface do usuário. Por motivos de segurança, se o seu serviço tiver restrições (como uma restrição ao estabelecimento de conexões de rede com outros sites), você também poderá querer que a página da Web do seu serviço tenha as mesmas restrições.
Por padrão, os serviços têm permissões limitadas para acessar a Internet. O navegador também deve restringir o acesso do aplicativo cliente à Internet e o possível compartilhamento de dados na maioria dos casos. Se você configurar uma integração de acesso externo (EAI) para permitir que seu serviço acesse example.com (consulte Configuração da saída da rede), a página da Web do seu serviço também deverá poder acessar example.com por meio de seu navegador.
O proxy Snowflake aplica as mesmas restrições de rede ao serviço e à página da web adicionando um cabeçalho Content-Security-Policy (CSP) na resposta. Por padrão, o proxy adiciona uma linha de base CSP na resposta para proteção contra ameaças de segurança comuns. A segurança do navegador é um esforço máximo para equilibrar funcionalidade e segurança. É uma responsabilidade compartilhada para garantir que essa linha de base seja apropriada para seu caso de uso. Além disso, se o seu serviço estiver configurado para usar um EAI, o proxy aplicará as mesmas regras de rede de EAI a CSP para a página da web. Este CSP permite que a página da web no navegador acesse os mesmos sites que o serviço pode acessar.
O Snowflake oferece o suporte CORS que você configura na especificação do serviço.
O proxy do Snowflake retorna as configurações do CORS definidas na especificação do serviço. Observe que o proxy remove todos os cabeçalhos do CORS retornados pelo serviço.
Os seguintes cabeçalhos do CORS são definidos por padrão:
O cabeçalho
Access-Control-Expose-Headerssempre informa os seguintes nomes de cabeçalho, além dos cabeçalhos configurados na especificação de serviço para o ponto de extremidade.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é definido para duas horas.Access-Control-Allow-Credentialsé definido como verdadeiro.
Além disso, o Snowflake define o cabeçalho Vary com o valor Origin para indicar ao navegador que, com base no valor de Origin, o valor de Access-Control-Allow-Origin pode ser diferente.
O cabeçalho Authorization é necessário para fazer a solicitação CORS. Você pode especificar um token de acesso programático (PAT) neste cabeçalho (Authorization: "Snowflake Token=\"${patToken}\""). Para obter informações sobre como gerar um token de acesso programático, consulte Uso de tokens de acesso programático para autenticação.
As seções a seguir explicam como o proxy Snowflake lida com solicitações de entrada para o seu serviço e modifica as respostas de saída do seu serviço para os clientes.
Solicitações recebidas no serviço¶
Quando chega uma solicitação, o proxy faz o seguinte antes de encaminhar a solicitação ao serviço:
Solicitações recebidas com métodos HTTP banidos: se uma solicitação HTTP recebida usar qualquer um dos métodos HTTP banidos a seguir, o proxy não encaminhará a solicitação para seu serviço:
TRACECONNECT
Limpeza do cabeçalho das solicitações de entrada: o proxy Snowflake remove os seguintes cabeçalhos de solicitação, se presentes:
X-SF-SPCS-AuthorizationAuthorization: removido somente se contiver um token Snowflake; caso contrário, será passado ao seu serviço.
Respostas enviadas aos clientes¶
O proxy Snowflake aplica essas modificações à resposta enviada pelo seu serviço antes de encaminhar a resposta ao cliente.
Limpeza de cabeçalho: o proxy Snowflake remove esses cabeçalhos de resposta, se presentes:
X-XSS-ProtectionServerX-Powered-ByPublic-Key-Pins
Manipulação de cabeçalhos do CORS: consulte Considerações sobre ingresso e CORS.
Cabeçalho de resposta Content-Type: se sua resposta de serviço incluir o cabeçalho Content-Type com qualquer um dos seguintes valores de tipo MIME (que indicam um executável), o proxy Snowflake não encaminhará essa resposta ao cliente. Em vez disso, o proxy enviará uma resposta
403 Forbidden.application/x-msdownload: executável da Microsoft.application/exe: executável genérico.application/x-exe: outro executável genérico.application/dos-exe: DOS executável.application/x-winexe: executável do Windows.application/msdos-windows: MS-DOS executável do Windows.application/x-msdos-program: MS-DOS executável.application/x-sh: script de shell Unix.application/x-bsh: script de shell Bourne.application/x-csh: script de shell C.application/x-tcsh: script de shell Tcsh.application/batch: arquivo em lote do Windows.
Cabeçalho de resposta X-Frame-Options: para evitar ataques de clickjacking, o proxy Snowflake define esse cabeçalho de resposta como
DENY, evitando que outras páginas da Web usem um iframe para a página da Web do seu serviço.Cabeçalho de resposta Cross-Origin-Opener-Policy (COOP): Snowflake define o cabeçalho de resposta COOP como
same-originpara impedir que janelas de origem cruzada de referência acessem sua guia de serviço.Cabeçalho de resposta Cross-Origin-Resource-Policy (CORP): Snowflake define o cabeçalho CORP como
same-originpara evitar que sites externos carreguem recursos expostos pelo ponto de extremidade de entrada (por exemplo, em um iframe).Cabeçalho de resposta X-Content-Type-Options: o proxy Snowflake define esse cabeçalho como
nosniffpara garantir que os clientes não alterem o tipo MIME indicado na resposta pelo seu serviço.Cabeçalho de resposta Cross-Origin-Embedder-Policy (COEP): o proxy Snowflake define o cabeçalho de resposta COEP como
credentialless, o que significa que ao carregar um objeto de origem cruzada, como uma imagem ou um script, se o objeto remoto não suportar o protocolo Cross-Origin Resource Sharing (CORS), o Snowflake não enviará as credenciais ao carregá-lo.Cabeçalho de resposta Content-Security-Policy-Report-Only: o proxy Snowflake substitui esse cabeçalho de resposta por um novo valor direcionando o cliente para enviar os relatórios CSP ao Snowflake.
Cabeçalho de resposta Content-Security-Policy (CSP): por padrão, o proxy Snowflake adiciona a seguinte linha de base CSP para proteção contra ataques comuns da Web.
default-src 'self' 'unsafe-inline' 'unsafe-eval' blob: data:; object-src 'none'; connect-src 'self'; frame-ancestors 'self';
Há duas considerações sobre política de segurança de conteúdo:
Além da política de segurança de conteúdo de linha de base que o proxy adiciona, o próprio serviço pode adicionar explicitamente um CSP na resposta. Um serviço pode optar por aumentar a segurança adicionando um CSP mais rigoroso. Por exemplo, um serviço pode adicionar o seguinte CSP para permitir scripts somente de
self.script-src 'self'
Na resposta resultante enviada ao cliente, haverá dois cabeçalhos CSP. Ao receber a resposta, os navegadores do cliente aplicam a política de segurança de conteúdo mais rigorosa que inclui as restrições adicionais especificadas por cada política.
Se você configurar uma integração de acesso externo (EAI) para permitir que seu serviço acesse um site externo (Configuração da saída da rede), o proxy Snowflake criará um CSP que permite que sua página da web acesse esse site. Por exemplo, suponha que uma regra de rede associada a EAI permita acesso de saída de serviço a
example.com. Em seguida, o proxy Snowflake adiciona este cabeçalho de resposta 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';
Os navegadores respeitam a política de acesso ao conteúdo recebida na resposta. Neste exemplo, os navegadores permitem que o aplicativo acesse
example.com, mas não outros sites.
Considerações sobre ingresso e CORS¶
Por padrão, os navegadores impedem que os aplicativos Web hospedados em um servidor enviem solicitações a outro servidor com um nome de host diferente. Por exemplo, se você hospedar um aplicativo Web fora do Snowpark Container Services que precise interagir com um serviço de backend implantado no Snowpark Container Services, essa restrição se aplica.
O CORS (Cross-Origin Resource Sharing ou Compartilhamento de recursos entre origens) permite que um serviço do Snowpark Container Services comunique aos navegadores que é permitido fazer solicitações de aplicativos Web hospedados fora do seu ambiente. Você pode configurar cada ponto de extremidade público para especificar como ele responde às solicitações de preflight do CORS e às solicitações padrão.
O proxy do Snowflake sempre substitui os seguintes cabeçalhos de resposta:
Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Allow-HeadersAccess-Control-Expose-HeadersAccess-Control-Max-AgeAccess-Control-Allow-Credentials
O proxy do Snowflake não inclui nenhum desses cabeçalhos do CORS na resposta quando um dos seguintes itens for verdadeiro:
O CORS não está configurado para o ponto de extremidade do serviço. Ou seja, não há
corsSettingsna especificação do serviçoO CORS está configurado para o ponto de extremidade do serviço, mas o cabeçalho
Originna solicitação não corresponde ao campoAccess-Control-Allow-Originespecificado na especificação do serviço
Na especificação do serviço, você pode definir as configurações do CORS para cada ponto de extremidade público. Quando o cabeçalho origin na solicitação corresponde ao campo Access-Control-Allow-Origin especificado para o ponto de extremidade na especificação, o proxy inclui na resposta os cabeçalhos do CORS definidos na especificação, com os seguintes ajustes:
Access-Control-Allow-Origin: retorna o cabeçalhoOriginda solicitação.Access-Control-Expose-Headers: mescla a lista de cabeçalhos permitidos que você configurou com esses cabeçalhos sempre expostos: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: é definido para duas horas.Access-Control-Allow-Credentials: é definido como verdadeiro.
Considerações sobre ingresso e SSO¶
Ao acessar o ponto de extremidade público pela Internet, você pode descobrir que a autenticação por nome de usuário/senha funciona, mas SSO resulta em uma página em branco ou no erro: «A integração do clienteOAuth com o ID do cliente fornecido não foi encontrada.»
Isso acontece quando você está usando o estilo antigo de autenticação federada (SSO) com o Snowflake em vez da versão mais recente de integração de segurança, conforme explicado em Configuração do Snowflake para usar a autenticação federada. Faça o seguinte para verificar:
Execute a seguinte consulta:
SHOW PARAMETERS LIKE 'SAML_IDENTITY_PROVIDER' IN ACCOUNT;
Se esse parâmetro estiver definido, então, em algum momento, você estava usando a autenticação federada antiga.
Se o parâmetro anterior foi definido, execute a seguinte consulta para verificar se você tem uma integração de segurança SAML:
SHOW INTEGRATIONS ->> SELECT * FROM $1 WHERE "type" = 'SAML2';
Se você não tiver nenhuma integração do tipo SAML2, então está usando a versão antiga de autenticação federada.
Nesse caso, a solução é migrar da autenticação federada antiga para a nova autenticação federada da integração. Para obter mais informações, consulte Migração para uma integração de segurança SAML2.
Configuração da saída da rede¶
O código do seu aplicativo pode exigir acesso à internet. Por padrão, os contêineres de aplicativos não têm permissão para acessar a internet. Você precisa ativar o acesso à internet usando integrações de acesso externo (EAIs).
Normalmente, você deseja que um administrador de conta crie EAIs para gerenciar o acesso externo permitido de serviços (incluindo serviços de trabalho). Os administradores da conta podem então conceder o uso de EAI a funções específicas que os desenvolvedores usam para executar serviços.
O exemplo a seguir descreve as etapas para criar uma EAI que permite o tráfego de saída para destinos específicos determinados usando regras de rede. Em seguida, consulte a EAI ao criar um serviço para permitir solicitações para destinos específicos da internet.
Exemplo
Suponha que você queira que o código do seu aplicativo envie solicitações para os seguintes destinos:
Solicitações de HTTPS para translation.googleapis.com
Solicitações de HTTP e HTTPS para google.com
Siga estas etapas para permitir que seu serviço acesse esses domínios na Internet:
Criação de uma integração de acesso externo (EAI). Isso requer permissões apropriadas. Por exemplo, você pode usar a função ACCOUNTADMIN para criar uma EAI. Este é um processo de duas etapas:
Use o comando CREATE NETWORK RULE para criar uma ou mais regras de rede de saída listando destinos externos aos quais você deseja permitir acesso. Você pode realizar este exemplo com uma regra de rede, mas para ilustração, criamos duas regras de rede:
Crie uma regra de rede chamada
translate_network_rule:CREATE OR REPLACE NETWORK RULE translate_network_rule MODE = EGRESS TYPE = HOST_PORT VALUE_LIST = ('translation.googleapis.com');
Esta regra permite conexões TCP com o destino
translation.googleapis.com. O domínio na propriedade VALUE_LIST não especifica o número da porta opcional, portanto a porta padrão 443 (HTTPS) é assumida. Isso permite que seu aplicativo se conecte a qualquer URL que comece comhttps://translation.googleapis.com/.Crie uma regra de rede chamada
google_network_rule:CREATE OR REPLACE NETWORK RULE google_network_rule MODE = EGRESS TYPE = HOST_PORT VALUE_LIST = ('google.com:80', 'google.com:443');
Isso permite que seu aplicativo se conecte a qualquer URL que comece com
http://google.com/ouhttps://google.com/.
Nota
Para o parâmetro
VALUE_LIST, você deve fornecer um nome de host completo. Curingas (por exemplo,*.googleapis.com) não são suportados.O Snowpark Container Services oferece suporte apenas às regras de rede que permitem as portas 22, 80, 443, e 1024+. Se uma regra de rede referenciada permitir acesso a outras portas, a criação do serviço falhará. Entre em contato com seu representante de conta se precisar do uso de portas adicionais.
Nota
Para permitir que seu serviço envie solicitações HTTP ou HTTPS para qualquer destino na internet, especifique «0.0.0.0» como o domínio na propriedade VALUE_LIST. A regra de rede a seguir permite enviar solicitações «HTTP» e «HTTPS» para qualquer lugar na Internet. Somente as portas 80 ou 443 são suportadas com «0.0.0.0».
CREATE NETWORK RULE allow_all_rule TYPE = 'HOST_PORT' MODE= 'EGRESS' VALUE_LIST = ('0.0.0.0:443','0.0.0.0:80');
Crie uma integração de acesso externo (EAI) que especifique que as duas regras de rede de saída anteriores são permitidas:
CREATE EXTERNAL ACCESS INTEGRATION google_apis_access_integration ALLOWED_NETWORK_RULES = (translate_network_rule, google_network_rule) ENABLED = true;
Agora o administrador da conta pode conceder o uso da integração aos desenvolvedores para permitir que executem um serviço que pode acessar destinos específicos na Internet.
GRANT USAGE ON INTEGRATION google_apis_access_integration TO ROLE test_role;
Crie o serviço fornecendo EAI conforme mostrado nos exemplos a seguir. A função do proprietário que está criando o serviço precisa do privilégio USAGE no privilégio EAI e READ bre os segredos referenciados. Observe que você não pode usar a função ACCOUNTADMIN para criar um serviço.
Crie um serviço:
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 $$;
Este exemplo de solicitação CREATE SERVICE usa uma especificação de serviço sequencial e especifica a propriedade opcional EXTERNAL_ACCESS_INTEGRATIONS para incluir a EAI. A EAI especifica as regras de rede que permitem o tráfego de saída do serviço para destinos específicos.
Execute um serviço de trabalho:
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/" $$;
Este exemplo de comando EXECUTE JOB SERVICE especifica a especificação embutida e a propriedade opcional EXTERNAL_ACCESS_INTEGRATIONS para incluir a EAI. Isso permite o tráfego de saída do trabalho para destinos especificados nas regras de rede permitidas por EAI.
Saída da rede usando conectividade privada¶
Em vez de rotear a saída da rede pela Internet pública, você pode optar por direcionar o tráfego de saída do seu serviço por meio de um ponto de extremidade de conectividade privada.
Primeiro, você precisa criar o ponto de extremidade de conectividade privada em sua conta do Snowflake. Em seguida, configure uma regra de rede para permitir que o tráfego de saída use a conectividade privada. O processo de configuração de uma integração de acesso externo (EAI) permanece o mesmo descrito na seção anterior.
Nota
A comunicação privada exige que tanto o Snowflake quanto a conta de nuvem do cliente usem o mesmo provedor de nuvem e a mesma região.
Por exemplo, se você quiser habilitar o acesso de saída da Internet do seu serviço a um bucket S3 Amazon por meio de conectividade privada, faça o seguinte:
Habilite a conectividade do link privado para o serviço de ponto de extremidade autônomo (Amazon S3). Para obter instruções passo a passo, consulte AWS Private Link para Amazon S3.
Chame a função do sistema SYSTEM$PROVISION_PRIVATELINK_ENDPOINT para provisionar um ponto de extremidade de conectividade privada em seu Snowflake VNet. Isso permite que o Snowflake se conecte ao serviço externo (neste exemplo, o Amazon S3) usando conectividade privada.
USE ROLE ACCOUNTADMIN; SELECT SYSTEM$PROVISION_PRIVATELINK_ENDPOINT( 'com.amazonaws.us-west-2.s3', '*.s3.us-west-2.amazonaws.com' );
Na conta do provedor de nuvem, aprove o ponto de extremidade. Neste exemplo, para a Amazon AWS, consulte Como aceitar ou rejeitar solicitações de conexão na documentação do AWS. Além disso, para aprovar o ponto de extremidade no Azure, consulte a documentação do Azure.
Use o comando CREATE NETWORK RULE para criar uma regra de rede de saída que especifique os destinos externos aos quais você deseja permitir o acesso.
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');
O valor do parâmetro TYPE é definido como PRIVATE_HOST_PORT. Isso indica que a regra de rede permite que o tráfego de rede de saída use a conectividade privada.
As demais etapas para criar uma EAI e usá-la para criar um serviço são as mesmas explicadas na seção anterior (consulte Configuração da saída da rede).
Para obter mais informações sobre como trabalhar com pontos de extremidade de conectividade privada, consulte o seguinte:
Configuração de comunicações de rede entre contêineres¶
Há duas considerações:
Comunicações entre contêineres de uma instância de serviço: se uma instância de serviço executar vários contêineres, esses contêineres poderão se comunicar entre si por meio do host local (não há necessidade de definir pontos de extremidade na especificação de serviço).
Comunicação entre contêineres em vários serviços ou múltiplas instâncias de serviço: contêineres pertencentes a diferentes serviços (ou diferentes instâncias do mesmo serviço) podem se comunicar usando pontos de extremidade definidos em arquivos de especificação. Para obter mais informações, consulte Comunicações serviço a serviço.
Como passar credenciais para um contêiner usando segredos do Snowflake¶
Há muitos motivos pelos quais você pode querer passar credenciais Snowflake gerenciadas para seu contêiner. Por exemplo, seu serviço pode se comunicar com pontos de extremidade externos (fora do Snowflake), caso em que será necessário fornecer informações de credenciais em seu contêiner para que o código do aplicativo as utilize.
Para fornecer as credenciais, primeiro armazene-as em objetos secretos Snowflake. Em seguida, na especificação do serviço, use containers.secrets para definir quais objetos secretos usar e onde colocá-los dentro do contêiner. É possível passar essas credenciais para variáveis de ambiente nos contêineres ou disponibilizá-las em arquivos locais nos contêineres.
Especificando segredos Snowflake¶
Especifique um segredo Snowflake por nome ou referência (a referência é aplicável somente no cenário com Native Applications):
Passe o segredo Snowflake por nome: É possível passar um nome secreto como valor do campo
snowflakeSecret.... secrets: - snowflakeSecret: objectName: '<secret-name>' <other info about where in the container to copy the secret> ...
Observe que você pode opcionalmente especificar
<secret-name>diretamente como o valorsnowflakeSecret.Passe o segredo Snowflake por referência: Ao usar o Snowpark Container Services para criar um Native App (um aplicativo com contêineres), o produtor e os consumidores do aplicativo usam contas Snowflake diferentes. Em alguns contextos, um Snowflake Native App instalado precisa acessar objetos secretos existentes na conta do consumidor que existem fora do objeto APPLICATION. Nesse caso, os desenvolvedores podem usar a sintaxe da especificação “segredos por referência” para manipular credenciais, conforme mostrado:
containers: - name: main image: <url> secrets: - snowflakeSecret: objectReference: '<reference-name>' <other info about where in the container to copy the secret>
Observe que a especificação usa
objectReferenceem vez deobjectNamepara fornecer um nome de referência de segredo.
Especificação do posicionamento dos segredos dentro do contêiner¶
É possível dizer ao Snowflake para colocar os segredos nos contêineres como variáveis de ambiente ou gravá-los em arquivos de contêiner locais.
Como passar os segredos como variáveis de ambiente¶
Para passar segredos Snowflake para contêineres como variáveis de ambiente, inclua envVarName no campo containers.secrets.
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: <secret-name>
secretKeyRef: username | password | secret_string | 'access_token'
envVarName: '<env-variable-name>'
O valor secretKeyRef depende do tipo de segredo Snowflake. Os valores possíveis são os seguintes:
usernameoupasswordse o segredo do Snowflake for do tipopassword.secret_stringse o segredo do Snowflake for do tipogeneric_string.
Observe que o Snowflake não atualiza segredos passados como variáveis de ambiente após a criação de um serviço.
Exemplo 1: como passar segredos do tipo senha como variáveis de ambiente¶
Neste exemplo, você cria o seguinte objeto de segredo do Snowflake do tipo password:
CREATE SECRET testdb.testschema.my_secret_object
TYPE = password
USERNAME = 'snowman'
PASSWORD = '1234abc';
Para fornecer esse objeto de segredo do Snowflake às variáveis de ambiente (por exemplo, LOGIN_USER e LOGIN_PASSWORD) em seu contêiner, adicione o seguinte campo containers.secrets no arquivo de especificação:
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: testdb.testschema.my_secret_object
secretKeyRef: username
envVarName: LOGIN_USER
- snowflakeSecret: testdb.testschema.my_secret_object
secretKeyRef: password
envVarName: LOGIN_PASSWORD
Neste exemplo, o valor snowflakeSecret é um nome de objeto totalmente qualificado porque os segredos podem ser armazenados em um esquema diferente do serviço que está sendo criado.
O campo containers.secrets neste exemplo é uma lista de dois objetos snowflakeSecret:
O primeiro objeto mapeia
usernameno objeto do segredo do Snowflake para a variável de ambienteLOGIN_USERem seu contêiner.O segundo objeto mapeia
passwordno objeto do segredo do Snowflake para a variável de ambienteLOGIN_PASSWORDem seu contêiner.
Exemplo 2: como passar segredos do tipo cadeia_de_caracteres_genérica como variáveis de ambiente¶
Neste exemplo, você cria o seguinte objeto de segredo do Snowflake do tipo generic_string:
CREATE SECRET testdb.testschema.my_secret
TYPE=generic_string
SECRET_STRING='
some_magic: config
';
Para fornecer esse objeto do segredo do Snowflake para variáveis de ambiente (por exemplo, GENERIC_SECRET) em seu contêiner, adicione o seguinte campo containers.secrets no arquivo de especificação:
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: testdb.testschema.my_secret
secretKeyRef: secret_string
envVarName: GENERIC_SECRET
Gravação de segredos em arquivos de contêiner locais¶
Para disponibilizar segredos Snowflake para o contêiner do aplicativo em arquivos de contêiner locais, inclua um campo containers.secrets: Para disponibilizar os segredos Snowflake para o contêiner do aplicativo em arquivos de contêiner locais, inclua directoryPath em containers.secrets:
containers:
- name: <name>
image: <url>
...
secrets:
- snowflakeSecret: <snowflake-secret-name>
directoryPath: '<local directory path in the container>'
O Snowflake preenche os arquivos necessários para o segredo neste directoryPath especificado; não é necessário especificar secretKeyRef. Dependendo do tipo de segredo, o Snowflake cria os seguintes arquivos no contêiner no caminho de diretório fornecido:
usernameepassword, se o segredo Snowflake for do tipopassword.secret_stringse o segredo do Snowflake for do tipogeneric_string.access_tokense o segredo do Snowflake for do tipooauth2.
Nota
Após a criação de um serviço, se o objeto do segredo do Snowflake for atualizado, o Snowflake atualizará os arquivos do segredo correspondentes nos contêineres em execução.
Exemplo 1: como passar segredos do tipo senha em arquivos de contêiner locais¶
Neste exemplo, você cria o seguinte objeto de segredo do Snowflake do tipo password:
CREATE SECRET testdb.testschema.my_secret_object
TYPE = password
USERNAME = 'snowman'
PASSWORD = '1234abc';
Para disponibilizar essas credenciais em arquivos de contêiner locais, adicione o seguinte campo containers.secrets no arquivo de especificação:
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: testdb.testschema.my_secret_object
directoryPath: '/usr/local/creds'
Quando você inicia o serviço, o Snowflake cria dois arquivos dentro do contêiner: /usr/local/creds/username e /usr/local/creds/password. O código do seu aplicativo pode então ler esses arquivos.
Exemplo 2: Como passar segredos do tipo generic_string em arquivos de contêiner locais¶
Neste exemplo, você cria o seguinte objeto de segredo do Snowflake do tipo generic_string:
CREATE SECRET testdb.testschema.my_secret
TYPE=generic_string
SECRET_STRING='
some_magic: config
';
Para fornecer este objeto secreto Snowflake em arquivos de contêiner locais, adicione o seguinte campo containers.secrets no arquivo de especificação:
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: testdb.testschema.my_secret
directoryPath: '/usr/local/creds'
Quando você inicia o serviço, o Snowflake cria este arquivo dentro dos contêineres: /usr/local/creds/secret_string.
Exemplo 3: Como passar segredos do tipo oauth2 em arquivos de contêiner locais¶
Neste exemplo, você cria o seguinte objeto de segredo do Snowflake do tipo oauth2:
CREATE SECRET testdb.testschema.oauth_secret
TYPE = OAUTH2
OAUTH_REFRESH_TOKEN = '34n;vods4nQsdg09wee4qnfvadH'
OAUTH_REFRESH_TOKEN_EXPIRY_TIME = '2023-12-31 20:00:00'
API_AUTHENTICATION = my_integration;
Para disponibilizar essas credenciais em arquivos de contêiner locais, adicione o seguinte campo containers.secrets no arquivo de especificação:
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: testdb.testschema.oauth_secret
directoryPath: '/usr/local/creds'
Snowflake busca o token de acesso do objeto do segredo do OAuth e cria /usr/local/creds/access_token nos contêineres.
Quando um serviço usa segredos do tipo oauth2, espera-se que o serviço use esse segredo para acessar um destino da internet. Um segredo oauth deve ser permitido pela integração de acesso externo (EAI); caso contrário, CREATE SERVICE ou EXECUTE JOB SERVICE falharão. Este requisito de EAI extra se aplica apenas a segredos do tipo oauth2 e não a outros tipos de segredos.
Em resumo, as etapas típicas na criação de tal serviço são:
Crie um segredo do tipo oauth2 (mostrado anteriormente).
Crie uma EAI para permitir o uso do segredo por um serviço. Por exemplo:
CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION example_eai ALLOWED_NETWORK_RULES = (<name>) ALLOWED_AUTHENTICATION_SECRETS = (testdb.testschema.oauth_secret) ENABLED = true;
Crie um serviço que inclua um campo
containers.secretsna especificação. Isso também especifica a propriedade opcional EXTERNAL_ACCESS_INTEGRATIONS para incluir uma EAI para permitir o uso do segredo oauth2.Um exemplo de comando CREATE SERVICE (com especificação inline):
CREATE SERVICE eai_service IN COMPUTE POOL MYPOOL EXTERNAL_ACCESS_INTEGRATIONS = (example_eai) FROM SPECIFICATION $$ spec: containers: - name: main image: <url> secrets: - snowflakeSecret: testdb.testschema.oauth_secret directoryPath: '/usr/local/creds' endpoints: - name: api port: 8080 $$;
Para obter mais informações sobre saída, consulte Configuração da saída da rede.
Diretrizes e limitações¶
Limitações gerais: Se você encontrar algum problema com essas limitações, entre em contato com seu representante de conta.
É possível criar até 200 serviços em sua conta Snowflake.
Cada serviço pode ter até 100 pontos de extremidade (consulte spec.endpoints).
Cada serviço pode ter até 20 contêineres (consulte spec.containers).
Cada serviço pode ter até 50 segredos (consulte containers.secrets).
Cada serviço pode ter até 20 volumes (consulte spec.volumes).
As seguintes limitações se aplicam quando você habilita o acesso à Internet (consulte Configuração da saída da rede) usando integrações de acesso externo (EAIs).
Cada serviço pode oferecer suporte para até 10 EAIs (consulte CREATE SERVICE e ALTER SERVICE).
Cada EAI pode ter até 100 nomes de host.
Ao acessar o ponto de extremidade público pela Internet, você pode descobrir que a autenticação por nome de usuário/senha funciona, mas SSO resulta em uma página em branco ou no erro: «A integração do clienteOAuth com o ID do cliente fornecido não foi encontrada.» Para obter informações sobre como resolver esse problema, consulte Considerações sobre ingresso e SSO.
Requisitos de plataforma de imagem: atualmente, o Snowpark Container Services requer imagens de plataforma linux/amd64.
Contêineres de serviço não são privilegiados: os contêineres de serviço não são executados como privilegiados e, portanto, não podem alterar a configuração do hardware no host e podem alterar apenas configurações de OS limitadas. Os contêineres de serviço só podem executar configurações do sistema operacional que um usuário normal (ou seja, um usuário que não requer root) pode fazer.
Como renomear o banco de dados e o esquema:
Não renomeie bancos de dados e esquemas onde você já criou um serviço. Renomear é efetivamente mover um serviço para outro banco de dados e esquema, que não é compatível. Por exemplo:
As informações de banco de dados e esquema que o Snowflake forneceu aos contêineres de serviço em execução continuarão a se referir aos nomes antigos.
Os novos logs que os serviços ingerem na tabela de eventos continuarão a fazer referência ao banco de dados antigo e aos nomes de esquema.
A função de serviço continuará a fazer referência ao serviço no banco de dados e esquema antigos e, quando você invocar a função de serviço, ela falhará.
Uma especificação de serviço pode fazer referência a objetos como estágios Snowflake e repositórios de imagens. Se você renomear os nomes do banco de dados ou do esquema onde esses objetos residem, será necessário atualizar manualmente os nomes do banco de dados e do esquema dos objetos referenciados na especificação de serviço.
Ownership transferof the parent schema or database:
You can transfer the ownership of the parent schema or database to a different role. But the ownership of services inside the schema or database isn’t transferred to the new role because services run as service’s owner roles and that doesn’t change. As a result, the services could lose permissions on objects inside the schema, such as image repositories and Snowflake stages in the same schema.
If you must transfer the ownership of the parent schema or database, consider re-creating the services.
Descarte e cancelamento de um banco de dados e esquema:
Quando você descarta o banco de dados ou esquema pai, os serviços são excluídos de forma assíncrona. Isso significa que um serviço pode continuar em execução por algum tempo antes que os processos internos o removam.
Se você tentar cancelar um banco de dados ou esquema excluído anteriormente, não há garantia de que os serviços serão restaurados.
Ownership transfer of services: Ownership transfer or future ownership transfer for services, including job services, isn’t supported.
Transferência de propriedade das funções de serviço:
a propriedade de uma função de serviço pode ser transferida para uma função diferente. Se a nova função de proprietário não tiver o privilégio USAGE no serviço, as invocações de função falharão. Você precisa conceder o privilégio USAGE à nova função de proprietário da função.
Replicação: ao lidar com replicação no Snowflake, observe o seguinte:
Os objetos do Snowpark Container Services, como serviços, pools de computação e repositórios, não podem ser replicados.
Se você criar um repositório em um banco de dados, o banco de dados inteiro não poderá ser replicado. Nos casos em que o banco de dados contém outros recursos, como serviços ou pools de computação, o processo de replicação do banco de dados será bem-sucedido, mas esses objetos individuais no banco de dados não serão replicados.
Job services timeout: Snowpark Container Services job services runs synchronously by default. If a statement times out, the job service is canceled. The default statement timeout is two days. Customers can change the timeout by setting the parameter STATEMENT_TIMEOUT_IN_SECONDS using ALTER SESSION.
ALTER SESSION SET statement_timeout_in_seconds=<time>
Configure-o antes de executar o comando EXECUTE JOB SERVICE. É possível executar serviços de trabalho de forma assíncrona, especificando
ASYNC=true, para evitar que os serviços de trabalho sejam interrompidos pelo tempo limite de uma instrução.File staging commands support in Google Cloud: To use the PUT, GET, LIST, or REMOVE command with Snowflake client libraries on Google Cloud, update your clients to at least the following versions.
Cliente
Versão
Driver Go Snowflake
1.14.1
Conector Snowflake para Python
3.16.0
Driver .NET
4.6.0
Driver Node.js
2.1.3
Driver JDBC
3.25.1
Driver ODBC
3.10.0