D AWS api授权无效

时间:2015-10-10 23:51:35

标签: api amazon-web-services d

我正在尝试使用D编写的程序连接到AWS API。我正在使用vibe-aws module

通过小修改(删除vibe.d依赖关系,通过复制粘贴错过了2个函数),所有单元测试都通过了。最重要的是,我写了这个程序:

#!/usr/bin/rdmd -L-lcurl

import std.stdio;
import std.string;
import std.file;
import std.datetime;
import std.process;
import std.digest.sha;
import std.net.curl;
import std.uri;
import sigv4;


auto zone = "us-east-1";
auto service = "ec2";


void main()
{
    auto accKey = environment["AWS_ACCESS_KEY"];
    auto secKey = environment["AWS_SECRET_KEY"];

    auto currentClock = Clock.currTime(UTC());
    writeln(currentClock);
    auto currentDate = cast(Date)currentClock;
    auto curDateStr = currentDate.toISOString;

    writeln(curDateStr);

    auto currentTime = cast(TimeOfDay)currentClock;
    auto curTimeStr = currentTime.toISOString;

    writeln(curTimeStr);

    auto xamztime = curDateStr ~ "T" ~ curTimeStr ~ "Z";

    string[string] empty;

    SignableRequest r;
    r.dateString = curDateStr;
    r.timeStringUTC = curTimeStr;
    r.region = zone;
    r.service = service;
    r.canonicalRequest = CanonicalRequest(
                    "GET",
                    "/",
                    ["action" : "DescribeInstances", "version" : "2013-10-15"],
                    ["content-type" : "application/x-www-form-urlencoded; charset=utf-8",
                     "host" : service ~ ".amazonaws.com",
                     "x-amz-date" : xamztime],
                    cast(ubyte[])"");    




    writeln(signableString(r));

    auto qParm = canonicalQueryString(r.canonicalRequest.queryParameters);

    auto sigHead = canonicalHeaders(r.canonicalRequest.headers);

    auto sigStr = signableString(r);

    auto sigKey = signingKey(secKey, curDateStr, zone, service);

    auto signature = sign(sigKey, cast(ubyte[])sigStr).toHexString().toLower();

    writeln();  
    writeln(qParm);
    writeln();
    writeln(sigHead);
    writeln();
    writeln(sigStr);
    writeln();
    writeln(sigKey);
    writeln(signature);
    writeln();
    auto client = HTTP(service ~ ".amazonaws.com/?" ~ "Action=DescribeInstances&Version=2013-10-15");
    client.method = HTTP.Method.get;
    client.clearRequestHeaders;
    client.addRequestHeader("content-type", "application/x-www-form-urlencoded; charset=utf-8");
    client.addRequestHeader("host", service ~ ".amazonaws.com");
    client.addRequestHeader("x-amz-date", xamztime);
    client.addRequestHeader("authorization", "AWS4-HMAC-SHA256" ~ " " ~ "Credential=" ~ accKey ~ "/" ~ xamztime ~ "/" ~ zone ~ "/" ~ service ~ "/" ~ "aws4_request" ~ ", " ~ "SignedHeaders=" ~ "content-type;host;x-amz-date" ~ ", " ~ "Signature=" ~ signature);
    auto content = client.perform();
    writeln(content);
}

以下是我得到的输出:

./header.d 
2015-Oct-11 16:54:01.208441Z
20151011
165401
AWS4-HMAC-SHA256
20151011T165401Z
20151011/us-east-1/ec2/aws4_request
f053e1901b164a712ed6c8384754673822d609da696b5d15799304835b3870ea

action=DescribeInstances&version=2013-10-15

content-type:application/x-www-form-urlencoded; charset=utf-8
host:ec2.amazonaws.com
x-amz-date:20151011T165401Z


AWS4-HMAC-SHA256
20151011T165401Z
20151011/us-east-1/ec2/aws4_request
f053e1901b164a712ed6c8384754673822d609da696b5d15799304835b3870ea

