2012-11-16 16 views
5

Desidero utilizzare il pacchetto R httr per accedere ai servizi EC2 tramite la loro API. Ma sono un po 'insicuro su come iniziare, dato che non rientra nel solito formato di autenticazione di "Oauth2.0" in cui si hanno i soliti: chiave, sistema segreto, token e firma. Penso che EC2 usi il metodo "signature signature 2", ma non sono chiaro su come funzioni.Problemi di autenticazione R + httr ed EC2 api

Guardando la documentazione EC2 offre per quanto riguarda rendendo richieste di query al http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/using-query-api.html

Penso di aver bisogno il valore per la firma .... ma non so come ottenerlo

ho provato a usare alcuni dei comandi dati usando httr come mostrato sotto. Posso adattare la maggior parte dei parametri nella stringa dell'URL per rappresentare me e le cose che voglio fare, ad esempio AWSAccessKeyId, ImageId, endpoint e Action ecc., Ma non so esattamente dove andare per ottenere il valore della firma.

anche in alcuni degli esempi riportati, essi non sembrano fornire la chiave di accesso segreta o ...

Così i comandi provati sono i seguenti aver modificato alcuni dei valori per rappresentare me, ma ha ottenuto la seguente:

require(httr) 
GET("https://ec2.amazonaws.com/ 
?Action=RunInstances 
&ImageId=ami-60a54009 
&MaxCount=3 
&MinCount=1 
&Placement.AvailabilityZone=us-east-1b 
&Monitoring.Enabled=true 
&AWSAccessKeyId=0GS7553JW74RRM612K02EXAMPLE 
&Version=2012-10-01 
&Expires=2010-10-10T12:00:00Z 
&Signature=lBP67vCvGlDMBQ1dofZxg8E8SUEXAMPLE 
&SignatureVersion=2 
&SignatureMethod=HmacSHA256") 

a cui ho la risposta:

Response [http://aws.amazon.com/ec2/] 
    Status: 200 
    Content-type: text/html; charset=UTF-8 


    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 
<html> 

<head> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
    <link rel="icon" type="image/ico" href="//d36cz9buwru1tt.cloudfront.net/favicon.ico"> 
    <link rel="shortcut icon" type="image/ico" href="//d36cz9buwru1tt.cloudfront.net/favicon.ico"> 
    <meta name="description" content="Amazon Elastic Compute Cloud delivers scalable, pay-as-you-go compute capacity in the cloud. " /><meta name="keywords" content="" /> ... 

qualcuno ha avuto esperienza con l'API EC2 e la sua procedura di autenticazione e sarebbe b E abbastanza facile usare R per essere in grado di configurare ed eseguire istanze linux con AMI scelte da me (che hanno R e altri pacchetti rilevanti caricati su di esso), quindi eseguire alcuni comandi R in tali istanze e riportare l'output?

Non pensare la sua davvero legata alla mia sessionInfo, ma solo nel caso in qui è:

sessionInfo() 
R version 2.15.1 (2012-06-22) 
Platform: x86_64-apple-darwin9.8.0/x86_64 (64-bit) 

locale: 
[1] en_GB.UTF-8/en_GB.UTF-8/en_GB.UTF-8/C/en_GB.UTF-8/en_GB.UTF-8 

attached base packages: 
[1] stats  graphics grDevices utils  datasets methods base  

other attached packages: 
[1] httr_0.2 

loaded via a namespace (and not attached): 
[1] digest_0.5.2 plyr_1.7.1  RCurl_1.95-1.1 stringr_0.6.1 tools_2.15.1 

EDIT:

Quindi, in un ulteriore tentativo di seguire la documentazione come suggerito da @ Hadley questo è quello che ho provato e ho ... ogni più utili suggerimenti su dove im andando male sarebbe molto apprezzato ...:

require(httr) 

aws.key <- "xxxxxxx" 
aws.secret <- "xxxxxxxxxxxx" 

verb <- "GET" 
zone <- "ec2.amazonaws.com" 
func <- "DescribeImages" 

ami.number <- "ami-xxxxxxxxx" 

params <- list(paste0("ImageId.1=",ami.number), 
    "Version=2012-10-01", 
    "Expires=2012-11-20T12%3A00%3A00Z") 


# adding in method and key parameters for creation of string to sign 
orig.len.params <- length(params) 
params.w.method.key <- params 
params.w.method.key[[orig.len.params+1]] <- "SignatureVersion=2" 
params.w.method.key[[orig.len.params+2]] <- "SignatureMethod=HmacSHA1" 
params.w.method.key[[orig.len.params+3]] <- paste0("AWSAccessKeyId=",aws.key) 

# String to sign (s2s) 
s2s <- paste(c(paste0(verb,"\n",zone,"\n","/\n","AWSAccessKeyId=",aws.key),paste0("Action=",func),paste(sort(unlist(params.w.method.key)),collapse="&")),collapse="&") 

# Signature(sig) 
sig <- hmac_sha1(aws.secret, s2s) 

# adding in signature, method and key parameters for signed request url generation 
params.w.sig.method.key <- params 
params.w.sig.method.key[[orig.len.params+1]] <- paste0("Signature=",sig) 
params.w.sig.method.key[[orig.len.params+2]] <- "SignatureVersion=2" 
params.w.sig.method.key[[orig.len.params+3]] <- "SignatureMethod=HmacSHA1" 
params.w.sig.method.key[[orig.len.params+4]] <- paste0("AWSAccessKeyId=",aws.key) 

# Signed request (sr) 
sr <- paste(c(paste0("https://",zone,paste0("?Action=",func)),paste(unlist(params.w.sig.method.key),collapse="&")),collapse="&") 

# GET signed request 
GET(sr) 

a cui ottengo la risposta:

Response [https://ec2.amazonaws.com?Action=DescribeImages&ImageId.1=[ami.number.from.before]&Version=2012-10-01&Expires=2012-11-20T12%3A00%3A00Z&Signature=[sig.value.from.before]&SignatureVersion=2&SignatureMethod=HmacSHA1&AWSAccessKeyId=[aws.key.from.before]/] 
    Status: 401 
    Content-type: 
<?xml version="1.0" encoding="UTF-8"?> 
<Response><Errors><Error><Code>AuthFailure</Code><Message>AWS was not able to validate the provided access credentials</Message></Error></Errors><RequestID>5e10fb0b-f304-4677-9c64-98b4537c659a</RequestID></Response> 
+0

L'algoritmo di base per la generazione della firma è disposto in http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/using-query-api.html#query-authentication - 'httr' ha la Funzione 'hmac' per il passaggio 3. – hadley

+0

grazie ... l'ho visto ma non ero sicuro di aver capito cosa significasse ... c'è una possibilità che potresti fornire un esempio? –

+0

o potenzialmente vedere dove sto andando male date le mie modifiche? Penso che stia vicino ... –

risposta

6

Ecco il mio tentativo di conversione graduale dell'algoritmo in codice R. Nella mia esperienza, voglio davvero fare ogni passo separatamente in modo da poter verificare in ogni fase che i risultati siano corretti.

require("httr") 
require("RCurl") 
require("stringr") 

# 0: get key and secret from envvars, and set up request parameters 

aws.key <- Sys.getenv("AWS_KEY") 
aws.secret <- Sys.getenv("AWS_SECRET_KEY") 

verb <- "GET" 
zone <- "ec2.amazonaws.com" 

ami.number <- "ami-xxxxxxxxx" 

params <- list(
    Action = "DescribeImages", 
    ImageId.1 = ami.number, 
    Version = "2012-10-01", 
    Expires = "2012-11-20T12:00:00Z", 
    SignatureVersion = 2, 
    SignatureMethod = "HmacSHA1", 
    AWSAccessKeyId = aws.key) 

# 1a: Sort the UTF-8 query string components by parameter name 
params <- params[order(names(params))] 

# 1b: URL encode the parameter name and values 
params_e <- lapply(params, curlEscape) 
names(params_e) <- curlEscape(names(params_e)) 
params_str <- str_c(names(params_e), "=", unlist(params_e), collapse = "&") 
params_str <- gsub("%2E",".",gsub("%2D","-",params_str)) 

# 2: Create the string to sign 
string_to_sign <- str_c(
    toupper(verb), "\n", 
    tolower(zone), "\n", 
    "/", "\n", 
    params_str 
) 

# 3: Calculate an RFC 2104-compliant HMAC 
# 4: Convert the resulting value to base64. 
hmac <- hmac_sha1(aws.secret, string_to_sign) 

params$Signature <- hmac 

GET(paste0("https://",zone),query=params) 
+0

scusa forse mi manca qualcosa ma cosa faccio con l'oggetto params?essere in grado di utilizzare la funzione GET da 'httr' –

+0

' GET (url, query = params) ' – hadley

+0

hmm ... sembra ancora ottenere un codice di errore dalla risposta di' GET ("https: //ec2.amazonaws .com ", query = params)', ottenendo: 'SignatureDoesNotMatch La firma della richiesta che abbiamo calcolato non corrisponde alla firma che hai fornito. Controlla la chiave di accesso segreta di AWS e il metodo di firma. Consultare la documentazione del servizio per i dettagli. 'i valori di segreto e accesso sembrano buoni ... –