Python을 사용한 IAM 인증을 사용하여 Amazon Neptune 데이터베이스에 연결 - Amazon Neptune

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

Python을 사용한 IAM 인증을 사용하여 Amazon Neptune 데이터베이스에 연결

이 섹션에서는 Amazon Neptune에서 Signature Version 4로 작업하는 방법을 설명하는 Python으로 작성된 예제 프로그램을 보여줍니다. 이 예제는 Amazon Web Services 일반 참조Signature Version 4 서명 프로세스 섹션에 있는 예제를 기반으로 합니다.

이 예제 프로그램을 사용하려면 다음이 필요합니다.

  • Python 3.x가 컴퓨터에 설치되어 있어야 합니다. 이 버전은 Python 사이트에서 얻을 수 있습니다. 이러한 프로그램은 Python 3.6을 사용하여 테스트했습니다.

  • 예제 스크립트에서 웹 요청을 생성하는 데 사용되는 Python 요청 라이브러리가 필요합니다. Python 패키지를 설치하는 간편한 방법은 Python 패키지 인덱스 사이트에서 패키지를 가져오는 pip를 사용하는 것입니다. 그런 다음 명령줄에서 pip install requests를 실행하여 requests를 설치할 수 있습니다.

  • AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY 환경 변수에 액세스 키(액세스 키 ID 및 보안 액세스 키)가 필요합니다. 자격 증명을 코드에 포함하지 않는 것이 가장 좋은 방법입니다. 자세한 내용을 알아보려면 AWS Account Management 참조 안내서AWS 계정의 모범 사례를 참조하세요.

    SERVICE_REGION 환경 변수에 있는 Neptune DB 클러스터의 리전이 필요합니다.

    임시 자격 증명을 사용하는 경우 AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEYSERVICE_REGION 외에도 AWS_SESSION_TOKEN을 지정해야 합니다.

    참고

    임시 자격 증명을 사용하는 경우 세션 토큰을 포함하여 지정된 간격 후에 만료됩니다.

    새 자격 증명을 요청할 경우 세션 토큰을 업데이트해야 합니다. 자세한 내용은 임시 보안 인증 정보를 사용하여 AWS 리소스 액세스 권한 요청을 참조하세요.

다음 예제는 Python을 사용하여 Neptune에 대한 서명 요청을 생성하는 방법을 설명합니다. 이 요청으로 GET 또는 POST 요청이 생성됩니다. 인증 정보는 Authorization 요청 헤더를 사용하여 전달됩니다.

이 예제는 AWS Lambda 함수로도 작동합니다. 자세한 내용은 Neptune IAM 인증을 위한 AWS Lambda 설정 단원을 참조하십시오.

