외부 네트워크 액세스 예시

이 항목에서는 사용자 정의 함수와 프로시저에서 외부 네트워크 위치에 액세스하는 예를 제시합니다.

Google Translate API에 액세스하기

다음 단계에는 Google Translate API에 액세스하기 위한 외부 액세스 통합을 생성하는 코드가 포함됩니다. 이러한 단계에서는 문을 실행하는 데 필요한 보안 통합과 권한을 추가합니다.

  1. 외부 위치를 나타내는 네트워크 규칙을 만듭니다.

    외부 액세스에서 네트워크 규칙의 역할에 대한 자세한 내용은 외부 네트워크 위치를 나타내는 네트워크 규칙 만들기 섹션을 참조하십시오.

    CREATE OR REPLACE NETWORK RULE google_apis_network_rule
      MODE = EGRESS
      TYPE = HOST_PORT
      VALUE_LIST = ('translation.googleapis.com');
    
    Copy
  2. google_apis_network_rule 네트워크 규칙으로 지정한 외부 네트워크 위치로 인증하는 데 필요한 OAuth 자격 증명을 보관하기 위한 보안 통합을 만듭니다.

    명령에 대한 참조 정보는 CREATE SECURITY INTEGRATION(External API 인증) 섹션을 참조하십시오.

    CREATE OR REPLACE SECURITY INTEGRATION google_translate_oauth
      TYPE = API_AUTHENTICATION
      AUTH_TYPE = OAUTH2
      OAUTH_CLIENT_ID = 'my-client-id'
      OAUTH_CLIENT_SECRET = 'my-client-secret'
      OAUTH_TOKEN_ENDPOINT = 'https://oauth2.googleapis.com/token'
      OAUTH_AUTHORIZATION_ENDPOINT = 'https://accounts.google.com/o/oauth2/auth'
      OAUTH_ALLOWED_SCOPES = ('https://www.googleapis.com/auth/cloud-platform')
      ENABLED = TRUE;
    
    Copy
  3. google_translate_oauth 보안 통합에 포함된 자격 증명을 나타내는 시크릿을 만듭니다.

    외부 액세스에서 시크릿의 역할에 대한 자세한 내용은 자격 증명을 나타내는 시크릿 만들기 섹션을 참조하십시오.

    OAUTH_REFRESH_TOKEN 값의 경우 서비스 공급자(이 경우 Google Cloud Translation API 서비스)로부터 얻은 새로 고침 토큰을 지정해야 합니다. 예를 들어 새로 고침 토큰을 받으려면 다음을 사용할 수 있습니다.

    • Google OAuth Playground. 1단계에서 Cloud Translation API를 선택하고 권한을 부여합니다. 2단계에서 exchange authorization code for tokens 를 클릭한 다음 refresh token 토큰 값을 복사합니다.

    CREATE OR REPLACE SECRET oauth_token
      TYPE = oauth2
      API_AUTHENTICATION = google_translate_oauth
      OAUTH_REFRESH_TOKEN = 'my-refresh-token';
    
    Copy
  4. developer 역할을 생성하고 시크릿에 대한 READ 권한을 이 역할에 부여합니다. 이 역할은 시크릿을 사용하는 UDF 또는 프로시저를 생성해야 하는 사용자에게 할당됩니다.

    또한 사용자가 함수 호출에 사용할 역할을 생성합니다.

    USE ROLE USERADMIN;
    CREATE OR REPLACE ROLE developer;
    CREATE OR REPLACE ROLE user;
    
    Copy

    developer 역할에 READ 권한을 부여합니다.

    GRANT READ ON SECRET oauth_token TO ROLE developer;
    
    Copy
  5. 외부 액세스 통합 만들기 에 설명된 대로 네트워크 규칙과 시크릿을 사용하여 외부 액세스 통합을 만듭니다.

    이 명령을 실행하려면 기본적으로 ACCOUNTADMIN 역할에 있는 CREATE INTEGRATION 권한이 있는 역할을 사용해야 합니다.

    USE ROLE ACCOUNTADMIN;
    
    CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION google_apis_access_integration
      ALLOWED_NETWORK_RULES = (google_apis_network_rule)
      ALLOWED_AUTHENTICATION_SECRETS = (oauth_token)
      ENABLED = TRUE;
    
    Copy
  6. UDF 개발자가 사용할 수 있도록 통합에 대한 USAGE 권한을 developer 역할에 부여합니다. UDF 또는 프로시저에서 외부 네트워크 위치에 액세스하기 위해 통합을 사용하려는 사용자는 통합에 대한 USAGE 권한이 있는 역할을 사용해야 합니다.

    GRANT USAGE ON INTEGRATION google_apis_access_integration TO ROLE developer;
    
    Copy
  7. 지정된 텍스트를 지정된 언어의 문구로 번역하는 UDF google_translate_python 을 만듭니다. 자세한 내용은 함수 또는 프로시저에서 외부 액세스 통합 사용하기 섹션을 참조하십시오.

    USE ROLE developer;
    
    CREATE OR REPLACE FUNCTION google_translate_python(sentence STRING, language STRING)
    RETURNS STRING
    LANGUAGE PYTHON
    RUNTIME_VERSION = 3.8
    HANDLER = 'get_translation'
    EXTERNAL_ACCESS_INTEGRATIONS = (google_apis_access_integration)
    PACKAGES = ('snowflake-snowpark-python','requests')
    SECRETS = ('cred' = oauth_token )
    AS
    $$
    import _snowflake
    import requests
    import json
    session = requests.Session()
    def get_translation(sentence, language):
      token = _snowflake.get_oauth_access_token('cred')
      url = "https://translation.googleapis.com/language/translate/v2"
      data = {'q': sentence,'target': language}
      response = session.post(url, json = data, headers = {"Authorization": "Bearer " + token})
      return response.json()['data']['translations'][0]['translatedText']
    $$;
    
    Copy
  8. 사용자 역할을 가진 사용자가 호출할 수 있도록 google_translate_python 함수에 대한 USAGE 권한을 부여합니다.

    GRANT USAGE ON FUNCTION google_translate_python(string, string) TO ROLE user;
    
    Copy
  9. google_translate_python 함수를 실행하여 문구를 번역합니다.

    USE ROLE user;
    SELECT google_translate_python('Happy Thursday!', 'zh-CN');
    
    Copy

    그러면 다음과 같은 출력이 생성됩니다.

    -------------------------------------------------------
    | GOOGLE_TRANSLATE_PYTHON('HAPPY THURSDAY!', 'ZH-CN') |
    -------------------------------------------------------
    | 快乐星期四!                                          |
    -------------------------------------------------------
    

