Solicitação de referências e privilégios de nível de objeto de consumidores

Este tópico descreve como os provedores podem configurar um Snowflake Native App para solicitar acesso a objetos na conta do consumidor que existem fora do objeto APPLICATION.

Sobre as referências

Em alguns contextos, um Snowflake Native App instalado precisa acessar objetos existentes na conta do consumidor que existem fora do objeto APPLICATION. Por exemplo, um aplicativo pode precisar acessar tabelas existentes em um banco de dados do consumidor.

Neste contexto, não é suficiente que o consumidor conceda acesso a um objeto ao objeto APPLICATION porque o aplicativo não pode determinar o nome do esquema e do objeto na conta do consumidor.

Para permitir que o Snowflake Native App acesse objetos existentes fora do objeto APPLICATION, o Snowflake Native App Framework fornece referências que permitem ao cliente especificar o nome e o esquema de um objeto e permitir o acesso ao objeto.

Fluxo de trabalho para definição de referências na conta do consumidor

Para solicitar uma referência e privilégio de nível de objeto, o provedor executa o seguinte ao desenvolver e publicar um Snowflake Native App:

  1. Determine quais objetos exigem referências e seus privilégios correspondentes.

  2. Defina as referências no arquivo de manifesto.

  3. Adicione um procedimento armazenado no script de configuração para manipular o retorno de chamada para cada referência definida no arquivo do manifesto.

Depois de instalar o Snowflake Native App, o consumidor realiza o seguinte:

  1. Visualiza as referências exigidas pelo Snowflake Native App.

  2. Cria a referência chamando a função do sistema SYSTEM$REFERENCE.

  3. Executa o procedimento armazenado de retorno de chamada passando o id da referência.

Depois que o consumidor executa o procedimento armazenado de retorno de chamada, o Snowflake Native App pode acessar o objeto solicitado.

Este fluxo de trabalho descreve o processo em que o consumidor cria a referência manualmente. Consulte Criação de uma interface de usuário para solicitar privilégios e referências para obter informações sobre como criar uma interface de usuário para permitir que os consumidores criem referências e concedam privilégios usando o Snowsight.

Tipos de objeto e privilégios que uma referência pode conter

A tabela a seguir lista os tipos de objeto que uma referência pode incluir e os privilégios permitidos para cada objeto:

Tipo de objeto

Privilégios permitidos

TABLE

SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES

VIEW

SELECT, REFERENCES

EXTERNAL TABLE

SELECT, REFERENCES

FUNCTION

USAGE

PROCEDURE

USAGE

WAREHOUSE

MODIFY, MONITOR, USAGE, OPERATE

API INTEGRATION

USAGE

EXTERNAL ACCESS INTEGRATION

USAGE

SECRET

USAGE, READ

Definição de uma referência no arquivo de manifesto

O exemplo a seguir mostra como definir uma referência no arquivo manifest.yml para uma tabela na conta do consumidor que existe fora do objeto APPLICATION:

references:
  - consumer_table:
      label: "Consumer table"
      description: "A table in the consumer account that exists outside the APPLICATION object."
      privileges:
        - INSERT
        - SELECT
      object_type: TABLE
      multi_valued: false
      register_callback: config.register_single_reference
Copy

Este exemplo define uma referência chamada consumer_table que requer os privilégios INSERT e SELECT em uma tabela na conta do consumidor. A propriedade register_callback especifica um procedimento armazenado usado para vincular uma tabela do consumidor a esta definição de referência.

Use multi_valued para vincular vários objetos de consumidor à mesma referência. Quando essa propriedade é especificada, as mesmas operações são executadas em objetos com uma única referência de valor. A propriedade também pode ser usada com objetos com referências de vários valores. Consulte Funções de referência compatíveis para saber mais sobre operações de referência do Snowflake Native App Framework.

Remoção de uma definição de referência

Nota

Snowflake não recomenda a remoção de uma definição de referência do arquivo de manifesto em uma nova versão de um aplicativo. Se você precisar remover uma referência definida, atualize qualquer código que use a referência removida na mesma versão e notifique o consumidor no arquivo README.