[116, 194, 23, 247, 184, 145, 90, 14, 192, 208, 97, 210, 77, 165, 201, 250, 6, 121, 49, 208, 142, 197, 33, 93, 204, 139, 11, 29, 227, 218, 107, 240]
57fdf77b44f2d14fa688b42bc88250a6ad2e6596964a6d40037333240ca15608

<?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>2cf1443d-11b9-4a16-92e7-bf30c61e550b</RequestID></Response>0

1 个答案:

答案 0 :(得分:0)

在与之前的代码长期斗争之后,我尝试重写&#34;一对一&#34;从http://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html(GET部分)的蟒蛇示例,从乞讨到D并取得圆满成功。这是使用hmac函数的清晰D. Im的工作代码,可以从2.069的phobos获得。它不是太漂亮,但我是初学者,这里是:

#!/usr/bin/rdmd -L-lcurl

module sigawsv4;

import std.stdio, std.process;
import std.digest.sha, std.digest.hmac;
import std.string;
import std.conv;
import std.datetime;
import std.net.curl;

void main()
{
    auto accessKey = environment["AWS_ACCESS_KEY"];
    auto secretKey = environment["AWS_SECRET_KEY"];

    auto currentClock = Clock.currTime(UTC());

    auto currentDate = cast(Date)currentClock;
    auto curDateStr = currentDate.toISOString;

    auto currentTime = cast(TimeOfDay)currentClock;
    auto curTimeStr = currentTime.toISOString;

    auto xamztime = curDateStr ~ "T" ~ curTimeStr ~ "Z";


    string method = "GET";
    string service = "ec2";
    string host = "ec2.amazonaws.com";
    string region = "us-east-1";
    string endpoint = "https://ec2.amazonaws.com";
    string request_parameters = "Action=DescribeInstances&Version=2013-10-15";


    auto hmac_sha256(ubyte[] key, ubyte[] msg)
    {
        auto hmac = hmac!SHA256(key);
        hmac.put(msg);
        auto digest = hmac.finish;

        return digest;
    }

    alias sign = hmac_sha256;

    auto getSignatureKey(string key, string dateStamp, string regionName, string serviceName)
    {
        ubyte[] kString = cast(ubyte[])("AWS4" ~ key);
        auto kDate = sign(kString, cast(ubyte[])dateStamp);
        auto kRegion = sign(kDate, cast(ubyte[])regionName);
        auto kService = sign(kRegion,  cast(ubyte[])serviceName);
        auto kSigning = sign(kService, cast(ubyte[])"aws4_request");

        return kSigning;
    }


    string canonicalURI = "/";
    string canonicalQueryString = request_parameters;
    string canonicalHeadersString =  "host:" ~ host ~ "\n" ~ "x-amz-date:" ~ xamztime ~ "\n";
    string signedHeaders = "host;x-amz-date";
    string payloadHash = sha256Of("").toHexString.toLower;
    string canonicalRequest = method ~ "\n" ~ canonicalURI ~ "\n" ~ canonicalQueryString ~ "\n" ~ canonicalHeadersString ~ "\n" ~ signedHeaders ~ "\n" ~ payloadHash;


    string algorithm = "AWS4-HMAC-SHA256";
    string credentialScope = curDateStr ~ "/" ~ region ~ "/" ~ service ~ "/" ~ "aws4_request";
    string stringToSign = algorithm ~ "\n" ~ xamztime ~ "\n" ~ credentialScope ~ "\n" ~ sha256Of(canonicalRequest).toHexString.toLower;

    auto signingKey = getSignatureKey(secretKey, curDateStr, region, service);

    string signature = hmac_sha256(signingKey, cast(ubyte[])stringToSign).toHexString.toLower;

    string authorizationHeader = algorithm ~ " " ~ "Credential=" ~ accessKey ~ "/" ~ credentialScope ~ ", " ~ "SignedHeaders=" ~ signedHeaders ~ ", " ~ "Signature=" ~ signature;

    auto client = HTTP(endpoint ~ "?" ~ canonicalQueryString);
    client.method = HTTP.Method.get;
    client.addRequestHeader("x-amz-date", xamztime);
    client.addRequestHeader("Authorization", authorizationHeader);
    auto content = client.perform();

    writeln(content);
}