외부 람다 함수에 액세스하기

다음 단계에는 Snowflake 외부의 람다 함수에 액세스하기 위한 외부 액세스 통합을 생성하는 예제 코드가 포함되어 있습니다. 이 예시에서는 외부 엔드포인트 자체에 대한 자리 표시자를 사용하지만, 예를 들어 REST 서비스 엔드포인트에서 사용 가능한 함수일 수도 있습니다.

외부 액세스는 데이터가 포함된 Pandas DataFrame을 수신하는 벡터화된 Python UDF 에서 사용됩니다.

  1. 외부 위치 my_external_service (여기서는 외부 엔드포인트의 위치를 나타내는 자리 표시자 값)를 나타내는 네트워크 규칙 lambda_network_rule 을 만듭니다.

    외부 액세스에서 네트워크 규칙의 역할에 대한 자세한 내용은 외부 네트워크 위치를 나타내는 네트워크 규칙 만들기 섹션을 참조하십시오.

    CREATE OR REPLACE NETWORK RULE lambda_network_rule
      MODE = EGRESS
      TYPE = HOST_PORT
      VALUE_LIST = ('my_external_service');
    
    Copy
  2. 외부 서비스에 필요한 자격 증명을 나타내는 시크릿을 만듭니다.

    이 예시의 뒷부분에 나오는 처리기 코드는 Python용 Snowflake API를 사용하여 시크릿에서 자격 증명을 불러옵니다.

    외부 액세스에서 시크릿의 역할에 대한 자세한 내용은 자격 증명을 나타내는 시크릿 만들기 섹션을 참조하십시오.

    CREATE OR REPLACE SECRET secret_password
      TYPE = PASSWORD
      USERNAME = 'my_user_name'
      PASSWORD = 'my_password';
    
    Copy
  3. developer 역할을 생성하고 시크릿에 대한 READ 권한을 이 역할에 부여합니다. 이 역할은 시크릿을 사용하는 UDF 또는 프로시저를 생성해야 하는 사용자에게 할당됩니다.

    또한 사용자가 함수 호출에 사용할 역할을 생성합니다.

    USE ROLE USERADMIN;
    
    CREATE OR REPLACE ROLE developer;
    CREATE OR REPLACE ROLE user;
    
    Copy

    developer 역할에 시크릿에 대한 READ 권한을 부여합니다.

    GRANT READ ON SECRET secret_password TO ROLE developer;
    
    Copy
  4. 외부 액세스 통합을 생성하여 생성한 네트워크 규칙과 시크릿을 통해 외부 엔드포인트 및 자격 증명을 지정합니다.

    이 명령을 실행하려면 기본적으로 ACCOUNTADMIN 역할에 있는 CREATE INTEGRATION 권한이 있는 역할을 사용해야 합니다.

    통합 생성에 대한 자세한 내용은 외부 액세스 통합 만들기 섹션을 참조하십시오.

    USE ROLE ACCOUNTADMIN;
    
    CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION lambda_external_access_integration
      ALLOWED_NETWORK_RULES = (lambda_network_rule)
      ALLOWED_AUTHENTICATION_SECRETS = (secret_password)
      ENABLED = TRUE;
    
    Copy
  5. Pandas DataFrame 으로 수신된 데이터를 처리하기 위해 외부 네트워크 위치에 액세스하는 벡터화된 Python UDF return_double_column 를 만듭니다.

    UDF에서 외부 액세스를 사용하는 방법에 대한 자세한 내용은 함수 또는 프로시저에서 외부 액세스 통합 사용하기 섹션을 참조하십시오.

    CREATE OR REPLACE FUNCTION return_double_column(x int)
    RETURNS INT
    LANGUAGE PYTHON
    EXTERNAL_ACCESS_INTEGRATIONS = (lambda_external_access_integration)
    SECRETS = ('cred' = secret_password)
    RUNTIME_VERSION = 3.8
    HANDLER = 'return_first_column'
    PACKAGES = ('pandas', 'requests')
    AS $$
    import pandas
    import numpy as np
    import json
    import requests
    import base64
    import _snowflake
    from _snowflake import vectorized
    from requests.auth import HTTPBasicAuth
    from requests.adapters import HTTPAdapter
    from requests.packages.urllib3.util.retry import Retry
    
    session = requests.Session()
    retries = Retry(total=10, backoff_factor=1, status_forcelist=[429, 500, 502, 503, 504], allowed_methods = None)
    
    session.mount('https://', HTTPAdapter(max_retries=retries))
    
    @vectorized(input=pandas.DataFrame)
    def return_first_column(df):
      request_rows = []
    
      df.iloc[:,0] = df.iloc[:,0].astype(int)
      request_rows = np.column_stack([df.index, df.iloc[:,0]]).tolist()
    
      request_payload = {"data" : request_rows}
    
      username_password_object = _snowflake.get_username_password('cred');
      basic = HTTPBasicAuth(username_password_object.username, username_password_object.password)
    
      url = 'my_external_service'
    
      response = session.post(url, json=request_payload, auth=basic)
    
      response.raise_for_status()
      response_payload = json.loads(response.text)
    
      response_rows = response_payload["data"]
    
      return pandas.DataFrame(response_rows)[1]
    $$;
    
    Copy
  6. user 역할이 있는 사용자가 호출할 수 있도록 return_double_column 함수에 대한 USAGE 권한을 부여합니다.

    GRANT USAGE ON FUNCTION return_double_column(int) TO ROLE user;
    
    Copy
  7. return_double_column 함수를 실행하여 외부 엔드포인트에 요청합니다.

    다음 예제의 코드는 2열 테이블을 생성하고 4바이트 정수가 포함된 100,000,000개의 행을 삽입합니다. 그런 다음 이 코드는 return_double_column 함수를 실행하여 외부 엔드포인트에서 처리하도록 a 열의 값을 전달합니다.

    CREATE OR REPLACE TABLE t1 (a INT, b INT);
    INSERT INTO t1 SELECT SEQ4(), SEQ4() FROM TABLE(GENERATOR(ROWCOUNT => 100000000));
    
    SELECT return_double_column(a) AS retval FROM t1 ORDER BY retval;
    
    Copy