Se um aplicativo definir uma referência e depois excluir a definição de referência de uma versão subsequente do aplicativo, chamar qualquer função ou procedimento que ainda use a referência excluída resultará em um erro para os consumidores. Por exemplo, o arquivo de manifesto da versão V1 do aplicativo my_app inclui uma definição de referência para REF_TO_TABLE e um procedimento armazenado CREATE_VIEW_FROM_TABLE que usa a referência de tabela REF_TO_TABLE para criar uma exibição VIEW_SELECT_FROM_DEFINED_REF.

Na versão V2 de my_app, a definição de referência para REF_TO_TABLE é removida do arquivo de manifesto. Quando um consumidor atualiza o aplicativo instalado my_app para a versão V2, chamar o procedimento CREATE_VIEW_FROM_TABLE resulta no seguinte erro:

Reference definition '<REF_DEF_NAME>' cannot be found in the current version of the application '<APP_NAME>'

Criação de um procedimento armazenado de retorno de chamada para uma referência

Depois de definir uma referência no arquivo manifest.yml, um provedor deve adicionar um procedimento armazenado no script de configuração para registrar o retorno de chamada para a referência.

O exemplo a seguir mostra um procedimento armazenado usado para manipular um retorno de chamada para a referência mostrada em Definição de uma referência no arquivo de manifesto:

CREATE APPLICATION ROLE app_admin;

CREATE OR ALTER VERSIONED SCHEMA config;
GRANT USAGE ON SCHEMA config TO APPLICATION ROLE app_admin;

CREATE PROCEDURE CONFIG.REGISTER_SINGLE_REFERENCE(ref_name STRING, operation STRING, ref_or_alias STRING)
  RETURNS STRING
  LANGUAGE SQL
  AS $$
    BEGIN
      CASE (operation)
        WHEN 'ADD' THEN
          SELECT SYSTEM$SET_REFERENCE(:ref_name, :ref_or_alias);
        WHEN 'REMOVE' THEN
          SELECT SYSTEM$REMOVE_REFERENCE(:ref_name, :ref_or_alias);
        WHEN 'CLEAR' THEN
          SELECT SYSTEM$REMOVE_ALL_REFERENCES(:ref_name);
      ELSE
        RETURN 'unknown operation: ' || operation;
      END CASE;
      RETURN NULL;
    END;
  $$;

GRANT USAGE ON PROCEDURE CONFIG.REGISTER_SINGLE_REFERENCE(STRING, STRING, STRING)
  TO APPLICATION ROLE app_admin;
Copy

Este exemplo cria um procedimento armazenado chamado REGISTER_SINGLE_REFERENCE que chama uma função do sistema para executar uma operação específica em uma referência que é passada como um argumento para o procedimento armazenado.

Nota

Como o procedimento armazenado usa a função do sistema SYSTEM$SET_REFERENCE, o procedimento armazenado funciona apenas para uma referência com um único valor na descrição. Para associar uma referência a vários valores, use a função do sistema SYSTEM$ADD_REFERENCE.

Criação de um procedimento armazenado de retorno de chamada para solicitar a configuração do objeto

Para alguns tipos de objeto, um provedor deve adicionar um procedimento armazenado ao script de configuração para fornecer configuração adicional. Este retorno de chamada é usado quando os consumidores permitem referências usando Snowsight.

O exemplo a seguir mostra como definir um procedimento armazenado de retorno de chamada de configuração para a referência mostrada em Definição de uma referência no arquivo de manifesto:

CREATE OR REPLACE CONFIG.GET_CONFIGURATION_FOR_REFERENCE(ref_name STRING)
  RETURNS STRING
  LANGUAGE SQL
  AS
  $$
  BEGIN
    CASE (ref_name)
      WHEN 'CONSUMER_EXTERNAL_ACCESS' THEN
        RETURN '{
          "type": "CONFIGURATION",
          "payload":{
            "host_ports":["google.com"],
            "allowed_secrets" : "LIST",
            "secret_references":["CONSUMER_SECRET"]}}';
      WHEN 'CONSUMER_SECRET' THEN
        RETURN '{
          "type": "CONFIGURATION",
          "payload":{
            "type" : "OAUTH2",
            "security_integration": {
              "oauth_scopes": ["https://www.googleapis.com/auth/analytics.readonly"],
              "oauth_token_endpoint": "https://oauth2.googleapis.com/token",
              "oauth_authorization_endpoint":
                "https://accounts.google.com/o/oauth2/auth"}}}';
     END CASE;
     RETURN '';
   END;
   $$;

