Amazon OpenSearch Serverless와 상호 작용하기 위한 AWS SDK 사용 - 아마존 OpenSearch 서비스

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

Amazon OpenSearch Serverless와 상호 작용하기 위한 AWS SDK 사용

이 섹션에는 AWS SDK를 사용하여 Amazon OpenSearch Serverless와 상호 작용하는 방법의 예시가 나와 있습니다. 이 코드 샘플은 보안 정책 및 컬렉션을 만드는 방법과 컬렉션을 쿼리하는 방법을 보여줍니다.

참고

현재 이러한 코드 샘플을 빌드하고 있습니다. 코드 샘플(Java, Go 등)을 제공하려면 GitHub 리포지토리 내에서 직접 끌어오기 요청을 여세요.

Python

다음 샘플 스크립트는 AWS SDK for Python (Boto3)뿐만 아니라 Python용 opensearch-py 클라이언트를 사용하여 암호화, 네트워크, 데이터 액세스 정책을 생성하고 일치하는 컬렉션을 생성하고 일부 샘플 데이터를 인덱싱합니다.

필요한 종속성을 설치하려면 다음 명령을 실행합니다.

pip install opensearch-py pip install boto3 pip install botocore pip install requests-aws4auth

스크립트 내에서 Principal 요소를 요청에 서명하는 사용자 또는 역할의 Amazon 리소스 이름(ARN)으로 바꿉니다. 선택적으로 region을 수정할 수도 있습니다.

from opensearchpy import OpenSearch, RequestsHttpConnection from requests_aws4auth import AWS4Auth import boto3 import botocore import time # Build the client using the default credential configuration. # You can use the CLI and run 'aws configure' to set access key, secret # key, and default region. client = boto3.client('opensearchserverless') service = 'aoss' region = 'us-east-1' credentials = boto3.Session().get_credentials() awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, region, service, session_token=credentials.token) def createEncryptionPolicy(client): """Creates an encryption policy that matches all collections beginning with tv-""" try: response = client.create_security_policy( description='Encryption policy for TV collections', name='tv-policy', policy=""" { \"Rules\":[ { \"ResourceType\":\"collection\", \"Resource\":[ \"collection\/tv-*\" ] } ], \"AWSOwnedKey\":true } """, type='encryption' ) print('\nEncryption policy created:') print(response) except botocore.exceptions.ClientError as error: if error.response['Error']['Code'] == 'ConflictException': print( '[ConflictException] The policy name or rules conflict with an existing policy.') else: raise error def createNetworkPolicy(client): """Creates a network policy that matches all collections beginning with tv-""" try: response = client.create_security_policy( description='Network policy for TV collections', name='tv-policy', policy=""" [{ \"Description\":\"Public access for TV collection\", \"Rules\":[ { \"ResourceType\":\"dashboard\", \"Resource\":[\"collection\/tv-*\"] }, { \"ResourceType\":\"collection\", \"Resource\":[\"collection\/tv-*\"] } ], \"AllowFromPublic\":true }] """, type='network' ) print('\nNetwork policy created:') print(response) except botocore.exceptions.ClientError as error: if error.response['Error']['Code'] == 'ConflictException': print( '[ConflictException] A network policy with this name already exists.') else: raise error def createAccessPolicy(client): """Creates a data access policy that matches all collections beginning with tv-""" try: response = client.create_access_policy( description='Data access policy for TV collections', name='tv-policy', policy=""" [{ \"Rules\":[ { \"Resource\":[ \"index\/tv-*\/*\" ], \"Permission\":[ \"aoss:CreateIndex\", \"aoss:DeleteIndex\", \"aoss:UpdateIndex\", \"aoss:DescribeIndex\", \"aoss:ReadDocument\", \"aoss:WriteDocument\" ], \"ResourceType\": \"index\" }, { \"Resource\":[ \"collection\/tv-*\" ], \"Permission\":[ \"aoss:CreateCollectionItems\" ], \"ResourceType\": \"collection\" } ], \"Principal\":[ \"arn:aws:iam::123456789012:role\/Admin\" ] }] """, type='data' ) print('\nAccess policy created:') print(response) except botocore.exceptions.ClientError as error: if error.response['Error']['Code'] == 'ConflictException': print( '[ConflictException] An access policy with this name already exists.') else: raise error def createCollection(client): """Creates a collection""" try: response = client.create_collection( name='tv-sitcoms', type='SEARCH' ) return(response) except botocore.exceptions.ClientError as error: if error.response['Error']['Code'] == 'ConflictException': print( '[ConflictException] A collection with this name already exists. Try another name.') else: raise error def waitForCollectionCreation(client): """Waits for the collection to become active""" response = client.batch_get_collection( names=['tv-sitcoms']) # Periodically check collection status while (response['collectionDetails'][0]['status']) == 'CREATING': print('Creating collection...') time.sleep(30) response = client.batch_get_collection( names=['tv-sitcoms']) print('\nCollection successfully created:') print(response["collectionDetails"]) # Extract the collection endpoint from the response host = (response['collectionDetails'][0]['collectionEndpoint']) final_host = host.replace("https://", "") indexData(final_host) def indexData(host): """Create an index and add some sample data""" # Build the OpenSearch client client = OpenSearch( hosts=[{'host': host, 'port': 443}], http_auth=awsauth, use_ssl=True, verify_certs=True, connection_class=RequestsHttpConnection, timeout=300 ) # It can take up to a minute for data access rules to be enforced time.sleep(45) # Create index response = client.indices.create('sitcoms-eighties') print('\nCreating index:') print(response) # Add a document to the index. response = client.index( index='sitcoms-eighties', body={ 'title': 'Seinfeld', 'creator': 'Larry David', 'year': 1989 }, id='1', ) print('\nDocument added:') print(response) def main(): createEncryptionPolicy(client) createNetworkPolicy(client) createAccessPolicy(client) createCollection(client) waitForCollectionCreation(client) if __name__ == "__main__": main()

