Wie entkräften Sie einen zwischengespeicherte AWS API-Gateway-Endpunkt in ASPNETCORE?

stimmen
0

[Anmerkung: Ich habe gearbeitet bereits eine Antwort auf diese, aber gekämpft, etwas zu finden online, so dass es hier ich hinzufüge]

Ich brauche den Cache für einen einzelnen AWS API-Gateway-Endpunkt mit ASPNETCORE ungültig zu machen.

Die docs sagen ein signiertes Anfrage zu senden. Wie tun Sie dies in .NET?

Veröffentlicht am 19/12/2018 um 14:18
quelle vom benutzer
In anderen Sprachen...                            


1 antworten

stimmen
1

Ich beantworte meine eigene Frage, da ich nicht viele Informationen online finden konnte, und es dauerte ein wenig Zeit zum Laufen zu bringen. Hoffentlich wird es jemand helfen.

Ich habe Code hier hinzugefügt: https://gist.github.com/secretorange/905b4811300d7c96c71fa9c6d115ee24

CacheInvalidationRequestBuilder.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;

namespace Aws
{
    public static class CacheInvalidationRequestBuilder
    {
        private const string ServiceName    = "execute-api";
        private const string Algorithm      = "AWS4-HMAC-SHA256";
        private const string ContentType    = "application/json";
        private const string DateTimeFormat = "yyyyMMddTHHmmssZ";
        private const string DateFormat     = "yyyyMMdd";

        public static WebRequest Build(CacheInvalidationRequestModel request)
        {
            string hashedRequestPayload = CreateRequestPayload(String.Empty);

            string authorization = Sign(request, hashedRequestPayload, "GET", request.AbsolutePath, request.QueryString);
            string requestDate = DateTime.UtcNow.ToString(DateTimeFormat);

            var webRequest = WebRequest.Create($"https://{request.Host}{request.AbsolutePath}");

            webRequest.Method = "GET";
            webRequest.ContentType = ContentType;

            webRequest.Headers.Add("Cache-Control", "max-age=0");
            webRequest.Headers.Add("Host", request.Host);
            webRequest.Headers.Add("X-Amz-Date", requestDate);

            webRequest.Headers.Add("Authorization", authorization);

            return webRequest;
        }

        private static string CreateRequestPayload(string jsonString)
        {
            return HexEncode(Hash(ToBytes(jsonString)));
        }

        private static string Sign(CacheInvalidationRequestModel request, string hashedRequestPayload, string requestMethod, string canonicalUri, string canonicalQueryString)
        {
            var currentDateTime = DateTime.UtcNow;

            var dateStamp = currentDateTime.ToString(DateFormat);
            var requestDate = currentDateTime.ToString(DateTimeFormat);
            var credentialScope = $"{dateStamp}/{request.Region}/{ServiceName}/aws4_request";

            var headers = new SortedDictionary<string, string> {
                { "cache-control", "max-age=0" },
                { "content-type", ContentType },
                { "host", request.Host },
                { "x-amz-date", requestDate }
            };

            var canonicalHeaders = string.Join("\n", headers.Select(x => x.Key.ToLowerInvariant() + ":" + x.Value.Trim())) + "\n";

            // Task 1: Create a Canonical Request For Signature Version 4
            var SignedHeaders = String.Join(';', headers.Select(x => x.Key.ToLowerInvariant()));

            var canonicalRequest = $"{requestMethod}\n{canonicalUri}\n{canonicalQueryString}\n{canonicalHeaders}\n{SignedHeaders}\n{hashedRequestPayload}";

            var hashedCanonicalRequest = HexEncode(Hash(ToBytes(canonicalRequest)));

            // Task 2: Create a String to Sign for Signature Version 4
            var stringToSign = $"{Algorithm}\n{requestDate}\n{credentialScope}\n{hashedCanonicalRequest}";

            // Task 3: Calculate the AWS Signature Version 4
            var signingKey = GetSignatureKey(request.SecretKey, dateStamp, request.Region, ServiceName);
            var signature = HexEncode(HmacSha256(stringToSign, signingKey));

            // Task 4: Prepare a signed request
            // Authorization: algorithm Credential=access key ID/credential scope, SignedHeadaers=SignedHeaders, Signature=signature
            var authorization = $"{Algorithm} Credential={request.AccessKey}/{dateStamp}/{request.Region}/{ServiceName}/aws4_request, SignedHeaders={SignedHeaders}, Signature={signature}";

            return authorization;
        }

        private static byte[] GetSignatureKey(string key, string dateStamp, string regionName, string serviceName)
        {
            var kDate = HmacSha256(dateStamp, ToBytes("AWS4" + key));
            var kRegion = HmacSha256(regionName, kDate);
            var kService = HmacSha256(serviceName, kRegion);
            return HmacSha256("aws4_request", kService);
        }

        private static byte[] ToBytes(string str)
        {
            return Encoding.UTF8.GetBytes(str.ToCharArray());
        }

        private static string HexEncode(byte[] bytes)
        {
            return BitConverter.ToString(bytes).Replace("-", string.Empty).ToLowerInvariant();
        }

        private static byte[] Hash(byte[] bytes)
        {
            return SHA256.Create().ComputeHash(bytes);
        }

        private static byte[] HmacSha256(string data, byte[] key)
        {
            return new HMACSHA256(key).ComputeHash(ToBytes(data));
        }
    }
}

CacheInvalidationRequestModel.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace Aws
{
    public class CacheInvalidationRequestModel
    {
        public string Region { get; set; }

        public string Host { get; set; }

        public string AbsolutePath { get; set; }

        public string QueryString { get; set; }

        public string AccessKey { get; set; }

        public string SecretKey { get; set; }
    }
}

Wie Sie den Code verwenden,

Zur Anfrage, verwenden Sie Code ähnlich:

var url = $"/myendpoint";

var model = GetCacheInvalidationRequestModel(url);

var request = CacheInvalidationRequestBuilder.Build(model);

try
{
  // Hit the endpoint
  using (var response = request.GetResponse())
  {
    // Not currently doing anything with the response
  }
}
catch(Exception ex)
{
  Logger.LogError(ex, "Problem invalidating cache for url: " + url);
}

Das GetCacheInvalidationRequestModelVerfahren könnte wie folgt aussehen (Ich gehe in den Modell - Eigenschaften wie IOptions):

private CacheInvalidationRequestModel GetCacheInvalidationRequestModel(string absolutePath)
{
    return new CacheInvalidationRequestModel()
    {
        Region = Options.Region,
        Host = Options.Host,
        AccessKey = Options.InvalidatorKey,
        SecretKey = Options.InvalidatorSecret,
        AbsolutePath = absolutePath
    };
}

AWS Informationen

AWS docs für signierte Anfragen Gebäude sind hier: https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html

Ihre AWS Benutzer eine angeschlossene Politik benötigen, wie hier gezeigt: https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-caching.html

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "execute-api:InvalidateCache"
      ],
      "Resource": [
        "arn:aws:execute-api:region:account-id:api-id/stage-name/GET/resource-path-specifier"
      ]
    }
  ]
}

HINWEIS: Sie können Platzhalter verwenden, wenn Sie möchten.

Beantwortet am 19/12/2018 um 14:18
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more