GRANT USAGE ON PROCEDURE CONFIG.GET_CONFIGURATION_FOR_REFERENCE(STRING)
  TO APPLICATION ROLE app_admin;
Copy

Este exemplo cria um procedimento armazenado denominado GET_CONFIGURATION_FOR_REFERENCE que retorna uma configuração com formação de JSON que é usada para construir uma referência do tipo EXTERNAL ACCESS INTEGRATION ou SECRET. As entradas na instrução de mudança devem mapear os nomes de referência no arquivo manifest.yml.

Nota

Esta função de retorno de chamada é necessária para referências do tipo EXTERNAL ACCESS INTEGRATION e SECRET. Ela só se aplica a esses tipos de referências.

Visualização das referências definidas em um aplicativo

Quando um provedor define referências no arquivo manifest.yml, eles são incluídos como parte do Snowflake Native App instalado.

Para visualizar as referências definidas para um Snowflake Native App, execute o comando SHOW REFERENCES como mostrado no exemplo a seguir:

SHOW REFERENCES IN APPLICATION hello_snowflake_app;
Copy

Vinculação de um objeto ao aplicativo

Depois de visualizar a definição de referência para um Snowflake Native App, o consumidor cria uma referência executando a função do sistema SYSTEM$REFERENCE conforme mostrado no exemplo a seguir:

SELECT SYSTEM$REFERENCE('table', 'db1.schema1.table1', 'persistent', 'select', 'insert');
Copy

Este comando retorna um identificador para a referência. O consumidor pode passar o identificador para o procedimento armazenado de retorno de chamada para a referência, conforme mostrado no exemplo a seguir:

CALL app.config.register_single_reference(
  'consumer_table' , 'ADD', SYSTEM$REFERENCE('TABLE', 'db1.schema1.table1', 'PERSISTENT', 'SELECT', 'INSERT'));
Copy

Neste exemplo, consumer_table é o nome da referência definida no arquivo manifest.yml. Depois que o consumidor executa o procedimento armazenado que associa a referência, o Snowflake Native App pode acessar a tabela na conta do consumidor.

O procedimento armazenado de retorno de chamada na seção anterior chama a função do sistema SYSTEM$SET_REFERENCE conforme mostrado no exemplo a seguir:

SELECT SYSTEM$SET_REFERENCE(:ref_name, :ref_or_alias);
Copy

Consulte Funções de referência suportadas para outras funções do sistema relacionadas a referências.

Considerações ao usar referências

A Snowflake recomenda que você não modifique as definições de referência nas versões. Para atualizar uma definição de referência em uma nova versão, por exemplo, para alterar os privilégios para SELECT, INSERT de SELECT, você deve definir uma nova definição de referência com um nome diferente. O Snowflake Native App atualizado pode usar essa nova referência na nova versão do aplicativo.

Para incorporar uma referência em outro objeto, por exemplo, para atribuir uma referência a uma variável, a referência já deve estar vinculada a um objeto na conta do consumidor. Por exemplo, você não pode criar uma tarefa a menos que primeiro vincule a referência ao warehouse do consumidor.

Exemplos de uso de referências inversas em um Snowflake Native App

As seções a seguir fornecem exemplos de uso de referências em contextos diferentes:

Nota

As funções reference() nos exemplos a seguir só podem ser chamadas em um procedimento armazenado no objeto APPLICATION.

Execução de consultas usando uma referência

Os exemplos a seguir mostram como executar consultas usando referências:

SELECT * FROM reference('consumer_table');
Copy
SELECT reference('encrypt_func')(t.c1) FROM consumer_table t;
Copy

Chamada de um procedimento armazenado usando uma referência