JavaScript

다음 샘플 스크립트는 Node.js의 JavaScript용 SDK와 JavaScript용 opensearch-js 클라이언트를 사용하여 암호화, 네트워크, 데이터 액세스 정책을 생성하고, 일치하는 컬렉션을 생성하고, 인덱스를 생성하고, 일부 샘플 데이터를 인덱싱합니다.

필요한 종속성을 설치하려면 다음 명령을 실행합니다.

npm i aws-sdk npm i aws4 npm i @opensearch-project/opensearch

스크립트 내에서 Principal 요소를 요청에 서명하는 사용자 또는 역할의 Amazon 리소스 이름(ARN)으로 바꿉니다. 선택적으로 region을 수정할 수도 있습니다.

var AWS = require('aws-sdk'); var aws4 = require('aws4'); var { Client, Connection } = require("@opensearch-project/opensearch"); var { OpenSearchServerlessClient, CreateSecurityPolicyCommand, CreateAccessPolicyCommand, CreateCollectionCommand, BatchGetCollectionCommand } = require("@aws-sdk/client-opensearchserverless"); var client = new OpenSearchServerlessClient(); async function execute() { await createEncryptionPolicy(client) await createNetworkPolicy(client) await createAccessPolicy(client) await createCollection(client) await waitForCollectionCreation(client) } async function createEncryptionPolicy(client) { // Creates an encryption policy that matches all collections beginning with 'tv-' try { var command = new CreateSecurityPolicyCommand({ description: 'Encryption policy for TV collections', name: 'tv-policy', type: 'encryption', policy: " \ { \ \"Rules\":[ \ { \ \"ResourceType\":\"collection\", \ \"Resource\":[ \ \"collection\/tv-*\" \ ] \ } \ ], \ \"AWSOwnedKey\":true \ }" }); const response = await client.send(command); console.log("Encryption policy created:"); console.log(response['securityPolicyDetail']); } catch (error) { if (error.name === 'ConflictException') { console.log('[ConflictException] The policy name or rules conflict with an existing policy.'); } else console.error(error); }; } async function createNetworkPolicy(client) { // Creates a network policy that matches all collections beginning with 'tv-' try { var command = new CreateSecurityPolicyCommand({ description: 'Network policy for TV collections', name: 'tv-policy', type: 'network', policy: " \ [{ \ \"Description\":\"Public access for television collection\", \ \"Rules\":[ \ { \ \"ResourceType\":\"dashboard\", \ \"Resource\":[\"collection\/tv-*\"] \ }, \ { \ \"ResourceType\":\"collection\", \ \"Resource\":[\"collection\/tv-*\"] \ } \ ], \ \"AllowFromPublic\":true \ }]" }); const response = await client.send(command); console.log("Network policy created:"); console.log(response['securityPolicyDetail']); } catch (error) { if (error.name === 'ConflictException') { console.log('[ConflictException] A network policy with that name already exists.'); } else console.error(error); }; } async function createAccessPolicy(client) { // Creates a data access policy that matches all collections beginning with 'tv-' try { var command = new CreateAccessPolicyCommand({ description: 'Data access policy for TV collections', name: 'tv-policy', type: 'data', policy: " \ [{ \ \"Rules\":[ \ { \ \"Resource\":[ \ \"index\/tv-*\/*\" \ ], \ \"Permission\":[ \ \"aoss:CreateIndex\", \ \"aoss:DeleteIndex\", \ \"aoss:UpdateIndex\", \ \"aoss:DescribeIndex\", \ \"aoss:ReadDocument\", \ \"aoss:WriteDocument\" \ ], \ \"ResourceType\": \"index\" \ }, \ { \ \"Resource\":[ \ \"collection\/tv-*\" \ ], \ \"Permission\":[ \ \"aoss:CreateCollectionItems\" \ ], \ \"ResourceType\": \"collection\" \ } \ ], \ \"Principal\":[ \ \"arn:aws:iam::123456789012:role\/Admin\" \ ] \ }]" }); const response = await client.send(command); console.log("Access policy created:"); console.log(response['accessPolicyDetail']); } catch (error) { if (error.name === 'ConflictException') { console.log('[ConflictException] An access policy with that name already exists.'); } else console.error(error); }; } async function createCollection(client) { // Creates a collection to hold TV sitcoms indexes try { var command = new CreateCollectionCommand({ name: 'tv-sitcoms', type: 'SEARCH' }); const response = await client.send(command); return (response) } catch (error) { if (error.name === 'ConflictException') { console.log('[ConflictException] A collection with this name already exists. Try another name.'); } else console.error(error); }; } async function waitForCollectionCreation(client) { // Waits for the collection to become active try { var command = new BatchGetCollectionCommand({ names: ['tv-sitcoms'] }); var response = await client.send(command); while (response.collectionDetails[0]['status'] == 'CREATING') { console.log('Creating collection...') await sleep(30000) // Wait for 30 seconds, then check the status again function sleep(ms) { return new Promise((resolve) => { setTimeout(resolve, ms); }); } var response = await client.send(command); } console.log('Collection successfully created:'); console.log(response['collectionDetails']); // Extract the collection endpoint from the response var host = (response.collectionDetails[0]['collectionEndpoint']) // Pass collection endpoint to index document request indexDocument(host) } catch (error) { console.error(error); }; } async function indexDocument(host) { var client = new Client({ node: host, Connection: class extends Connection { buildRequestObject(params) { var request = super.buildRequestObject(params) request.service = 'aoss'; request.region = 'us-east-1'; // e.g. us-east-1 var body = request.body; request.body = undefined; delete request.headers['content-length']; request.headers['x-amz-content-sha256'] = 'UNSIGNED-PAYLOAD'; request = aws4.sign(request, AWS.config.credentials); request.body = body; return request } } }); // Create an index try { var index_name = "sitcoms-eighties"; var response = await client.indices.create({ index: index_name }); console.log("Creating index:"); console.log(response.body); // Add a document to the index var document = "{ \"title\": \"Seinfeld\", \"creator\": \"Larry David\", \"year\": \"1989\" }\n"; var response = await client.index({ index: index_name, body: document }); console.log("Adding document:"); console.log(response.body); } catch (error) { console.error(error); }; } execute()