Canonical Request to AWS Signature 4 is correct? - amazon-web-services

I'd like to ask if there's any error in my canonical request, im trying to create one to the AWS Secrets Manager taking the sample request by example.
Doc:https://docs.aws.amazon.com/pt_br/AmazonS3/latest/API/sig-v4-header-based-auth.html
Sample Request:
`POST / HTTP/1.1
Host: secretsmanager.region.domain
Accept-Encoding: identity
X-Amz-Target: secretsmanager.GetSecretValue
Content-Type: application/x-amz-json-1.1
User-Agent:
X-Amz-Date:
Authorization: AWS4-HMAC-SHA256 Credential=,SignedHeaders=, Signature=
Content-Length:
{
"SecretId": "MyTestDatabaseSecret",
}`
My Canonical Request:
`POST
/GetSecretValue
accept-encoding:identity
content-type:application/x-amz-json-1.1
host:secretsmanager.sa-east-1.amazonaws.com
x-amz-content-sha256:beaead3198f7da1e70d03ab969765e0821b24fc913697e929e726aeaebf0eba3
x-amz-date:20230111T145646Z
x-amz-target:secretsmanager.getsecretvalue
accept-encoding;content-type;host;x-amz-content-sha256;x-amz-date;x-amz-target
beaead3198f7da1e70d03ab969765e0821b24fc913697e929e726aeaebf0eba3`
I did the changes that the documentation was asking, but when i try to recreate the signature by the postman, well, It gets wrong.

Related

AWS Api Gateway: passing a multipart/form-data

I need to go through the AWS ApiGteway. From the gateway API the request is routed to EC2. The direct request to Ec2 works. This is my request:
POST /TEST/resource HTTP/1.1
Host: xxxxxxxx.execute-api.yyyyyyyyyy.amazonaws.com
Content-Length: 358
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="metadata"
{
"mimeType":"application/video",
"extension":"mp3",
"name":"MP3File.mp3"
}
----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file"; filename="MP3File.mp3"
Content-Type: audio/mpeg
(data)
----WebKitFormBoundary7MA4YWxkTrZu0gW
My request is of type multi and consists of a file (MP3) and a metadata (string which represents a json payload).
I configured the APIGateway settings as follows:
This is the error I get on POSTMAN:
What am I doing wrong? Thanks for the support

Why can't I upload config file in the POST method using Postman?

