La autenticación AWS API con Rest API - AWS no pudo validar las credenciales de acceso proporcionadas
Estoy tratando de crear un simple programa C# o VB para conectarse a la API AWS y devolver una cadena JSON dando datos de instancia EC2. En lugar de eso, obtengo el error. "AWS no pudo validar las credenciales de acceso proporcionadas"
He intentado conectarme en ambos Postman
y en un programa VB como sigue:
Imports System.Net
Imports System.IO
Module Main
Sub Main()
Dim result As String = RunQuery("", "https://ec2.amazonaws.com/?Action=DescribeInstances")
Console.WriteLine(result)
Console.ReadLine()
End Sub
Public Function RunQuery(creds As String, url As String, Optional data As String = Nothing) As String
Dim request As HttpWebRequest = TryCast(WebRequest.Create(url), HttpWebRequest)
request.ContentType = "application/json"
request.Method = "GET"
If data IsNot Nothing Then
Using writer As StreamWriter = New StreamWriter(request.GetRequestStream())
writer.Write(data)
End Using
End If
Dim d As Date = Date.UtcNow
Dim t As String = Format(d, "yyyyMMdd") & "T" & Format(d, "HHmmss") & "Z"
request.Headers.Add("X-Amz-Date", t)
request.Headers.Add("Authorization", "AWS4-HMAC-SHA256 Credential=***MYAPIKEY***/20201216/us-east-2/ec2/aws4_request, SignedHeaders=host;x-amz-date, Signature=***MYAPISECRET***")
Dim response As HttpWebResponse = TryCast(request.GetResponse(), HttpWebResponse)
Dim result As String = String.Empty
Using reader As StreamReader = New StreamReader(response.GetResponseStream())
result = reader.ReadToEnd()
End Using
Return result
End Function
End Module
La producción del cartero era
xml version="1.0" encoding="UTF-8"?
AuthFailure
AWS was not able to validate the provided access credentials 37153d9f-c042-4ae3-8a13-06dc3b052afc
Escribí el vb basado en código postal:
var client = new RestClient("https://ec2.amazonaws.com/?Action=DescribeInstances");
client.Timeout = -1;
var request = new RestRequest(Method.GET);
request.AddHeader("X-Amz-Date", "20201216T092737Z");
request.AddHeader("Authorization", "AWS4-HMAC-SHA256 Credential=MYAPIKEY/20201216/us-east-2/ec2/aws4_request, SignedHeaders=host;x-amz-date, Signature=MYAPISIGNATURE");
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
Preguntas similares se han hecho muchas veces antes, pero las únicas respuestas que puedo ver son que el reloj PC estaba equivocado, así que he corregido la mía tal que su dentro de 0,2 segundos del verdadero tiempo de Internet.
También no pude encontrar otro programa VB o C# similarmente simple que se conecta con éxito a EC2, por lo que este hilo puede ayudar a otros en el futuro.
Me pregunto si la firma tiene que ser codificada con base64 o algún otro algoritmo? De lo contrario, ¿cómo puedo conseguir que esto funcione ya sea en cartero o en vb/c#? TIA
Pregunta hecha hace 3 años, 5 meses, 0 días - Por scriptsculptor52b5
3 Respuestas:
-
Así que hubo un par de problemas
URL incorrecta, la correcta era
https://ec2.us-east-2.amazonaws.com/?Action=DescribeInstances&Version=2016-11-15
Supuse que el secreto era la firma, no lo es.
Aquí hay un VB completo. Aplicación de consola NET que conecta con éxito con AWS. Lo sentimos, pero el código es razonablemente obvio y no demasiado largo.
Option Explicit On Option Compare Text Option Strict On Imports System.Net.Http Imports System.Security.Cryptography Imports System.Text Public Module Program Public Sub Main(ByVal args As String()) If args.Length <> 5 Then Throw New Exception("AWS Integration requires 5 parameters: url accessKey secretKey awsRegion awsServiceName") End If Dim url As String = args(0) ' "https://ec2.us-east-2.amazonaws.com/?Action=DescribeInstances&Version=2016-11-15" Dim accessKey As String = args(1) ' api key Dim secretkey As String = args(2) ' api secret Dim awsRegion As String = args(3) ' = "us-east-2" Dim awsServiceName As String = args(4) '= "ec2" Dim msg As HttpRequestMessage = New HttpRequestMessage(HttpMethod.[Get], url) msg.Headers.Host = msg.RequestUri.Host Dim utcNowSaved As DateTimeOffset = DateTimeOffset.UtcNow Dim amzLongDate As String = utcNowSaved.ToString("yyyyMMddTHHmmssZ") Dim amzShortDate As String = utcNowSaved.ToString("yyyyMMdd") msg.Headers.Add("x-amz-date", amzLongDate) Dim canonicalRequest As New StringBuilder canonicalRequest.Append(msg.Method.ToString & vbLf) canonicalRequest.Append(String.Join("/", msg.RequestUri.AbsolutePath.Split("/"c).Select(AddressOf Uri.EscapeDataString)) & vbLf) canonicalRequest.Append(GetCanonicalQueryParams(msg) & vbLf) Dim headersToBeSigned As New List(Of String) For Each header In msg.Headers.OrderBy(Function(a) a.Key.ToLowerInvariant, StringComparer.OrdinalIgnoreCase) canonicalRequest.Append(header.Key.ToLowerInvariant) canonicalRequest.Append(":") canonicalRequest.Append(String.Join(",", header.Value.[Select](Function(s) s.Trim))) canonicalRequest.Append(vbLf) headersToBeSigned.Add(header.Key.ToLowerInvariant) Next canonicalRequest.Append(vbLf) Dim signedHeaders As String = String.Join(";", headersToBeSigned) canonicalRequest.Append(signedHeaders & vbLf) canonicalRequest.Append("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855") Dim stringToSign As String = "AWS4-HMAC-SHA256" & vbLf & amzLongDate & vbLf & amzShortDate & "/" & awsRegion & "/" & awsServiceName & "/aws4_request" & vbLf & Hash(Encoding.UTF8.GetBytes(canonicalRequest.ToString)) Dim dateKey() As Byte = HmacSha256(Encoding.UTF8.GetBytes("AWS4" & secretkey), amzShortDate) Dim dateRegionKey() As Byte = HmacSha256(dateKey, awsRegion) Dim dateRegionServiceKey() As Byte = HmacSha256(dateRegionKey, awsServiceName) Dim signingKey() As Byte = HmacSha256(dateRegionServiceKey, "aws4_request") Dim signature As String = ToHexString(HmacSha256(signingKey, stringToSign.ToString)) Dim credentialScope As String = amzShortDate & "/" & awsRegion & "/" & awsServiceName & "/aws4_request" msg.Headers.TryAddWithoutValidation("Authorization", "AWS4-HMAC-SHA256 Credential=" & accessKey & "/" & credentialScope & ", SignedHeaders=" & signedHeaders & ", Signature=" & signature) Dim client As HttpClient = New HttpClient Dim result As HttpResponseMessage = client.SendAsync(msg).Result If result.IsSuccessStatusCode Then 'Console.WriteLine(result.Headers) Dim s As String = result.Content.ReadAsStringAsync().Result Console.WriteLine(s) Else Console.WriteLine(result.StatusCode & vbCrLf & result.ToString.Replace(vbCr, "").Replace(vbLf, "")) End If End Sub Private Function GetCanonicalQueryParams(ByVal request As HttpRequestMessage) As String Dim values = New SortedDictionary(Of String, String) Dim querystring = System.Web.HttpUtility.ParseQueryString(request.RequestUri.Query) For Each key In querystring.AllKeys If key Is Nothing Then values.Add(Uri.EscapeDataString(querystring(key)), $"{Uri.EscapeDataString(querystring(key))}=") Else values.Add(Uri.EscapeDataString(key), $"{Uri.EscapeDataString(key)}={Uri.EscapeDataString(querystring(key))}") End If Next Dim queryParams = values.Select(Function(a) a.Value) Return String.Join("&", queryParams) End Function Public Function Hash(ByVal bytesToHash() As Byte) As String Return ToHexString(SHA256.Create.ComputeHash(bytesToHash)) End Function Private Function ToHexString(ByVal array As IReadOnlyCollection(Of Byte)) As String Dim hex = New StringBuilder(array.Count * 2) For Each b In array hex.AppendFormat("{0:x2}", b) Next Return hex.ToString End Function Private Function HmacSha256(ByVal key() As Byte, ByVal data As String) As Byte() Return New HMACSHA256(key).ComputeHash(Encoding.UTF8.GetBytes(data)) End Function End Module
HTH someone :)
Respondida el Dec 16, 2020 a las 10:40 - por javagiant
Votos positivos: 0 | Votos negativos: 0 -
El error "AWS no pudo validar las credenciales de acceso proporcionadas" suele ocurrir cuando hay un problema con la autenticación de las credenciales de acceso a AWS. Parece que estás intentando realizar la autenticación manualmente en la solicitud HTTP, lo cual puede ser propenso a errores.
En lugar de realizar la autenticación manualmente, te recomendaría utilizar las bibliotecas y SDK proporcionados por AWS para interactuar con sus servicios de forma segura y sin tener que lidiar con la autenticación a nivel de la solicitud HTTP.
Para C
, puedes utilizar el AWS SDK for .NET, que te facilitará la autenticación y el uso de servicios como EC2. Aquí tienes un ejemplo de cómo podrías modificar tu código en C# utilizando el SDK:
csharp using Amazon; using Amazon.EC2; using Amazon.EC2.Model; class Program { static void Main() { var awsCreds = new Amazon.Runtime.BasicAWSCredentials("ACCESS_KEY", "SECRET_KEY"); var region = RegionEndpoint.USEast2; // Cambia a la región correcta si es necesario var client = new AmazonEC2Client(awsCreds, region); DescribeInstancesRequest request = new DescribeInstancesRequest(); DescribeInstancesResponse response = client.DescribeInstances(request); foreach (var reservation in response.Reservations) { foreach (var instance in reservation.Instances) { Console.WriteLine($"Instance Id: {instance.InstanceId}"); } } } }
Este código usaría las credenciales de acceso que proporciones en lugar de
ACCESS_KEY
ySECRET_KEY
, y luego se conectará a AWS EC2 para obtener información sobre las instancias en ejecución.Si aún prefieres realizar la autenticación manualmente, ten en cuenta que la firma debe generarse utilizando el algoritmo HMAC-SHA256 y los pasos requeridos por la documentación de AWS. Asegúrate de seguir correctamente todos los pasos necesarios para construir la firma y añadirla a la cabecera
Authorization
.Espero que esta información te sea útil y te ayude a solucionar tu problema de autenticación con AWS. ¡Déjame saber si tienes alguna otra pregunta!
Respondida el Dec 17, 2020 a las 10:41 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
Problema:
La autenticación con las API de AWS utilizando las credenciales de acceso proporcionadas no es válida.
Causas posibles:
Credenciales de acceso incorrectas o inválidas. Reloj del sistema desincronizado con la hora de AWS. Firma de solicitud incorrecta. Encabezado
Authorization
mal formado.Soluciones:
1. Verifica las credenciales de acceso:
Asegúrate de estar utilizando las credenciales de acceso correctas para tu cuenta de AWS. Comprueba el ID y la clave de acceso secreta en la consola de administración de AWS o en tus variables de entorno.
2. Sincroniza el reloj del sistema:
El reloj del sistema debe estar sincronizado con la hora de AWS para generar firmas de solicitud válidas. Utiliza el comando
ntpdate
o un servicio NTP para sincronizar el reloj del sistema.3. Genera una firma de solicitud válida:
Utiliza la biblioteca de firmas de AWS para generar la firma de solicitud. Sigue la documentación oficial de AWS para crear la cadena de firma y el encabezado
Authorization
.4. Comprueba el encabezado
Authorization
:El encabezado
Authorization
debe tener el formato correcto:AWS4-HMAC-SHA256 Credential=<access key ID>/<date>/<region>/<service>/aws4_request, SignedHeaders=<list of signed headers>, Signature=<signature>
Asegúrate de que los encabezados firmados incluyanhost
yx-amz-date
.Ejemplo para C
:
c
using Amazon;
using Amazon.EC2; using Amazon.Runtime; using System; namespace AwsEc2GetInstances { class Program { static void Main(string[] args) { // Define the AWS credentials var accessKeyId = "YOUR_ACCESS_KEY_ID"; var secretAccessKey = "YOUR_SECRET_ACCESS_KEY"; var credentials = new BasicAWSCredentials(accessKeyId, secretAccessKey); // Define the region var region = RegionEndpoint.USEast1; // Create the EC2 client var client = new AmazonEC2Client(credentials, region); // Create the request var request = new DescribeInstancesRequest { Filters = new List{ new Filter("instance-type", new List { "t2.micro" }) } }; // Get the instances var response = client.DescribeInstances(request); // Print the instances foreach (var instance in response.Reservations) { Console.WriteLine(instance.Instances[0].InstanceId); } } } } Ejemplo para Postman:
En la pestaña "Headers", agrega un nuevo encabezado con la clave
x-amz-date
y el valor de la fecha y hora actuales en formato ISO 8601 (por ejemplo,2023-03-08T12:00:00Z
). En la pestaña "Headers", agrega un nuevo encabezado con la claveAuthorization
y el valor generado por la biblioteca de firmas de AWS.Recursos adicionales:
AWS Signature Version 4 AWS SDK for .NET AWS SDK for Python (Boto3)
Respondida el Dec 17, 2020 a las 10:49 - por Gemini
Votos positivos: 0 | Votos negativos: 0