Assinar solicitações de HTTP para o Amazon Elasticsearch Service - Amazon Elasticsearch Service

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Assinar solicitações de HTTP para o Amazon Elasticsearch Service

Esta seção inclui exemplos de como enviar solicitações HTTP assinadas para o Amazon Elasticsearch Service usando clientes do Elasticsearch e outras bibliotecas comuns. Estas amostras de código destinam-se a interagir com o Elasticsearch tais como _index, _bulk, e _snapshot. Se a sua política de acesso ao domínio incluir utilizadores ou funções de IAM (ou utilizar um utilizador mestre do IAM com controlo de acesso fino), tem de assinar pedidos para Elasticsearch API com as suas credenciais IAM.

Importante

Para obter exemplos de como interagir com a API de configuração, incluindo operações como criar, atualizar e excluir domínios do Amazon ES, consulte Usar os SDKs da AWS com o Amazon Elasticsearch Service.

Tópicos

Java

A maneira mais fácil de enviar uma solicitação assinada é usando o Interceptador de solicitação assinada da AWS. O repositório contém alguns exemplos para ajudá-lo a começar, ou você pode fazer download de um exemplo de projeto para o Amazon ES no GitHub.

O exemplo a seguir usa o cliente Java REST de baixo nível do Elasticsearch para realizar duas ações não relacionadas: registrar um repositório de snapshots e indexar um documento. Você deve fornecer valores para region e host.