Hello, I'm trying to solve my issue for so long that I had to ask someone else.
I'm working with some API and I want to create resource using POST method via Postman. To create that resource I have to attach kubeconfig file to the POST request. This resource need to have name, description and of course config file. So I filled required fields:
POSTMAN fields
but I receive response "Bad Request":
Invalid Input:: Does not match pattern '^([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$'
It's look like i don't understand how to upload files that way because my request body looks like:
Request Body
metadata: "{"name": "edge01", "description": "Edge k8s cluster"}"
file: undefine
In the API documentation we can find that request body should look like this:
Request body multipart/form-data
metadata
object
file
string($binary)
Entire POST entry below:
Network
Request Headers
Accept: */*
Postman-Token: 8857f718-bb05-404c-865a-51ee3c0abe6f
Host: <Hidden_IP>:30461
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Type: multipart/form-data; boundary=--------------------------175308278007362265143565
Content-Length: 3518
Request Body
metadata: "{"name": "edge01", "description": "Edge k8s cluster"}"
file: undefined
Response Headers
Content-Type: text/plain; charset=utf-8
X-Content-Type-Options: nosniff
Date: Fri, 30 Jul 2021 10:19:58 GMT
Content-Length: 84
Response Body
Invalid Input:: Does not match pattern '^([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$'↵
I couldn't find anything about response presented above.
If anyone needs additional information, please comment. This string($binary) is interesting but I don't understand what it means, and couldn't find any informations in POSTMAN context.
This is a piece of API yaml:
/cluster-providers/{cluster-providers-name}/clusters:
parameters:
- $ref: '#/components/parameters/clusterProviderName'
post:
tags:
- Clusters
summary: Add Cluster
description: Add a new `cluster`
operationId: addClusterToClusterProvider
responses:
'201':
description: Created
content:
application/json: # operation response mime type
schema:
$ref: '#/components/schemas/Metadata'
'400':
description: Bad Request
'404':
description: Not Found
'409':
description: Conflict
'422':
description: Unprocessable Entity
'500':
description: Internal Server Error
requestBody:
content:
multipart/form-data: # Media type
schema: # Request payload
$ref: '#/components/schemas/AppData'
Add metadata to the body under raw, instead of form-data. This should be an object, like this:
{
"metadata": {
"name": "edge01",
"description": "Edge k8s cluster"
}
}

Go AWS SDK "Unable to determine service/operation name to be authorized"

I am using the Go SDK to connect to the Kinesis Video Streams service. When issuing a GetMedia request, I'm receiving a 403 response with the following body:
<AccessDeniedException>
<Message>Unable to determine service/operation name to be authorized</Message>
</AccessDeniedException>
I am using LogLevel LogDebugWithHTTPBody to see this since the SDK is expecting JSON and receives XML, causing a SerializationError.
I am using Go 1.9.2 and have attempted this operation with both v1 and v2 of aws-sdk-go with the same result.
Here is my request:
POST /getMedia HTTP/1.1
Host: kinesisvideo.us-west-2.amazonaws.com
User-Agent: aws-sdk-go/2.0.0-preview.1 (go1.9.2; darwin; amd64)
Content-Length: 141
Authorization: AWS4-HMAC-SHA256 Credential=AKIAXXXXXXXXXXXXXX/20180112/us-west-2/kinesisvideo/aws4_request, SignedHeaders=content-length;host;x-amz-date, Signature=60c625357b67c64caed32f5a0924882f26ffc776211801e94e7ecae84e7213c2
X-Amz-Date: 20180112T012511Z
Accept-Encoding: gzip
{"StartSelector":{"StartSelectorType":"NOW"},"StreamARN":"arn:aws:kinesisvideo:us-west-2:XXXXXXXXXXXXX:stream/StreamTest/XXXXXXXXXXXXX"}
Response:
HTTP/1.1 403 Forbidden
Content-Length: 130
Date: Fri, 12 Jan 2018 01:25:11 GMT
X-Amzn-Requestid: 6f1701aa-f737-11e7-bcd5-c70a68e72add
<AccessDeniedException>
<Message>Unable to determine service/operation name to be authorized</Message>
</AccessDeniedException>
Any help would be greatly appreciated.
To follow up, I have tried to issue the HTTP request above directly with the Content-Type: application/json header added, and the response is now:
{
"Output": {
"__type": "com.amazon.coral.service#UnknownOperationException",
"message": null
},
"Version": "1.0"
}
I have found the solution. From the docs,
"You must first call the GetDataEndpoint API to get an endpoint to which you can then send the GetMedia requests."

hls.js CORS using AWS Cloudfront issues with Cookies

I'm trying to set up a video streaming using Cloudfront HLS capabilities but I'm having trouble getting Hls.js to send my credential cookies in the request.
I already have Cloudfront configured to forward cookies and to forward Access-control headers. I also have set my S3 CORS policies to include GET, HEAD.
The problem I'm having is that even though I'm setting the xhr.withCredentials=true and the cookies are defined in the session, when I look at the request using chrome console, I can see that the HLS request has no cookies. As a result I get an error response from cloudfront saying I need to include the credential cookies.
Code:
First I do an ajax request to my server to generate the cookies. The server returns three Set-Cookies headers stored as session cookies in the browser:
$.ajax(
{
type: 'GET',
url: 'http://subdomain.mydomain.com:8080/service-
webapp/rest/resourceurl/cookies/98400738-a415-4e32-898c-9592d48d1ad7',
success: function (data) {
playMyVideo();
},
headers: { "Authorization": 'Bearer XXXXXX' }
});
Once the cookies are stored the test function is called to play my video using HLS.js:
function test(){
if (Hls.isSupported()) {
var video = document.getElementById('video');
var config = {
debug: true,
xhrSetup: function (xhr,url) {
xhr.withCredentials = true; // do send cookie
xhr.setRequestHeader("Access-Control-Allow-Headers","Content-Type, Accept, X-Requested-With");
xhr.setRequestHeader("Access-Control-Allow-Origin","http://sybdomain.domain.com:8080");
xhr.setRequestHeader("Access-Control-Allow-Credentials","true");
}
};
var hls = new Hls(config);
// bind them together
hls.attachMedia(video);
hls.on(Hls.Events.MEDIA_ATTACHED, function () {
console.log("video and hls.js are now bound together !");
hls.loadSource("http://cloudfrontDomain.net/small.m3u8");
hls.on(Hls.Events.MANIFEST_PARSED, function (event, data) {
console.log("manifest loaded, found " + data.levels.length + " quality level");
});
});
}
video.play();
}
As you can see below HLS OPTIONS and GET request do not set the session cookies:
HLS OPTIONS request:
OPTIONS /hls/98400738-a415-4e32-898c-9592d48d1ad7/small.m3u8 HTTP/1.1
Host: cloudfrontDomain.net
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: subdomain.mydomain.com:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.104 Safari/537.36
Access-Control-Request-Headers: access-control-allow-credentials,access-control-allow-headers,access-control-allow-origin
Accept: */*
Referer: http://subdomain.mydomain.com:8080/play.html
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8,es;q=0.6
CloudFront response:
HTTP/1.1 200 OK
Content-Length: 0
Connection: keep-alive
Date: Fri, 07 Jul 2017 00:16:31 GMT
Access-Control-Allow-Origin: http://subdomain.mydomain.com:8080
Access-Control-Allow-Methods: GET, HEAD
Access-Control-Allow-Headers: access-control-allow-credentials, access-control-allow-headers, access-control-allow-origin
Access-Control-Max-Age: 3000
Access-Control-Allow-Credentials: true
Server: AmazonS3
Vary: Origin,Access-Control-Request-Headers,Access-Control-Request-Method
Age: 845
X-Cache: Hit from cloudfront
Via: 1.1 cloudfrontDomain.net (CloudFront)
X-Amz-Cf-Id: XXXXXX
HLS subsequent GET request missing the cookies:
GET /hls/98400738-a415-4e32-898c-9592d48d1ad7/small.m3u8 HTTP/1.1
Host: cloudfrontDomain.net
Connection: keep-alive
Origin: http://subdomain.mydomain.com:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.104 Safari/537.36
Access-Control-Allow-Origin: http://subdomain.mydomain.com:8080
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Content-Type, Accept, X-Requested-With
Accept: */*
Referer: http://subdomain.mydomain.com:8080/play.html
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8,es;q=0.6
I've spent 4 days trying to figure this out. I've done plenty of research but I just can't figure out the solution. I'm new to CORS so maybe I'm not understanding some principle. I thought if the cookies are stored in the session they would get set if you enabled xhr with credentials but it doesn't seem to be the case.
Another thing I noted is that the GET request generated by HLS.js is not setting any xmlhttprequest header.
Thanks for your help :)
I was finally able to make it work. Thanks Michael for helping! Turns out it was a mix of not understanding how CORS principles work and properly configuring aws services. The main issue is to avoid cross domain requests by using cloudfront to serve both your webservice and s3 bucket. One important note I want to add is that any change you make in aws you have to wait for it to propagate. As a new aws dev I didn't know that and got very frustrated making changes that had no effect. Here is the solution:
1) Create your S3 bucket.
2) Create a Cloudfront distribution.
3) In the distribution set as the default origin your web-service domain.
4) Add a second origin and add a behavior in the distribution to forward all .m3u8 and .ts files to your S3 bucket.
5) When you add your bucket origin make sure you mark restrict access and also update bucket policy checkboxes.
6) In your bucket distribution behavior make sure you forward all white list headers and cookies. This can all be set in aws console.
7) If you are using different ports in your service make sure you set those too in the distribution.
8) Go to your S3 bucket settings and update the CORS config to the following:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
It is important that if your are using HLS.js to set the following config:
var config = {
debug: true,
xhrSetup: function (xhr,url) {
xhr.withCredentials = true; // do send cookie
xhr.setRequestHeader("Access-Control-Allow-Headers","Content-Type, Accept, X-Requested-With");
xhr.setRequestHeader("Access-Control-Allow-Origin","http://sybdomain.domain.com:8080");
xhr.setRequestHeader("Access-Control-Allow-Credentials","true");
}
};
var hls = new Hls(config);
Other important notes:
When you serve a cookie with your web service you can set the Path to be "/" and it will apply to all request in your domain.
For anyone that might be having this issue only on Chrome for Android, our problem was that the browser was caching the m3u8 files and giving the same CORS error. The solution was to append a timestamp parameter to the querystring of the file url:
var config = {
xhrSetup: function (xhr, url) {
xhr.withCredentials = true; // do send cookies
url = url + '?t=' + new Date().getTime();
xhr.open('GET', url, true);
}
};
var hls = new Hls(config);

Call to AWSCognitoIdentityService.GetId for Cognito User Pools returns "Token is not from a supported provider of this identity pool."

I am using the AWS sdk for javascript and I am trying to use the new Cognito User pool service. I am getting an error from the underlying http request, accessing the Cognito API function AWSCognitoIdentityService.GetId:
POST / HTTP/1.1
Host: cognito-identity.us-east-1.amazonaws.com
Connection: keep-alive
Content-Length: 985
Cache-Control: max-age=0
Origin: http://localhost:3000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36
Content-Type: application/x-amz-json-1.1
X-Amz-Content-Sha256: 9fba852db0a50678957c5be2a317ebce5edbb4580ad7cb1d7b524e2ff5bf95f7
X-Amz-Target: AWSCognitoIdentityService.GetId
X-Amz-User-Agent: aws-sdk-js/2.3.17
Accept: */*
Referer: http://localhost:3000/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
Request payload:
{"IdentityPoolId":"us-east-1:f9a5b209-8ed6-405d-987c-eb2954d30d1c","Logins":{"cognito-idp.us-east-1.amazonaws.com/us-east-1_9ymEVPkkL":"eyJraWQiOiJQUFhBemRsVDg1K29kNzNvTFU4cnFzVUZORVJvVkh2aVJERGV4bzdISmJzPSIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiI0OTNlYjk5MS1iMTgyLTQxYzAtYmZhNC00N2M5YzViMzM1OTMiLCJhdWQiOiI3N3U3MnRidjN2M2M2MG1pZXFlNGhhbW8yOSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJ0b2tlbl91c2UiOiJpZCIsImF1dGhfdGltZSI6MTQ2ODk4OTY4MywiaXNzIjoiaHR0cHM6XC9cL2NvZ25pdG8taWRwLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tXC91cy1lYXN0LTFfOXltRVZQa2tMIiwibmFtZSI6Ik5uZW5uYSBVZGVnYnVuYW0iLCJleHAiOjE0Njg5OTMyODMsImlhdCI6MTQ2ODk4OTY4MywiZW1haWwiOiJubmVubmFAZGFzaHBlZWsuY29tIn0.gItOyeKF3pu24aWtaUwPMQtcOAJu9TWqmYeT3N74zijI9QgfxL93fagZvVgsQj-rqtRSddVV05ZHJBXXZiUZdb3PnUDp48R_1Kiv1RhIvMqOO43RNyS9B7G4uD0cdM8S7OCaoJMXbDPwVH5jy_j9_anm7HgbRGi3JYLS10bIvvuqznxp75V6bxsTGhVGT8EHTui-l0yqLhLbPDM05JV0sOXANFS-BO4sYjgJ-VU8GrP6D49wbses524bMIDAIRN78me5WAFC6OzOqZQ9e_JNVbgs8pHaaDqpqTZq6RUGGUS0QykhDPoJImbS_tt5rGNrVFrDpKXcwJAD1hI5x6lrNA"}}
Response:
HTTP/1.1 400 Bad Request
x-amzn-RequestId: 8e6f7124-4e35-11e6-a6a6-d56ee4384e6b
Access-Control-Allow-Origin: *
x-amzn-ErrorType: NotAuthorizedException:
Access-Control-Expose-Headers: x-amzn-RequestId,x-amzn-ErrorType,x-amzn-ErrorMessage,Date
**x-amzn-ErrorMessage: Token is not from a supported provider of this identity pool.**
Content-Type: application/x-amz-json-1.1
Content-Length: 109
Date: Wed, 20 Jul 2016 04:51:01 GMT
Connection: close
This "Token is not from a supported provider of this identity pool" makes no sense. This token is what came from the user session cached during authentication. And the provided loginID is based on the format for the Cognito user pool.
Here is some of the sample javascript code:
this.loginId = 'cognito-idp.' + this.region + '.amazonaws.com/' + this.userPoolId;
this.poolData = {
UserPoolId : this.userPoolId,
ClientId : this.clientId
};
this.userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(this.poolData);
cognitoUser.getSession(function(err, session) {
if (err) {
console.log(err);
console.log("user session expired. needs to log in");
this.navigateToLogin();
return;
}
var token = session.getIdToken().getJwtToken();
AWS.config.credentials.params.Logins[this.loginId] = token;
AWS.config.credentials.refresh(function(err){
if (err) {
alert(err);
}else{
onLoggedIn();
}
});
console.log('session validity: ' + session.isValid());
}.bind(this));
What is baffling me is that it used to work! And sometimes after many days of logging in and out I am able to get it to work again. But now it has all together stopped working. I wonder if this is a bug since this service is still in beta, or if there is something I'm doing wrong.
That exception is thrown from Cognito Federated Identities, not User Pools, so it wouldn't be because of service instability. It means that the logins key you gave doesn't match with what is linked to the pool and was configured from the console.
I'd double check that you have it configured on the console correctly, and if so, add some logging to see what is being sent as the key in the logins set when it does not work vs when it does.