O exemplo a seguir mostra como chamar um procedimento armazenado usando uma referência:

CALL reference('consumer_proc')(11, 'hello world');
Copy

Execução de comandos DML usando uma referência

Os exemplos a seguir mostram como modificar dados em uma tabela usando referências:

INSERT INTO reference('data_export')(C1, C2)
  SELECT T.C1, T.C2 FROM reference('other_table')
Copy
COPY INTO reference('the_table') ...
Copy

Execução do comando DESCRIBE usando uma referência

O exemplo a seguir mostra como executar a operação DESCRIBE usando uma referência:

DESCRIBE TABLE reference('the_table')
Copy

Como usar referências em uma tarefa

CREATE TASK app_task
  WAREHOUSE = reference('consumer_warehouse')
  ...;

ALTER TASK app_task SET WAREHOUSE = reference('consumer_warehouse');
Copy

Como usar referências em uma definição de exibição

CREATE VIEW app_view
  AS SELECT reference('function')(T.C1) FROM reference('table') AS T;
Copy

Como usar referências em um corpo de função

CREATE FUNCTION app.func(x INT)
  RETURNS STRING
  AS $$ select reference('consumer_func')(x) $$;
Copy

Como usar referências em uma função externa

CREATE EXTERNAL FUNCTION app.func(x INT)
  RETURNS STRING
  ...
  API_INTEGRATION = reference('app_integration');
Copy

Como usar referências em uma função ou procedimento

CREATE FUNCTION app.func(x INT)
  RETURNS STRING
  ...
  EXTERNAL_ACCESS_INTEGRATIONS = (reference('consumer_external_access_integration'), ...);
  SECRETS = ('cred1' = reference('consumer_secret'), ...);
Copy

Nota

Os consumidores não podem chamar diretamente funções ou procedimentos armazenados que contenham referências a integrações de acesso externo ou segredos. Referências a segredos e integrações de acesso externo podem ser usadas por todos os outros componentes do aplicativo, por exemplo, aplicativos Streamlit, tarefas, outras funções e procedimentos armazenados.

Para permitir que os consumidores chamem diretamente uma função ou procedimento armazenado que contenha referências a integrações de acesso externo ou segredos, os provedores podem incluir uma função contendo esses objetos dentro de uma função wrapper que o consumidor pode chamar diretamente.

Como usar referências em uma política

CREATE ROW ACCESS POLICY app_policy
  AS (sales_region varchar) RETURNS BOOLEAN ->
  'sales_executive_role' = reference('get_sales_team')
    or exists (
      select 1 from reference('sales_table')
        where sales_manager = reference('get_sales_team')()
        and region = sales_region
      );
Copy

Formato JSON para a resposta de retorno de chamada de configuração

A função de retorno de chamada de configuração retorna uma resposta em formato JSON. O formato JSON retornado é diferente para integração de acesso externo e referências secretas.

Formato JSON para integração de acesso externo

Para referências EXTERNAL ACCESS INTEGRATION, a estrutura esperada da resposta JSON é:

{
  "type": "CONFIGURATION",
  "payload": {
    "host_ports": ["host_port_1", ...],
    "allowed_secrets": "NONE|ALL|LIST",
    "secret_references": ["ref_name_1", ...]
  }
}
Copy
  • host_ports

    Uma matriz de cadeias de caracteres. Cada valor deve ser um domínio válido.

    Opcionalmente, ela também pode incluir uma porta. O intervalo de portas válido é de 1 a 65535, inclusive. Se você não especificar uma porta, o padrão será 443. Se um local de rede externo oferecer suporte a portas dinâmicas, será necessário especificar todas as portas possíveis.

    Para permitir acesso a todas as portas, especifique a porta como 0. Por exemplo, company.com:0.

    Esses valores são usados para criar uma regra de rede de saída para a integração de acesso externo. Consulte CREATE NETWORK RULE para obter mais informações.

  • allowed_secrets

    Especifica os segredos permitidos pela referência EXTERNAL ACCESS INTEGRATION. Os valores válidos são:

    • NONE: segredos não são permitidos.

    • ALL: permite qualquer segredo existente.

    • LIST: permite um conjunto específico de segredos conforme especificado na propriedade secret_references.

    Os valores do allowed_secrets são usados para criar a integração de acesso externo. Consulte CREATE EXTERNAL ACCESS INTEGRATION para obter mais informações.

  • secret_references:

    Especifica uma lista de referências de segredo que são permitidas pela integração de acesso externo.

    Os valores especificados aqui devem ser os mesmos que as referências de segredo definidas no manifesto.

    Esta propriedade só é aplicável se o allowed_secrets estiver definido para LIST. Nesse contexto, secret_references é obrigatório.

