简体   繁体   English

InvalidSignatureException 从 SQL 向 AWS Kinesis 发送 POST 请求

[英]InvalidSignatureException Sending POST request to AWS Kinesis from SQL

I'm trying to send data to my kinesis stream from SQL but I'm only able to get back the error.我正在尝试从 SQL 向我的 kinesis stream 发送数据,但我只能找回错误。

{
    "__type": "InvalidSignatureException",
    "message": "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."
}

My key & secret are correct as I've done a successful test in Postman.我的密钥和秘密是正确的,因为我已经在 Postman 中进行了成功的测试。

Here is my function for creating the Authentication header...这是我的 function 用于创建身份验证 header ...

ALTER FUNCTION [dbo].[CreateAuth]
(
    @awsAccessKey NVARCHAR(MAX),
    @awsSecretKey NVARCHAR(MAX),
    @content NVARCHAR(MAX),
    @dateTime Datetime
)
RETURNS VARCHAR(MAX)
AS
BEGIN

    DECLARE @awsRegion NVARCHAR(MAX) = 'eu-west-2';
    DECLARE @awsService NVARCHAR(MAX) = 'kinesis';
    DECLARE @timeStamp NVARCHAR(16) = FORMAT(@dateTime, 'yyyyMMddTHHmmssZ');
    DECLARE @scope NVARCHAR(MAX) = FORMAT(@dateTime, 'yyyyMMdd') + '/'+@awsRegion+'/'+@awsService+'/aws4_request'

    DECLARE @x_amz_content_sha256 NVARCHAR(MAX);
    DECLARE @hexbin VARBINARY(max) =  HASHBYTES('SHA2_256 ',@content);   

    SET @x_amz_content_sha256 = LOWER(CONVERT([varchar](512), @hexbin,2))
    
    -- CANONICAL REQUEST
        DECLARE @CanonicalRequest NVARCHAR(MAX) = '';
        -- HTTP verb
        SET @CanonicalRequest += 'POST' + CHAR(13) 
        -- URL
        SET @CanonicalRequest += 'kinesis.eu-west-2.amazonaws.com' + CHAR(13) 

        -- QUERYSTRING (must be sorted alphbetically)
        SET @CanonicalRequest += '' + CHAR(13) 

        -- HEADERS (must be sorted alphbetically)
        SET @CanonicalRequest += 'content-type:application/x-amz-json-1.1' + CHAR(13) 
        SET @CanonicalRequest += 'host:kinesis.eu-west-2.amazonaws.com' + CHAR(13) 
        SET @CanonicalRequest += 'x-amz-content-sha256:' + @x_amz_content_sha256 + CHAR(13) 
        SET @CanonicalRequest += 'x-amz-date:' + @timeStamp + CHAR(13) 
        SET @CanonicalRequest += 'x-amz-target:' + 'Kinesis_20131202.PutRecord' + CHAR(13) 

        -- SIGNED HEADERS
        DECLARE @signedheaders NVARCHAR(MAX) = 'content-type;host;x-amz-content-sha256;x-amz-date;x-amz-target'
        SET @CanonicalRequest += @signedheaders + CHAR(13) 

        -- HASHED PAYLOAD
        SET @CanonicalRequest += @x_amz_content_sha256

        DECLARE @CanonicalRequestHexbin VARBINARY(max) = HASHBYTES('SHA2_256 ',@CanonicalRequest);  

    -- STRING TO SIGN
        DECLARE @stringToSign NVARCHAR(MAX) = '';
        SET @stringToSign += 'AWS4-HMAC-SHA256' + CHAR(13) 
        SET @stringToSign += @timeStamp + CHAR(13) 
        SET @stringToSign += @scope + CHAR(13) 
        SET @stringToSign += LOWER(CONVERT([varchar](512), @CanonicalRequestHexbin,2))

    -- CALCULATE SIGNATURE
        DECLARE @DateKey VARBINARY(64); 
        DECLARE @DateRegionKey VARBINARY(64);
        DECLARE @DateRegionServiceKey VARBINARY(64);
        DECLARE @SigningKey VARBINARY(64);
        DECLARE @Signature VARBINARY(64);

        SET @DateKey                = dbo.HMAC('SHA2_256',CONVERT(VARBINARY(MAX), 'AWS4'+@awsSecretKey),CONVERT(VARBINARY(MAX),FORMAT(@dateTime, 'yyyyMMdd')))
        SET @DateRegionKey          = dbo.HMAC('SHA2_256', @DateKey,                CONVERT(VARBINARY(MAX),@awsRegion))
        SET @DateRegionServiceKey   = dbo.HMAC('SHA2_256', @DateRegionKey,          CONVERT(VARBINARY(MAX),@awsService))
        SET @SigningKey             = dbo.HMAC('SHA2_256', @DateRegionServiceKey,   CONVERT(VARBINARY(MAX),'aws4_request'))

        SET @Signature = dbo.HMAC('SHA2_256',@SigningKey,CONVERT(VARBINARY(MAX),@stringToSign));

    --BUILD Authorization
    DECLARE @AuthValue NVARCHAR(MAX) = '';
    SET @AuthValue += 'AWS4-HMAC-SHA256 Credential=' + @awsAccessKey + '/'+ @scope 
    SET @AuthValue += ',SignedHeaders=' + @signedheaders 
    SET @AuthValue += ',Signature=' + LOWER(CONVERT([varchar](512), @Signature,2))

    RETURN @AuthValue