Gremlin 및 SPARQL Neptune 엔드포인트에 대한 서명된 요청을 생성하려면
  1. 이름이 neptunesigv4.py인 새 파일을 만들어 텍스트 편집기에서 엽니다.

  2. 다음 코드를 복사하여 neptunesigv4.py 파일에 붙여 넣습니다.

    # Amazon Neptune version 4 signing example (version v3) # The following script requires python 3.6+ # (sudo yum install python36 python36-virtualenv python36-pip) # => the reason is that we're using urllib.parse() to manually encode URL # parameters: the problem here is that SIGV4 encoding requires whitespaces # to be encoded as %20 rather than not or using '+', as done by previous/ # default versions of the library. # See: https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html import sys, datetime, hashlib, hmac import requests # pip3 install requests import urllib import os import json from botocore.auth import SigV4Auth from botocore.awsrequest import AWSRequest from botocore.credentials import ReadOnlyCredentials from types import SimpleNamespace from argparse import RawTextHelpFormatter from argparse import ArgumentParser # Configuration. https is required. protocol = 'https' # The following lines enable debugging at httplib level (requests->urllib3->http.client) # You will see the REQUEST, including HEADERS and DATA, and RESPONSE with HEADERS but without DATA. # # The only thing missing will be the response.body which is not logged. # # import logging # from http.client import HTTPConnection # HTTPConnection.debuglevel = 1 # logging.basicConfig() # logging.getLogger().setLevel(logging.DEBUG) # requests_log = logging.getLogger("requests.packages.urllib3") # requests_log.setLevel(logging.DEBUG) # requests_log.propagate = True # Read AWS access key from env. variables. Best practice is NOT # to embed credentials in code. access_key = os.getenv('AWS_ACCESS_KEY_ID', '') secret_key = os.getenv('AWS_SECRET_ACCESS_KEY', '') region = os.getenv('SERVICE_REGION', '') # AWS_SESSION_TOKEN is optional environment variable. Specify a session token only if you are using temporary # security credentials. session_token = os.getenv('AWS_SESSION_TOKEN', '') ### Note same script can be used for AWS Lambda (runtime = python3.6). ## Steps to use this python script for AWS Lambda # 1. AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN and AWS_REGION variables are already part of Lambda's Execution environment # No need to set them up explicitly. # 3. Create Lambda deployment package https://docs.aws.amazon.com/lambda/latest/dg/lambda-python-how-to-create-deployment-package.html # 4. Create a Lambda function in the same VPC and assign an IAM role with neptune access def lambda_handler(event, context): # sample_test_input = { # "host": "END_POINT:8182", # "method": "GET", # "query_type": "gremlin", # "query": "g.V().count()" # } # Lambda uses AWS_REGION instead of SERVICE_REGION global region region = os.getenv('AWS_REGION', '') host = event['host'] method = event['method'] query_type = event['query_type'] query = event['query'] return make_signed_request(host, method, query_type, query) def validate_input(method, query_type): # Supporting GET and POST for now: if (method != 'GET' and method != 'POST'): print('First parameter must be "GET" or "POST", but is "' + method + '".') sys.exit() # SPARQL UPDATE requires POST if (method == 'GET' and query_type == 'sparqlupdate'): print('SPARQL UPDATE is not supported in GET mode. Please choose POST.') sys.exit() def get_canonical_uri_and_payload(query_type, query, method): # Set the stack and payload depending on query_type. if (query_type == 'sparql'): canonical_uri = '/sparql/' payload = {'query': query} elif (query_type == 'sparqlupdate'): canonical_uri = '/sparql/' payload = {'update': query} elif (query_type == 'gremlin'): canonical_uri = '/gremlin/' payload = {'gremlin': query} if (method == 'POST'): payload = json.dumps(payload) elif (query_type == 'openCypher'): canonical_uri = '/openCypher/' payload = {'query': query} elif (query_type == "loader"): canonical_uri = "/loader/" payload = query elif (query_type == "status"): canonical_uri = "/status/" payload = {} elif (query_type == "gremlin/status"): canonical_uri = "/gremlin/status/" payload = {} elif (query_type == "openCypher/status"): canonical_uri = "/openCypher/status/" payload = {} elif (query_type == "sparql/status"): canonical_uri = "/sparql/status/" payload = {} else: print( 'Third parameter should be from ["gremlin", "sparql", "sparqlupdate", "loader", "status] but is "' + query_type + '".') sys.exit() ## return output as tuple return canonical_uri, payload def make_signed_request(host, method, query_type, query): service = 'neptune-db' endpoint = protocol + '://' + host print() print('+++++ USER INPUT +++++') print('host = ' + host) print('method = ' + method) print('query_type = ' + query_type) print('query = ' + query) # validate input validate_input(method, query_type) # get canonical_uri and payload canonical_uri, payload = get_canonical_uri_and_payload(query_type, query, method) # assign payload to data or params data = payload if method == 'POST' else None params = payload if method == 'GET' else None # create request URL request_url = endpoint + canonical_uri # create and sign request creds = SimpleNamespace( access_key=access_key, secret_key=secret_key, token=session_token, region=region, ) request = AWSRequest(method=method, url=request_url, data=data, params=params) SigV4Auth(creds, service, region).add_auth(request) r = None # ************* SEND THE REQUEST ************* if (method == 'GET'): print('++++ BEGIN GET REQUEST +++++') print('Request URL = ' + request_url) r = requests.get(request_url, headers=request.headers, verify=False, params=params) elif (method == 'POST'): print('\n+++++ BEGIN POST REQUEST +++++') print('Request URL = ' + request_url) if (query_type == "loader"): request.headers['Content-type'] = 'application/json' r = requests.post(request_url, headers=request.headers, verify=False, data=data) else: print('Request method is neither "GET" nor "POST", something is wrong here.') if r is not None: print() print('+++++ RESPONSE +++++') print('Response code: %d\n' % r.status_code) response = r.text r.close() print(response) return response help_msg = ''' export AWS_ACCESS_KEY_ID=[MY_ACCESS_KEY_ID] export AWS_SECRET_ACCESS_KEY=[MY_SECRET_ACCESS_KEY] export AWS_SESSION_TOKEN=[MY_AWS_SESSION_TOKEN] export SERVICE_REGION=[us-east-1|us-east-2|us-west-2|eu-west-1] python version >=3.6 is required. Examples: For help python3 program_name.py -h Examples: Queries python3 program_name.py -ho your-neptune-endpoint -p 8182 -a GET -q status python3 program_name.py -ho your-neptune-endpoint -p 8182 -a GET -q sparql/status python3 program_name.py -ho your-neptune-endpoint -p 8182 -a GET -q sparql -d "SELECT ?s WHERE { ?s ?p ?o }" python3 program_name.py -ho your-neptune-endpoint -p 8182 -a POST -q sparql -d "SELECT ?s WHERE { ?s ?p ?o }" python3 program_name.py -ho your-neptune-endpoint -p 8182 -a POST -q sparqlupdate -d "INSERT DATA { <https://s> <https://p> <https://o> }" python3 program_name.py -ho your-neptune-endpoint -p 8182 -a GET -q gremlin/status python3 program_name.py -ho your-neptune-endpoint -p 8182 -a GET -q gremlin -d "g.V().count()" python3 program_name.py -ho your-neptune-endpoint -p 8182 -a POST -q gremlin -d "g.V().count()" python3 program_name.py -ho your-neptune-endpoint -p 8182 -a GET -q openCypher/status python3 program_name.py -ho your-neptune-endpoint -p 8182 -a GET -q openCypher -d "MATCH (n1) RETURN n1 LIMIT 1;" python3 program_name.py -ho your-neptune-endpoint -p 8182 -a POST -q openCypher -d "MATCH (n1) RETURN n1 LIMIT 1;" python3 program_name.py -ho your-neptune-endpoint -p 8182 -a GET -q loader -d '{"loadId": "68b28dcc-8e15-02b1-133d-9bd0557607e6"}' python3 program_name.py -ho your-neptune-endpoint -p 8182 -a GET -q loader -d '{}' python3 program_name.py -ho your-neptune-endpoint -p 8182 -a POST -q loader -d '{"source": "source", "format" : "csv", "failOnError": "fail_on_error", "iamRoleArn": "iam_role_arn", "region": "region"}' Environment variables must be defined as AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and SERVICE_REGION. You should also set AWS_SESSION_TOKEN environment variable if you are using temporary credentials (ex. IAM Role or EC2 Instance profile). Current Limitations: - Query mode "sparqlupdate" requires POST (as per the SPARQL 1.1 protocol) ''' def exit_and_print_help(): print(help_msg) exit() def parse_input_and_query_neptune(): parser = ArgumentParser(description=help_msg, formatter_class=RawTextHelpFormatter) group_host = parser.add_mutually_exclusive_group() group_host.add_argument("-ho", "--host", type=str) group_port = parser.add_mutually_exclusive_group() group_port.add_argument("-p", "--port", type=int, help="port ex. 8182, default=8182", default=8182) group_action = parser.add_mutually_exclusive_group() group_action.add_argument("-a", "--action", type=str, help="http action, default = GET", default="GET") group_endpoint = parser.add_mutually_exclusive_group() group_endpoint.add_argument("-q", "--query_type", type=str, help="query_type, default = status ", default="status") group_data = parser.add_mutually_exclusive_group() group_data.add_argument("-d", "--data", type=str, help="data required for the http action", default="") args = parser.parse_args() print(args) # Read command line parameters host = args.host port = args.port method = args.action query_type = args.query_type query = args.data if (access_key == ''): print('!!! ERROR: Your AWS_ACCESS_KEY_ID environment variable is undefined.') exit_and_print_help() if (secret_key == ''): print('!!! ERROR: Your AWS_SECRET_ACCESS_KEY environment variable is undefined.') exit_and_print_help() if (region == ''): print('!!! ERROR: Your SERVICE_REGION environment variable is undefined.') exit_and_print_help() if host is None: print('!!! ERROR: Neptune DNS is missing') exit_and_print_help() host = host + ":" + str(port) make_signed_request(host, method, query_type, query) if __name__ == "__main__": parse_input_and_query_neptune()
  3. 터미널에서 neptunesigv4.py 파일 위치로 이동합니다.

  4. 다음 명령을 입력하고 액세스 키, 보안 키 및 리전을 올바른 값으로 바꿉니다.

    export AWS_ACCESS_KEY_ID=MY_ACCESS_KEY_ID export AWS_SECRET_ACCESS_KEY=MY_SECRET_ACCESS_KEY export SERVICE_REGION=us-east-1 or us-east-2 or us-west-1 or us-west-2 or ca-central-1 or sa-east-1 or eu-north-1 or eu-west-1 or eu-west-2 or eu-west-3 or eu-central-1 or me-south-1 or me-central-1 or il-central-1 or af-south-1 or ap-east-1 or ap-northeast-1 or ap-northeast-2 or ap-southeast-1 or ap-southeast-2 or ap-south-1 or cn-north-1 or cn-northwest-1 or us-gov-east-1 or us-gov-west-1

    임시 자격 증명을 사용하는 경우 AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEYSERVICE_REGION 외에도 AWS_SESSION_TOKEN을 지정해야 합니다.

    export AWS_SESSION_TOKEN=MY_AWS_SESSION_TOKEN
    참고

    임시 자격 증명을 사용하는 경우 세션 토큰을 포함하여 지정된 간격 후에 만료됩니다.

    새 자격 증명을 요청할 경우 세션 토큰을 업데이트해야 합니다. 자세한 내용은 임시 보안 인증 정보를 사용하여 AWS 리소스 액세스 권한 요청을 참조하세요.

  5. 다음 명령 중 하나를 입력하여 Neptune DB 인스턴스에 서명된 요청을 전송합니다. 이러한 예제에서는 Python 버전 3.6을 사용합니다.

    엔드포인트 상태

    python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a GET -q status

    Gremlin

    python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a GET -q gremlin -d "g.V().count()" python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a POST -q gremlin -d "g.V().count()"

    Gremlin status

    python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a GET -q gremlin/status

    SPARQL

    python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a GET -q sparql -d "SELECT ?s WHERE { ?s ?p ?o }"

    SPARQL 업데이트

    python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a POST -q sparqlupdate -d "INSERT DATA { <https://s> <https://p> <https://o> }"

    SPARQL status

    python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a GET -q sparql/status

    openCypher

    python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a GET -q openCypher -d "MATCH (n1) RETURN n1 LIMIT 1;" python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a POST -q openCypher -d "MATCH (n1) RETURN n1 LIMIT 1;"

    openCypher status

    python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a GET -q openCypher/status

    로더

    python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a GET -q loader -d '{"loadId": "68b28dcc-8e15-02b1-133d-9bd0557607e6"}' python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a GET -q loader -d '{}' python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a POST -q loader -d '{"source": "source", "format" : "csv", "failOnError": "fail_on_error", "iamRoleArn": "iam_role_arn", "region": "region"}'
  6. Python 스크립트 실행 구문은 다음과 같습니다.

    python3.6 neptunesigv4.py -ho your-neptune-endpoint -p port -a GET|POST -q gremlin|sparql|sparqlupdate|loader|status -d "string0data"

    SPARQL UPDATE는 POST가 필요합니다.