【问题标题】:R + httr and EC2 api authentication issuesR + httr 和 EC2 api 身份验证问题
【发布时间】:2012-11-05 15:42:54
【问题描述】:

我想使用 R 包 httr 通过其 API 访问 EC2 服务。但我有点不确定如何开始,因为它不属于通常的“Oauth2.0”身份验证格式,在这种格式中你有通常的:密钥、秘密、令牌和签名系统。我认为 EC2 使用“签名版本 2”方法,但我不清楚它是如何工作的。

查看 EC2 提供的有关在 http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/using-query-api.html 提出查询请求的文档

我想我需要签名的值....但不知道如何获取它

我已经尝试使用httr 来使用一些给定的命令,如下所示。我可以调整 URL 字符串中的大部分参数来代表我和我想做的事情,例如 AWSAccessKeyIdImageIdendpointAction 等......但只是不知道去哪里关于获取签名值。

在给出的一些示例中,它们似乎也没有提供秘密访问密钥......

所以尝试的命令如下,改变了一些代表我的值,但得到了以下内容:

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")

我得到了回应:

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="" /> ...

有人对 EC2 api 及其身份验证过程有任何经验吗?使用 R 来设置和运行带有我选择的 AMI 的 linux 实例是否足够容易(已加载 R 和其他相关软件包) ),然后在这些实例中运行一些 R 命令并返回输出?

不要认为它真的与我的 sessionInfo 相关,但以防万一:

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  

编辑:

因此,在进一步尝试按照@hadley 建议的文档进行操作时,这是我尝试并得到的结果...任何有关我哪里出错的有用提示将不胜感激...:

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)

我得到了回应:

 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> 

【问题讨论】:

  • 生成签名的基本算法在docs.amazonwebservices.com/AWSEC2/latest/UserGuide/… - httr 具有用于步骤3的hmac 函数。
  • 谢谢...我看到了,但不确定我是否理解它的意思...您可以提供一个例子吗?
  • 或者根据我的编辑可能会看到我哪里出错了?我想我很接近...

标签: r amazon-ec2 ec2-ami ec2-api-tools httr


【解决方案1】:

这是我逐步将算法转换为 R 代码的尝试。根据我的经验,您确实希望单独执行每个步骤,以便您可以在每个阶段检查结果是否正确。

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)

【讨论】:

  • 对不起,也许我遗漏了一些东西,但是我该如何处理 params 对象?能够使用来自httr 的 GET 功能
  • hmm...似乎仍然从GET("https://ec2.amazonaws.com", query=params) 的响应中得到错误代码,getting:&lt;Code&gt;SignatureDoesNotMatch&lt;/Code&gt;&lt;Message&gt;The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.&lt;/Message&gt; secret 和 access 的值看起来不错...
  • 是的,诊断问题是一场噩梦。上次我不得不这样做时,我通读了 3 或 4 次规范,然后找到了一个可以拆开检查的 ruby​​ 实现。不幸的是,我现在忙于其他工作,所以无法更详细地研究。
  • 啊!!!最后修复它...您只需在 param_str 下添加params_str &lt;- gsub("%2E",".",gsub("%2D","-",params_str)) 即可使其工作... curlEscape 将连字符 (-) 和句点 (.) 转换为不应该的十六进制...所以它最后被转换回来...将编辑并接受答案...
  • @h.l.m 您可能想编写自己的编码函数 - 请参阅oauth-signature.r 中的oauth_encode1 了解一种方法。
猜你喜欢
  • 2011-01-22
  • 1970-01-01
  • 2014-12-03
  • 1970-01-01
  • 2017-07-14
  • 2019-08-24
  • 2011-01-18
  • 2015-03-28
  • 1970-01-01
相关资源
最近更新 更多