Formato JSON para referências de segredo

Para referências de segredo, a estrutura esperada da resposta JSON é:

{
  "type": "CONFIGURATION",
    "payload": {
            "type": "OAUTH2",
            "security_integration": {
                    "oauth_scopes": ["scope_1", "scope_2"],
                    "oauth_token_endpoint" : "token_endpoint",
                    "oauth_authorization_endpoint" : "auth_endpoint"
            }
    }
}
Copy
  • payload.type

    O tipo de segredo. O valor válido é:

    • OAUTH2: especifica o segredo a ser usado com o fluxo de concessão de OAuth2. Consulte CREATE SECRET para obter mais informações.

  • payload.security_integration

    Especifica os valores necessários para configurar a autenticação de API para um segredo OAuth.

Respostas de erro do formato JSON

Em caso de erros ou se a referência ainda não estiver pronta para configuração, a estrutura esperada da resposta de erro é:

 {
   "type": "ERROR",
   "payload":{
     "message": "The reference is not available for configuration ..."
  }
}
Copy
  • message: a mensagem de erro do aplicativo que é exibida em Snowsight.

Funções de referência suportadas

O Snowflake Native App Framework oferece suporte às seguintes funções para executar diferentes operações relacionadas a referências.

Função do sistema

Descrição

set_reference

SYSTEM$SET_REFERENCE('<nome_de_referencia>', '<cadeia_de_caracteres_de_referência>')

  • Suporta apenas uma única referência. Se uma referência já tiver sido criada usando o mesmo nome, a referência existente será substituída.

  • Retorna um alias exclusivo gerado pelo sistema para a referência.

add_reference

SYSTEM$ADD_REFERENCE('<nome_de_referencia>', '<cadeia_de_caracteres_de_referência>')

  • Oferece suporte a referências únicas e de vários valores. Para referências de valor único, a função retornará um erro se uma referência já tiver sido criada usando o mesmo valor especificado por reference_name.

  • Retorna um alias exclusivo gerado pelo sistema para a referência.

remove_reference

SYSTEM$REMOVE_REFERENCE('<nome_de_referencia>'[, '<alias>'])

  • Oferece suporte a referências únicas e de vários valores. Um <alias> é necessário para remover referências de vários valores.

  • Remove uma associação com uma referência de vários valores.

remove_all_references

SYSTEM$REMOVE_ALL_REFERENCES('<nome_de_referencia>')

  • Remove todas as associações à referência.

get_all_references

SYSTEM$GET_ALL_REFERENCES('<nome_de_referencia>')

  • Retorna uma matriz de aliases gerados pelo sistema de entidades associadas a um nome de referência:

    • Lista vazia se o nome de referência não estiver vinculado a uma entidade

    • Todas as associações para referências de vários valores

    • Associação 1 ou 0 para referências de valor único

    • O valor retornado não contém o nome do objeto do consumidor

  • Usado para percorrer todas as associações para uma referência de múltiplos valores em um loop.

get_referenced_object_id_hash

SYSTEM$GET_REFERENCED_OBJECT_ID_HASH('<nome_de_referencia>'[, '<alias>'])

  • Usa o alias gerado pelo sistema para referência de vários valores.

  • Retorna o hash do ID da entidade do objeto vinculado. Este é o identificador da entidade resolvida originalmente quando uma referência foi criada.

  • Esta função é útil para o Snowflake Native App determinar se o objeto vinculado a uma referência foi alterado. O Snowflake Native App pode salvar o valor e depois comparar o valor atual com o valor conhecido anteriormente.