And here is the call to kinesis这是对运动的召唤

-- Open the connection.
    EXEC @ret = sp_OACreate 'MSXML2.ServerXMLHTTP', @token OUT;
    IF @ret <> 0 RAISERROR('Unable to open HTTP connection.', 10, 1);

-- Send the request.
    EXEC @ret = sp_OAMethod @token, 'open', NULL, 'POST', @url, 'false';
    SET @auth = dbo.CreateAuth('MYACCESSKEY','MYSECRETKEY',@postData, @datetime)
    EXEC @ret = sp_OAMethod @token, 'setRequestHeader', NULL, 'Authorization', @auth

    PRINT @auth
    PRINT ''

    DECLARE @hexbin VARBINARY(max) =  HASHBYTES('SHA2_256 ',@postData); --hash data
    DECLARE @x_amz_content_sha256 NVARCHAR(MAX) = LOWER(CONVERT([varchar](512), @hexbin,2)) -- get hex of hashed data
    EXEC @ret = sp_OAMethod @token, 'setRequestHeader', NULL, 'content-type', @contentType;
    EXEC @ret = sp_OAMethod @token, 'setRequestHeader', NULL, 'host', 'kinesis.eu-west-2.amazonaws.com';
    EXEC @ret = sp_OAMethod @token, 'setRequestHeader', NULL, 'x-amz-content-sha256', @x_amz_content_sha256;
    EXEC @ret = sp_OAMethod @token, 'setRequestHeader', NULL, 'x-amz-date', @xAmzDate;
    EXEC @ret = sp_OAMethod @token, 'setRequestHeader', NULL, 'x-amz-target', @xAmzTarget;
    EXEC @ret = sp_OAMethod @token, 'send', NULL, @postData;

-- Handle the response.
    EXEC @ret = sp_OAGetProperty @token, 'status', @status OUT;
    EXEC @ret = sp_OAGetProperty @token, 'statusText', @statusText OUT;
    EXEC @ret = sp_OAGetProperty @token, 'responseText', @responseText OUT;

-- Show the response.
    PRINT 'Status: ' + @status + ' (' + @statusText + ')';
    PRINT 'Response text: ' + @responseText;

-- Close the connection.
    EXEC @ret = sp_OADestroy @token;
    IF @ret <> 0 RAISERROR('Unable to close HTTP connection.', 10, 1);

The HMAC function I'm using is this one... https://gist.github.com/rmalayter/3130462 I've verified that the results produced with the SHA2_256 & HMAC functions are correct using https://codebeautify.org/ The HMAC function I'm using is this one... https://gist.github.com/rmalayter/3130462 I've verified that the results produced with the SHA2_256 & HMAC functions are correct using https://codebeautify.org /

I'm pretty sure I'm doing everything according to... https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html and https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html I'm pretty sure I'm doing everything according to... https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html and https://docs.aws.amazon.com/AmazonS3 /latest/API/sig-v4-header-based-auth.html

I'm lost as to what to look try next.我不知道接下来要尝试什么。

I've solved it now.我现在已经解决了。 There were a number of problems aside from my lazy hard coding.除了我懒惰的硬编码之外,还有许多问题。

  • CanonicalURI should just be '/'. CanonicalURI 应该只是'/'。 - thanks @AlwayLearning. - 谢谢@AlwayLearning。
  • Changed all string variables to VARCHAR rather than NVARCHAR, this was causing incorrect hashing.将所有字符串变量更改为 VARCHAR 而不是 NVARCHAR,这会导致不正确的散列。
  • The date used for the @datekey also needs to be a VARCHAR CONVERT(VARCHAR(MAX),FORMAT(@dateTime, 'yyyyMMdd')) as the FORMAT() function returns a NVARCHAR. @datekey 使用的日期也需要是 VARCHAR CONVERT(VARCHAR(MAX),FORMAT(@dateTime, 'yyyyMMdd')) ,因为 FORMAT() function 返回 NVARCHAR。

And I found this site which was very helpful http://aws-signature.com.s3-website-us-west-2.amazonaws.com/我发现这个网站非常有帮助http://aws-signature.com.s3-website-us-west-2.amazonaws.com/

Successful function now looks like this...成功的 function 现在看起来是这样的……

