2015-10-10 1 views
1

Я пытаюсь подключиться к AWS API в программе, написанной на D. Я использую vibe-aws module.D AWS авторизация api не работает

С небольшой модификацией (удалена 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

Вы можете проверить результаты вашего кода подписи с примерами, приведенными в подписи V4 тестов: http://docs.aws.amazon.com /general/latest/gr/signature-v4-test-suite.html –

+0

Я не знаю, помогает ли это, но у меня есть разрешение S3 в моей незавершенной библиотеке: https://github.com/sigod/s3-d /blob/master/source/s3/s3.d#L104 – sigod

+0

Я использовал готовую библиотеку для процесса авторизации, и я думаю, что она должна работать (все модульные тесты проходят). Я узнаю, что я не использовал время UTC, но я изменил его и все-таки это. Что странно, когда я помещаю данные из модульного теста в свой код, он генерирует другие хеши. Таким образом, проблема заключается в 99% в моем коде, но я не могу найти, где. – user3069488

ответ

0

После долгой борьбы с предыдущим кодом я пытаюсь переписать «один-к-одному» пример python от http://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html (часть GET) от попрошайничества до D с полным успехом. Вот рабочий код в ясном D. Im, использующем функцию hmac, которая доступна из 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); 
}