AWS 上での外部ネットワークアクセスとプライベート接続¶
このトピックでは、 外部ネットワークアクセス を使用して、AWS 外部サービスへのアウトバウンド プライベート接続を設定するための構成の詳細を説明します。アウトバウンド・パブリック接続とアウトバウンド・プライベート接続の設定の主な違いは、プライベート接続の場合、以下の操作を行う必要があることです。
プライベート接続エンドポイントを作成します。このステップでは、 ACCOUNTADMIN ロールが必要です。
ネットワーク・ルールを作成し、
TYPE
プロパティをPRIVATE_HOST_PORT
にセットします。
アウトバウンド プライベート接続コスト¶
各プライベート・コネクティビティ・エンドポイントの料金は、処理されるデータ総量に応じて支払われます。これらのアイテムの価格については、 Snowflake Service Consumption Table をご参照ください。
ACCOUNT_USAGE および ORGANIZATION_USAGE スキーマで請求ビューをクエリする際、以下のサービスタイプでフィルターをかけることで、これらの項目のコストを調べることができます。
OUTBOUND_PRIVATELINK_ENDPOINT
OUTBOUND_PRIVATELINK_DATA_PROCESSED
例えば、 USAGE_IN_CURRENCY_DAILY 表示をクエリし、これらのサービスタイプでフィルターをかけることができます。
外部Amazon S3サービスへのプライベート接続のセットアップ¶
SYSTEM$PROVISION_PRIVATELINK_ENDPOINT システム関数を呼び出して、Snowflake が AWS S3 サービスに接続することを指定し、サービスに接続するときに使用するホスト名を指定します:
USE ROLE ACCOUNTADMIN; SELECT SYSTEM$PROVISION_PRIVATELINK_ENDPOINT( 'com.amazonaws.us-west-2.s3', '*.s3.us-west-2.amazonaws.com' );
注釈
*.s3.us-west-2.amazonaws.com
のアスタリスクは、エンドポイントを使用して複数のS3バケットにアクセスできることを示します。次の SQL ステートメントを実行して、Snowflake が外部宛先にリクエストを送信できるようにするネットワークルールを作成します。
TYPE
プロパティをPRIVATE_HOST_PORT
にセットしてください:CREATE OR REPLACE NETWORK RULE aws_s3_network_rule MODE = EGRESS TYPE = PRIVATE_HOST_PORT VALUE_LIST = ('external-access-iam-bucket.s3.us-west-2.amazonaws.com');
以下の SQL ステートメントを実行して、外部 API 認証用のセキュリティ統合を作成します:
CREATE OR REPLACE SECURITY INTEGRATION aws_s3_security_integration TYPE = API_AUTHENTICATION AUTH_TYPE = AWS_IAM ENABLED = TRUE AWS_ROLE_ARN = 'arn:aws:iam::736112632310:role/external-access-iam-bucket';
次の SQL ステートメントを実行して、 IAM ユーザーの
STORAGE_AWS_IAM_USER_ARN
とSTORAGE_AWS_EXTERNAL_ID
の値を取得します:DESC SECURITY INTEGRATION aws_s3_security_integration;
STORAGE_AWS_IAM_USER_ARN
とSTORAGE_AWS_EXTERNAL_ID
の値を使用して、 オプション1: Amazon S3にアクセスするためのSnowflakeストレージ統合の構成 の ステップ 5 に従って、 IAM ユーザーに Amazon S3 サービスへのアクセスを付与します。以下の SQL ステートメントを実行して、 AWS S3サービスで認証に使用するトークンを作成します:
CREATE OR REPLACE SECRET aws_s3_access_token TYPE = CLOUD_PROVIDER_TOKEN API_AUTHENTICATION = aws_s3_security_integration;
次の SQL ステートメントを実行して、前の手順で作成したネットワークルールとトークンを使用する外部アクセス統合を作成します:
CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION aws_s3_external_access_integration ALLOWED_NETWORK_RULES = (aws_s3_network_rule) ALLOWED_AUTHENTICATION_SECRETS = (aws_s3_access_token) ENABLED = TRUE COMMENT = 'Testing S3 connectivity';
次の SQL ステートメントのいずれかを実行して、以前に作成した外部アクセス統合とトークンを使用できる関数を作成します:
CREATE OR REPLACE FUNCTION aws_s3_python_function() RETURNS VARCHAR LANGUAGE PYTHON EXTERNAL_ACCESS_INTEGRATIONS = (aws_s3_external_access_integration) RUNTIME_VERSION = '3.8' SECRETS = ('cred' = aws_s3_access_token) PACKAGES = ('boto3') HANDLER = 'main_handler' AS $$ import boto3 import _snowflake from botocore.config import Config def main_handler(): # Get the previously created token as an object cloud_provider_object = _snowflake.get_cloud_provider_token('cred') # Configure boto3 connection settings config = Config( retries=dict(total_max_attempts=9), connect_timeout=30, read_timeout=30, max_pool_connections=50 ) # Connect to S3 using boto3 s3 = boto3.client( 's3', region_name='us-west-2', aws_access_key_id=cloud_provider_object.access_key_id, aws_secret_access_key=cloud_provider_object.secret_access_key, aws_session_token=cloud_provider_object.token, config=config ) # Use the s3 object upload/download resources # ... return 'Successfully connected to AWS S3' $$;
CREATE OR REPLACE FUNCTION aws_s3_java_function() RETURNS STRING LANGUAGE JAVA EXTERNAL_ACCESS_INTEGRATIONS = (aws_s3_external_access_integration) SECRETS = ('cred' = aws_s3_access_token) HANDLER = 'AWSTokenProvider.handle' AS $$ import com.snowflake.snowpark_java.types.CloudProviderToken; import com.snowflake.snowpark_java.types.SnowflakeSecrets; public class AWSTokenProvider { public static String handle() { // Get the previously created token as an object SnowflakeSecrets sfSecret = SnowflakeSecrets.newInstance(); CloudProviderToken cloudProviderToken = sfSecret.getCloudProviderToken("cred"); // Create variables for the AWS session credentials String accessKeyId = cloudProviderToken.getAccessKeyId(); String secretAccessKey = cloudProviderToken.getSecretAccessKey(); String token = cloudProviderToken.getToken(); // Use the token to create an S3 client // ... return "Successfully connected to AWS S3 with the following access token: " + token; } } $$;
以下の SQL ステートメントのいずれかを実行して、作成した関数を実行します:
SELECT aws_s3_python_function();
SELECT aws_s3_java_function();
外部のAmazon Bedrockサービスへのプライベート接続のセットアップ¶
SYSTEM$PROVISION_PRIVATELINK_ENDPOINT システム関数を呼び出して、Snowflake が AWS S3 と Amazon Bedrock サービスに接続することと、サービスに接続するときに使用するホスト名を指定します:
USE ROLE ACCOUNTADMIN; SELECT SYSTEM$PROVISION_PRIVATELINK_ENDPOINT( 'com.amazonaws.us-west-2.s3', '*.s3.us-west-2.amazonaws.com' ); SELECT SYSTEM$PROVISION_PRIVATELINK_ENDPOINT( 'com.amazonaws.us-west-2.bedrock-runtime', 'bedrock-runtime.us-west-2.amazonaws.com' );
次の SQL ステートメントを実行して、Snowflake が外部宛先にリクエストを送信できるようにするネットワークルールを作成します。
TYPE
プロパティをPRIVATE_HOST_PORT
にセットしてください:CREATE OR REPLACE NETWORK RULE bedrock_network_rule MODE = EGRESS TYPE = PRIVATE_HOST_PORT VALUE_LIST = ('bedrock-runtime.us-west-2.amazonaws.com');
以下の SQL ステートメントを実行して、外部 API 認証用のセキュリティ統合を作成します:
CREATE OR REPLACE SECURITY INTEGRATION bedrock_security_integration TYPE = API_AUTHENTICATION AUTH_TYPE = AWS_IAM ENABLED = TRUE AWS_ROLE_ARN = 'arn:aws:iam::736112632310:role/external-access-iam-bucket';
次の SQL ステートメントを実行して、 IAM ユーザーの
STORAGE_AWS_IAM_USER_ARN
とSTORAGE_AWS_EXTERNAL_ID
の値を取得します:DESC SECURITY INTEGRATION bedrock_security_integration;
STORAGE_AWS_IAM_USER_ARN
とSTORAGE_AWS_EXTERNAL_ID
の値を使用して、 オプション1: Amazon S3にアクセスするためのSnowflakeストレージ統合の構成 の ステップ 5 に従って、 IAM ユーザーに Amazon Bedrock サービスへのアクセスを付与します。以下の SQL ステートメントを実行して、 AWS Bedrock サービスで認証に使用するトークンを作成します:
CREATE OR REPLACE SECRET aws_bedrock_access_token TYPE = CLOUD_PROVIDER_TOKEN API_AUTHENTICATION = bedrock_security_integration;
次の SQL ステートメントを実行して、前の手順で作成したネットワークルールとトークンを使用する外部アクセス統合を作成します:
CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION bedrock_external_access_integration ALLOWED_NETWORK_RULES = (bedrock_network_rule) ALLOWED_AUTHENTICATION_SECRETS=(aws_bedrock_access_token) ENABLED=true ;
次の SQL ステートメントを実行して、以前に作成した外部アクセス統合とトークンを使用できる関数を作成します:
CREATE OR REPLACE FUNCTION bedrock_private_connectivity_tests( id INT, instructions VARCHAR, user_context VARCHAR, model_id VARCHAR ) RETURNS VARCHAR LANGUAGE PYTHON EXTERNAL_ACCESS_INTEGRATIONS = (bedrock_external_access_integration) RUNTIME_VERSION = '3.8' SECRETS = ('cred' = aws_bedrock_access_token) PACKAGES = ('boto3') HANDLER = 'bedrock_py' AS $$ import boto3 import json import _snowflake def bedrock_py(id, instructions, user_context, model_id): # Get the previously created token as an object cloud_provider_object = _snowflake.get_cloud_provider_token('cred') cloud_provider_dictionary = { "ACCESS_KEY_ID": cloud_provider_object.access_key_id, "SECRET_ACCESS_KEY": cloud_provider_object.secret_access_key, "TOKEN": cloud_provider_object.token } # Assign AWS credentials and choose a region boto3_session_args = { 'aws_access_key_id': cloud_provider_dictionary["ACCESS_KEY_ID"], 'aws_secret_access_key': cloud_provider_dictionary["SECRET_ACCESS_KEY"], 'aws_session_token': cloud_provider_dictionary["TOKEN"], 'region_name': 'us-west-2' } session = boto3.Session(**boto3_session_args) client = session.client('bedrock-runtime') # Prepare the request body for the specified model def prepare_request_body(model_id, instructions, user_context): default_max_tokens = 512 default_temperature = 0.7 default_top_p = 1.0 if model_id == 'amazon.titan-text-express-v1': body = { "inputText": f"<SYSTEM>Follow these:{instructions}<END_SYSTEM>\n<USER_CONTEXT>Use this user context in your response:{user_context}<END_USER_CONTEXT>", "textGenerationConfig": { "maxTokenCount": default_max_tokens, "stopSequences": [], "temperature": default_temperature, "topP": default_top_p } } elif model_id == 'ai21.j2-ultra-v1': body = { "prompt": f"<SYSTEM>Follow these:{instructions}<END_SYSTEM>\n<USER_CONTEXT>Use this user context in your response:{user_context}<END_USER_CONTEXT>", "temperature": default_temperature, "topP": default_top_p, "maxTokens": default_max_tokens } elif model_id == 'anthropic.claude-3-sonnet-20240229-v1:0': body = { "max_tokens": default_max_tokens, "messages": [{"role": "user", "content": f"<SYSTEM>Follow these:{instructions}<END_SYSTEM>\n<USER_CONTEXT>Use this user context in your response:{user_context}<END_USER_CONTEXT>"}], "anthropic_version": "bedrock-2023-05-31" } else: raise ValueError("Unsupported model ID") return json.dumps(body) # Call Bedrock to get a completion body = prepare_request_body(model_id, instructions, user_context) response = client.invoke_model(modelId=model_id, body=body) response_body = json.loads(response.get('body').read()) # Parse the API response based on the model def get_completion_from_response(response_body, model_id): if model_id == 'amazon.titan-text-express-v1': output_text = response_body.get('results')[0].get('outputText') elif model_id == 'ai21.j2-ultra-v1': output_text = response_body.get('completions')[0].get('data').get('text') elif model_id == 'anthropic.claude-3-sonnet-20240229-v1:0': output_text = response_body.get('content')[0].get('text') else: raise ValueError("Unsupported model ID") return output_text # Get the generated text from Bedrock output_text = get_completion_from_response(response_body, model_id) return output_text $$;
以下の SQL ステートメントを実行して、作成した関数を実行します:
SELECT bedrock_private_connectivity_tests();