외부 네트워크 액세스 예시

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

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 서비스)로부터 새로 고침 토큰을 얻으려면 해당 공급자가 Snowflake 시스템 함수를 제공하거나 사용하는 방법을 사용할 수 있습니다.

    새로 고침 토큰으로 시크릿을 만들려면 다음 설명에 따라 Google OAuth Playground 또는 Snowflake 시스템 함수 중 하나 를 사용하십시오.

    • Snowflake 시스템 함수

      1. 시크릿을 생성하려면 CREATE SECRET을 실행하십시오. 이후 단계에서 새로 고침 토큰으로 업데이트합니다.

        USE DATABASE my_db;
        USE SCHEMA secret_schema;
        
        CREATE OR REPLACE SECRET oauth_token
          TYPE = oauth2
          API_AUTHENTICATION = google_translate_oauth;
        
        Copy
      2. 이전에 생성한 시크릿의 이름을 인자로 지정하여 SYSTEM$START_OAUTH_FLOW 함수를 실행하여 새로 고침 토큰을 얻을 수 있는 URL을 검색합니다.

        SYSTEM$START_OAUTH_FLOW( 'my_db.secret_schema.oauth_token' )
        
        Copy

        이 함수는 OAuth 동의 프로세스를 완료하는 데 사용할 수 있는 URL을 생성합니다.

      3. 브라우저에서 생성된 URL을 방문하여 OAuth2 동의 프로세스를 완료합니다. 완료되면 프로세스의 마지막 페이지까지 브라우저를 열어 둡니다.

      4. 브라우저 주소 표시줄에서 동의 프로세스 마지막 페이지의 URL에 있는 물음표 뒤의 텍스트를 모두 복사합니다.

      5. 브라우저 주소 표시줄에서 방금 복사한 매개 변수를 인자로 지정하여 SYSTEM$FINISH_OAUTH_FLOW 함수를 실행합니다.

        그러면 새로 고침 토큰으로 시크릿이 업데이트됩니다.

        SYSTEM$START_OAUTH_FLOW와 동일한 세션에서 SYSTEM$FINISH_OAUTH_FLOW를 실행해야 합니다. SYSTEM$FINISH_OAUTH_FLOW는 SYSTEM$START_OAUTH_FLOW에 지정한 시크릿을 OAuth 서버에서 얻은 액세스 토큰과 새로 고침 토큰으로 업데이트합니다.

        SYSTEM$FINISH_OAUTH_FLOW( 'state=<remaining_url_text>' )
        
        Copy
    • Google OAuth Playground

      1. Google OAuth Playground 에서 1단계에 지정한 대로 Cloud TranslationAPI를 선택하고 권한을 부여합니다.

      2. 2단계에서 exchange authorization code for tokens 를 클릭한 다음 refresh token 토큰 값을 복사합니다.

      3. CREATE SECRET을 실행하여 복사한 새로 고침 토큰 값을 지정하는 시크릿을 생성합니다.

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

        CREATE OR REPLACE SECRET oauth_token
          TYPE = oauth2
          API_AUTHENTICATION = google_translate_oauth
          OAUTH_REFRESH_TOKEN = 'my-refresh-token';
        
        Copy
  4. 네트워크 규칙과 시크릿을 사용하여 외부 액세스 통합을 만듭니다.

    필요한 권한을 포함하여, 외부 액세스 통합의 역할에 대한 자세한 내용은 외부 액세스 통합 만들기 섹션을 참조하십시오.

    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
  5. 통합을 사용하는 UDF 또는 프로시저를 생성해야 하는 사용자에게 할당할 developer 역할을 만듭니다.

    CREATE OR REPLACE ROLE developer;
    CREATE OR REPLACE ROLE user;
    
    Copy
  6. 외부 액세스를 위해 오브젝트를 사용하는 UDF를 생성하는 데 필요한 권한을 developer 역할에 부여합니다. 여기에는 다음이 포함됩니다.

    • 시크릿에 대한 READ 권한.

    • 시크릿이 포함된 스키마에 대한 USAGE 권한.

    • 통합에 대한 USAGE 권한.

      GRANT READ ON SECRET oauth_token TO ROLE developer;
      GRANT USAGE ON SCHEMA secret_schema TO ROLE developer;
      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. user 역할이 있는 사용자가 호출할 수 있도록 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 또는 프로시저를 생성해야 하는 사용자에게 할당됩니다.

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

    CREATE OR REPLACE ROLE developer;
    CREATE OR REPLACE ROLE user;
    
    Copy
  4. 외부 액세스를 위해 오브젝트를 사용하는 UDF를 생성하는 데 필요한 권한을 developer 역할에 부여합니다. 여기에는 다음이 포함됩니다.

    • 시크릿에 대한 READ 권한.

    • 시크릿이 포함된 스키마에 대한 USAGE 권한.

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

    필요한 권한을 포함하여, 외부 액세스 통합의 역할에 대한 자세한 내용은 외부 액세스 통합 만들기 섹션을 참조하십시오.

    CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION lambda_external_access_integration
      ALLOWED_NETWORK_RULES = (lambda_network_rule)
      ALLOWED_AUTHENTICATION_SECRETS = (secret_password)
      ENABLED = TRUE;
    
    Copy
  6. 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
  7. user 역할이 있는 사용자가 호출할 수 있도록 return_double_column 함수에 대한 USAGE 권한을 부여합니다.

    GRANT USAGE ON FUNCTION return_double_column(int) TO ROLE user;
    
    Copy
  8. 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