import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.HttpRequestInterceptor; import org.apache.http.entity.ContentType; import org.apache.http.nio.entity.NStringEntity; import org.elasticsearch.client.Request; import org.elasticsearch.client.Response; import org.elasticsearch.client.RestClient; import com.amazonaws.auth.AWS4Signer; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; import com.amazonaws.http.AWSRequestSigningApacheInterceptor; import java.io.IOException; public class AmazonElasticsearchServiceSample { private static String serviceName = "es"; private static String region = "us-west-1"; private static String aesEndpoint = "https://domain.us-west-1.es.amazonaws.com"; private static String payload = "{ \"type\": \"s3\", \"settings\": { \"bucket\": \"your-bucket\", \"region\": \"us-west-1\", \"role_arn\": \"arn:aws:iam::123456789012:role/TheServiceRole\" } }"; private static String snapshotPath = "/_snapshot/my-snapshot-repo"; private static String sampleDocument = "{" + "\"title\":\"Walk the Line\"," + "\"director\":\"James Mangold\"," + "\"year\":\"2005\"}"; private static String indexingPath = "/my-index/_doc"; static final AWSCredentialsProvider credentialsProvider = new DefaultAWSCredentialsProviderChain(); public static void main(String[] args) throws IOException { RestClient esClient = esClient(serviceName, region); // Register a snapshot repository HttpEntity entity = new NStringEntity(payload, ContentType.APPLICATION_JSON); Request request = new Request("PUT", snapshotPath); request.setEntity(entity); // request.addParameter(name, value); // optional parameters Response response = esClient.performRequest(request); System.out.println(response.toString()); // Index a document entity = new NStringEntity(sampleDocument, ContentType.APPLICATION_JSON); String id = "1"; request = new Request("PUT", indexingPath + "/" + id); request.setEntity(entity); // Using a String instead of an HttpEntity sets Content-Type to application/json automatically. // request.setJsonEntity(sampleDocument); response = esClient.performRequest(request); System.out.println(response.toString()); } // Adds the interceptor to the ES REST client public static RestClient esClient(String serviceName, String region) { AWS4Signer signer = new AWS4Signer(); signer.setServiceName(serviceName); signer.setRegionName(region); HttpRequestInterceptor interceptor = new AWSRequestSigningApacheInterceptor(serviceName, signer, credentialsProvider); return RestClient.builder(HttpHost.create(aesEndpoint)).setHttpClientConfigCallback(hacb -> hacb.addInterceptorLast(interceptor)).build(); } }

Se você preferir o cliente REST de alto nível, que oferece ma maioria dos mesmos recursos e um código mais simples, tente usar o exemplo a seguir, que também usa o Interceptador de solicitação assinada da AWS:

import org.apache.http.HttpHost; import org.apache.http.HttpRequestInterceptor; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestHighLevelClient; import com.amazonaws.auth.AWS4Signer; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; import com.amazonaws.http.AWSRequestSigningApacheInterceptor; import java.io.IOException; import java.util.HashMap; import java.util.Map; public class AmazonElasticsearchServiceSample { private static String serviceName = "es"; private static String region = "us-west-1"; private static String aesEndpoint = ""; // e.g. https://search-mydomain.us-west-1.es.amazonaws.com private static String index = "my-index"; private static String type = "_doc"; private static String id = "1"; static final AWSCredentialsProvider credentialsProvider = new DefaultAWSCredentialsProviderChain(); public static void main(String[] args) throws IOException { RestHighLevelClient esClient = esClient(serviceName, region); // Create the document as a hash map Map<String, Object> document = new HashMap<>(); document.put("title", "Walk the Line"); document.put("director", "James Mangold"); document.put("year", "2005"); // Form the indexing request, send it, and print the response IndexRequest request = new IndexRequest(index, type, id).source(document); IndexResponse response = esClient.index(request, RequestOptions.DEFAULT); System.out.println(response.toString()); } // Adds the interceptor to the ES REST client public static RestHighLevelClient esClient(String serviceName, String region) { AWS4Signer signer = new AWS4Signer(); signer.setServiceName(serviceName); signer.setRegionName(region); HttpRequestInterceptor interceptor = new AWSRequestSigningApacheInterceptor(serviceName, signer, credentialsProvider); return new RestHighLevelClient(RestClient.builder(HttpHost.create(aesEndpoint)).setHttpClientConfigCallback(hacb -> hacb.addInterceptorLast(interceptor))); } }
dica

Os dois exemplos assinados usam a cadeia de credenciais padrão. Execute aws configure usando a AWS CLI para definir suas credenciais.

Python

É possível instalar o elasticsearch-py, um cliente Elasticsearch para Python, usando o pip. Em vez do cliente, você pode optar por solicitações. Os pacotes requests-aws4auth e SDK para Python (Boto3) simplificam o processo de autenticação, mas não são estritamente necessários. No terminal, execute os comandos a seguir:

pip install boto3 pip install elasticsearch pip install requests pip install requests-aws4auth

O código de exemplo a seguir estabelece uma conexão segura com o domínio do Amazon ES especificado e indexa um único documento. Você deve fornecer valores para region e host.

from elasticsearch import Elasticsearch, RequestsHttpConnection from requests_aws4auth import AWS4Auth import boto3 host = '' # For example, my-test-domain.us-east-1.es.amazonaws.com region = '' # e.g. us-west-1 service = 'es' credentials = boto3.Session().get_credentials() awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, region, service, session_token=credentials.token) es = Elasticsearch( hosts = [{'host': host, 'port': 443}], http_auth = awsauth, use_ssl = True, verify_certs = True, connection_class = RequestsHttpConnection ) document = { "title": "Moneyball", "director": "Bennett Miller", "year": "2011" } es.index(index="movies", doc_type="_doc", id="5", body=document) print(es.get(index="movies", doc_type="_doc", id="5"))

Se você não deseja usar o elasticsearch-py, pode apenas fazer solicitações de HTTP padrão. Esta amostra cria um novo índice com sete estilhaços e duas réplicas:

from requests_aws4auth import AWS4Auth import boto3 import requests host = '' # The domain with https:// and trailing slash. For example, https://my-test-domain.us-east-1.es.amazonaws.com/ path = 'my-index' # the Elasticsearch API endpoint region = '' # For example, us-west-1 service = 'es' credentials = boto3.Session().get_credentials() awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, region, service, session_token=credentials.token) url = host + path # The JSON body to accompany the request (if necessary) payload = { "settings" : { "number_of_shards" : 7, "number_of_replicas" : 2 } } r = requests.put(url, auth=awsauth, json=payload) # requests.get, post, and delete have similar syntax print(r.text)

O próximo exemplo usa a biblioteca Beautiful Soup para ajudar a criar um arquivo em massa de um diretório local de arquivos HTML. Usando o mesmo cliente do primeiro exemplo, você pode enviar o arquivo para a API _bulk para indexação. Você pode usar esse código como base para adicionar a funcionalidade de pesquisa em um site:

from bs4 import BeautifulSoup from elasticsearch import Elasticsearch, RequestsHttpConnection from requests_aws4auth import AWS4Auth import boto3 import glob import json bulk_file = '' id = 1 # This loop iterates through all HTML files in the current directory and # indexes two things: the contents of the first h1 tag and all other text. for html_file in glob.glob('*.htm'): with open(html_file) as f: soup = BeautifulSoup(f, 'html.parser') title = soup.h1.string body = soup.get_text(" ", strip=True) # If get_text() is too noisy, you can do further processing on the string. index = { 'title': title, 'body': body, 'link': html_file } # If running this script on a website, you probably need to prepend the URL and path to html_file. # The action_and_metadata portion of the bulk file bulk_file += '{ "index" : { "_index" : "site", "_type" : "_doc", "_id" : "' + str(id) + '" } }\n' # The optional_document portion of the bulk file bulk_file += json.dumps(index) + '\n' id += 1 host = '' # For example, my-test-domain.us-east-1.es.amazonaws.com region = '' # e.g. us-west-1 service = 'es' credentials = boto3.Session().get_credentials() awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, region, service) es = Elasticsearch( hosts = [{'host': host, 'port': 443}], http_auth = awsauth, use_ssl = True, verify_certs = True, connection_class = RequestsHttpConnection ) es.bulk(bulk_file) print(es.search(q='some test query'))

Ruby

O primeiro exemplo usa o cliente do Ruby do Elasticsearch e o middleware Faraday para realizar a assinatura da solicitação. No terminal, execute os comandos a seguir:

gem install elasticsearch gem install faraday_middleware-aws-sigv4

Este código de exemplo cria um novo cliente do Elasticsearch, configura o middleware Faraday para assinar solicitações e indexa um único documento. Você deve fornecer valores para full_url_and_port e region.

require 'elasticsearch' require 'faraday_middleware/aws_sigv4' full_url_and_port = '' # e.g. https://my-domain.region.es.amazonaws.com:443 index = 'ruby-index' type = '_doc' id = '1' document = { year: 2007, title: '5 Centimeters per Second', info: { plot: 'Told in three interconnected segments, we follow a young man named Takaki through his life.', rating: 7.7 } } region = '' # e.g. us-west-1 service = 'es' client = Elasticsearch::Client.new(url: full_url_and_port) do |f| f.request :aws_sigv4, service: service, region: region, access_key_id: ENV['AWS_ACCESS_KEY_ID'], secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'], session_token: ENV['AWS_SESSION_TOKEN'] # optional end puts client.index index: index, type: type, id: id, body: document

Se as credenciais não funcionarem, exporte-as no terminal usando os seguintes comandos:

export AWS_ACCESS_KEY_ID="your-access-key" export AWS_SECRET_ACCESS_KEY="your-secret-key" export AWS_SESSION_TOKEN="your-session-token"

O próximo exemplo usa o AWS SDK para Ruby e as bibliotecas do Ruby padrão para enviar uma solicitação HTTP assinada. Assim como o primeiro exemplo, ele indexa um único documento. Você deve fornecer valores para host e região.

require 'aws-sdk-elasticsearchservice' host = '' # e.g. https://my-domain.region.es.amazonaws.com index = 'ruby-index' type = '_doc' id = '2' document = { year: 2007, title: '5 Centimeters per Second', info: { plot: 'Told in three interconnected segments, we follow a young man named Takaki through his life.', rating: 7.7 } } service = 'es' region = '' # e.g. us-west-1 signer = Aws::Sigv4::Signer.new( service: service, region: region, access_key_id: ENV['AWS_ACCESS_KEY_ID'], secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'], session_token: ENV['AWS_SESSION_TOKEN'] ) signature = signer.sign_request( http_method: 'PUT', url: host + '/' + index + '/' + type + '/' + id, body: document.to_json ) uri = URI(host + '/' + index + '/' + type + '/' + id) Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http| request = Net::HTTP::Put.new uri request.body = document.to_json request['Host'] = signature.headers['host'] request['X-Amz-Date'] = signature.headers['x-amz-date'] request['X-Amz-Security-Token'] = signature.headers['x-amz-security-token'] request['X-Amz-Content-Sha256']= signature.headers['x-amz-content-sha256'] request['Authorization'] = signature.headers['authorization'] request['Content-Type'] = 'application/json' response = http.request request puts response.body end

Node

Este exemplo usa o SDK para JavaScript no Node.js. No terminal, execute os comandos a seguir:

npm install aws-sdk

Este código de exemplo indexa um único documento. Você deve fornecer valores para region e domain.

var AWS = require('aws-sdk'); var region = ''; // e.g. us-west-1 var domain = ''; // e.g. search-domain.region.es.amazonaws.com var index = 'node-test'; var type = '_doc'; var id = '1'; var json = { "title": "Moneyball", "director": "Bennett Miller", "year": "2011" } indexDocument(json); function indexDocument(document) { var endpoint = new AWS.Endpoint(domain); var request = new AWS.HttpRequest(endpoint, region); request.method = 'PUT'; request.path += index + '/' + type + '/' + id; request.body = JSON.stringify(document); request.headers['host'] = domain; request.headers['Content-Type'] = 'application/json'; // Content-Length is only needed for DELETE requests that include a request // body, but including it for all requests doesn't seem to hurt anything. request.headers['Content-Length'] = Buffer.byteLength(request.body); var credentials = new AWS.EnvironmentCredentials('AWS'); var signer = new AWS.Signers.V4(request, 'es'); signer.addAuthorization(credentials, new Date()); var client = new AWS.HttpClient(); client.handleRequest(request, null, function(response) { console.log(response.statusCode + ' ' + response.statusMessage); var responseBody = ''; response.on('data', function (chunk) { responseBody += chunk; }); response.on('end', function (chunk) { console.log('Response body: ' + responseBody); }); }, function(error) { console.log('Error: ' + error); }); }

Se as credenciais não funcionarem, exporte-as no terminal usando os seguintes comandos:

export AWS_ACCESS_KEY_ID="your-access-key" export AWS_SECRET_ACCESS_KEY="your-secret-key" export AWS_SESSION_TOKEN="your-session-token"

Go

Este exemplo usa o AWS SDK para Go e indexa um único documento. Você deve fornecer valores para domain e region.

package main import ( "fmt" "net/http" "strings" "time" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/signer/v4" ) func main() { // Basic information for the Amazon Elasticsearch Service domain domain := "" // e.g. https://my-domain.region.es.amazonaws.com index := "my-index" id := "1" endpoint := domain + "/" + index + "/" + "_doc" + "/" + id region := "" // e.g. us-east-1 service := "es" // Sample JSON document to be included as the request body json := `{ "title": "Thor: Ragnarok", "director": "Taika Waititi", "year": "2017" }` body := strings.NewReader(json) // Get credentials from environment variables and create the AWS Signature Version 4 signer credentials := credentials.NewEnvCredentials() signer := v4.NewSigner(credentials) // An HTTP client for sending the request client := &http.Client{} // Form the HTTP request req, err := http.NewRequest(http.MethodPut, endpoint, body) if err != nil { fmt.Print(err) } // You can probably infer Content-Type programmatically, but here, we just say that it's JSON req.Header.Add("Content-Type", "application/json") // Sign the request, send it, and print the response signer.Sign(req, body, service, region, time.Now()) resp, err := client.Do(req) if err != nil { fmt.Print(err) } fmt.Print(resp.Status + "\n") }

Se as credenciais não funcionarem, exporte-as no terminal usando os seguintes comandos:

export AWS_ACCESS_KEY_ID="your-access-key" export AWS_SECRET_ACCESS_KEY="your-secret-key" export AWS_SESSION_TOKEN="your-session-token"