ALTER FUNCTION [dbo].[CreateAuth]
(
    @awsAccessKey VARCHAR(MAX),
    @awsSecretKey VARCHAR(MAX),
    @content VARCHAR(MAX),
    @dateTime Datetime,
    @awsRegion VARCHAR(MAX),
    @awsService VARCHAR(MAX),
    @CanonicalRequestURI VARCHAR(MAX),
    @host VARCHAR(MAX),
    @xAmzTarget VARCHAR(MAX),
    @contentType VARCHAR(MAX)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
    DECLARE @date VARCHAR(8) = FORMAT(@dateTime, 'yyyyMMdd')
    DECLARE @timeStamp VARCHAR(16) = FORMAT(@dateTime, 'yyyyMMddTHHmmssZ');
    DECLARE @scope VARCHAR(MAX) = @date + '/'+@awsRegion+'/'+@awsService+'/aws4_request'

    DECLARE @x_amz_content_sha256 VARCHAR(MAX);
    DECLARE @hexbin VARBINARY(max) =  HASHBYTES('SHA2_256 ',@content);   

    SET @x_amz_content_sha256 = LOWER(CONVERT([varchar](MAX), @hexbin,2))
    
    -- CANONICAL REQUEST
        DECLARE @CanonicalRequest VARCHAR(MAX) = '';
        -- HTTP verb
        SET @CanonicalRequest += 'POST' + CHAR(10) 
        -- URL
        SET @CanonicalRequest += @CanonicalRequestURI + CHAR(10) 

        -- QUERYSTRING (must be sorted alphbetically)
        SET @CanonicalRequest += '' + CHAR(10) 

        -- HEADERS (must be sorted alphbetically)
        SET @CanonicalRequest += 'content-type:' + @contentType + CHAR(10) 
        SET @CanonicalRequest += 'host:' + @host + CHAR(10) 
        SET @CanonicalRequest += 'x-amz-content-sha256:' + @x_amz_content_sha256 + CHAR(10) 
        SET @CanonicalRequest += 'x-amz-date:' + @timeStamp + CHAR(10) 
        SET @CanonicalRequest += 'x-amz-target:' + @xAmzTarget + CHAR(10) 
        SET @CanonicalRequest +=  CHAR(10)  

        -- SIGNED HEADERS
        DECLARE @signedheaders VARCHAR(MAX) = 'content-type;host;x-amz-content-sha256;x-amz-date;x-amz-target'
        SET @CanonicalRequest += @signedheaders + CHAR(10) 

        -- HASHED PAYLOAD
        SET @CanonicalRequest += @x_amz_content_sha256

        DECLARE @CanonicalRequestHexbin VARBINARY(max) = HASHBYTES('SHA2_256 ',@CanonicalRequest);  

    -- STRING TO SIGN
        DECLARE @stringToSign VARCHAR(MAX) = '';
        SET @stringToSign += 'AWS4-HMAC-SHA256' + CHAR(10) 
        SET @stringToSign += @timeStamp + CHAR(10) 
        SET @stringToSign += @scope + CHAR(10) 
        SET @stringToSign += LOWER(CONVERT([varchar](MAX), @CanonicalRequestHexbin,2))

    -- CALCULATE SIGNATURE
        DECLARE @DateKey VARBINARY(MAX); 
        DECLARE @DateRegionKey VARBINARY(MAX);
        DECLARE @DateRegionServiceKey VARBINARY(MAX);
        DECLARE @SigningKey VARBINARY(MAX);
        DECLARE @Signature VARBINARY(MAX);

        SET @DateKey                = dbo.HMAC('SHA2_256',CONVERT(VARBINARY(MAX), 'AWS4'+@awsSecretKey),CONVERT(VARBINARY(MAX),@date))
        SET @DateRegionKey          = dbo.HMAC('SHA2_256', @DateKey,                CONVERT(VARBINARY(MAX),@awsRegion))
        SET @DateRegionServiceKey   = dbo.HMAC('SHA2_256', @DateRegionKey,          CONVERT(VARBINARY(MAX),@awsService))
        SET @SigningKey             = dbo.HMAC('SHA2_256', @DateRegionServiceKey,   CONVERT(VARBINARY(MAX),'aws4_request'))

        SET @Signature = dbo.HMAC('SHA2_256',@SigningKey,CONVERT(VARBINARY(MAX),@stringToSign));

    --BUILD Authorization
    DECLARE @AuthValue VARCHAR(MAX) = '';
    SET @AuthValue += 'AWS4-HMAC-SHA256 Credential=' + @awsAccessKey + '/'+ @scope 
    SET @AuthValue += ',SignedHeaders=' + @signedheaders 
    SET @AuthValue += ',Signature=' + LOWER(CONVERT([varchar](MAX), @Signature,2))

    RETURN @AuthValue
    
END

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM