AWS Api Gateway: passing a multipart/form-data - amazon-web-services

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

Related

Canonical Request to AWS Signature 4 is correct?

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.

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"
}
}

Import dashboard in superset through api

I'm trying to import the Superset dashboard through API but currently not successful yet.
I'm following Superset API docs to import with endpoint
/api/v1/dashboard/import
My import payload as bellow:
POST /api/v1/dashboard/import/ HTTP/1.1
Host: localhost:8088
Authorization: Bearer <access token>
Content-Length: 289
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="formData"; filename="20210615_065115.json"
Content-Type: application/json
(data)
----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="overwrite"
True
----WebKitFormBoundary7MA4YWxkTrZu0gW
I got a response with status 200 but the dashboard not import, and in the preview response on postman a got output as the image below:
Anybody can help with this issue?
Thanks.
Superset documentation isn't very clear about this but I finally managed to solve this problem.
As you can see your response is redirecting you to a login page.
What you need to do is to first make a GET request to /api/v1/security/csrf_token/
And add header in your request to /api/v1/dashboard/import
'X-CSRFToken': csrf_token
Another thing incorrect thing in the documentation is that Content-type is not multipart/form-data; but it is text/html; charset=utf-8
So basically in your call you don't need to pass Content-type in headers
Python example:
import requests
headers = {
'accept': 'application/json',
'Authorization': f'Bearer {jwt_token}',
'X-CSRFToken': csrf_token
}
files = {
'formData': (
dashboard_path,
open(dashboard_path, 'rb'),
'application/json'
)
}
response = self.session.post(url, files=files, headers=headers)
EDIT 30.08.2021
I've noticed that for some reason when I was running Superset with AUTH_TYPE = AUTH_OAUTH on production the solution above stopped working.
It requires additionally header Referer to be included in headers, so more safe option would be
import requests
headers = {
'accept': 'application/json',
'Authorization': f'Bearer {jwt_token}',
'X-CSRFToken': csrf_token,
'Referer': url
}
files = {
'formData': (
dashboard_path,
open(dashboard_path, 'rb'),
'application/json'
)
}
response = self.session.post(url, files=files, headers=headers)

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."

Amazon AWS IAM Returns 302 on POST request (signature version 2)

This is my exact request: minus credentials (throw away key and cert)
POST / HTTP/1.1
Host: iam.amazonaws.com
cache-control: no-cache
connection: close
content-type: application/x-www-form-urlencoded; charset=utf-8
Accept: */*
User-Agent: Falcraft CMF
AWSAccessKeyId=XXX&Action=UploadServerCertificate&CertificateBody=-----BEGIN CERTIFICATE-----
MIIBoDCCAQugAwIBAgIBADALBgkqhkiG9w0BAQUwFzEVMBMGA1UECgwMRmFsY3Jh
ZnQgQ01GMCIYDzIwMTQwMzA4MDMxMzU1WhgPMjAxNTAzMDgwMzEzNTVaMBcxFTAT
BgNVBAoMDEZhbGNyYWZ0IENNRjCBnTALBgkqhkiG9w0BAQEDgY0AMIGJAoGBAMVc
9fFg0hT12K9pVSjAAoRPXzMDgybMWFiRtEVBAVy75i80p9B0A2K+si1T05ou2rb6
CHrDjp3XF/RuXhhPsXletJDpCcSlShKDPVFWlIa7AlzrFn/RuZN+sjzzhiO+TWJD
YS5oO8KGLgFehnaEDzUTlCVoxCtXiDSomcP5zgVlAgMBAAEwCwYJKoZIhvcNAQEF
A4GBAJ/YWAwMv0GO7BzAkBQkHg3R5PMwUqep2qKelI6gjfHD8gMO5D6grswuCm9o
DxN3ztilNWMU6C8P0m57g31kk60h62Som8vOHJp55JLqNaWrKUBd1zZo9Fy4jGxj
a7Ec1drUZWuivzzy0qPATGzOISaAPcGkajPX/h46cvmotav7
-----END CERTIFICATE-----&Path=/&PrivateKey=-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDFXPXxYNIU9divaVUowAKET18zA4MmzFhYkbRFQQFcu+YvNKfQ
dANivrItU9OaLtq2+gh6w46d1xf0bl4YT7F5XrSQ6QnEpUoSgz1RVpSGuwJc6xZ/
0bmTfrI884Yjvk1iQ2EuaDvChi4BXoZ2hA81E5QlaMQrV4g0qJnD+c4FZQIDAQAB
AoGAIfjzeN4yq1r6No+KEh6jEEVdXLmhDL+mAXDrN/SNmHnbkIqezFn77zZmEzlX
tjWUfmShqwgYd4D75Z5N4h9tq+nza3WlOeQBO8f+lSatO1D5YT8TW6sXbTsjDxPx
zjJr3QS7/wWpzp1MDn+oBUlju+KT6RWExWrx2CSSbf1Td+0CQQDM7fzdvIIXbmZY
v94NZqZJHv+cyspD0BOBT5sWjf1+9CND4SmFNS4dSIQsncsQR1jJ40HJesYQRXN/
dGsFMNkzAkEA9ow/dzyowh4IIriEWFompwT3xFTE/4Lf8h96jwtMkiGjYOAhK4im
W4mnrsyq92ZXo9rhALYNH1Z5CGjYszmXBwJBAMIvfV5L42X6mgbdALfoHgfJ1OMp
EhLCF8l/unDb6WqkQspukN6F7wWWkpCIkUQCp3Le4pbdvNLsTK5ojYSkrhsCQGQc
EI0nCVNBBIasq7iAap946e5DiXZCuxJCa+53ZREVLZThjTZzFzGmFHtqyaUJXl6/
OouiYHOwFhcvE4a6xLMCQQCpUeCFtsYybHn0S5CCGUXOExtbnSjjMrSdNKc7f3wj
G427Mw18d+YurVrgq7qDH58VX2z+j9ITJPlWAtIetMwG
-----END RSA PRIVATE KEY----&ServerCertificateName=testCertificate1&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2014-03-08T03:13:56.000Z&Version=2010-05-08&Signature=XXXX
Here is my exact reply:
HTTP/1.1 302 Moved Temporarily
x-amzn-RequestId: b036aa40-a66f-11e3-9c2e-71bc7ad65b2e
Location: http://aws.amazon.com/iam
Content-Length: 0
Date: Sat, 08 Mar 2014 03:13:57 GMT
I've looked quite a bit at my code, request, and google, but haven't found anything substantial to this problem.
Here's the answer:
Make sure you put a content-length header in your POST request (yeah, I know, overlooked it)
The content-length header must be the length of your request urlencoded!
urlencode your request (body) as well.
Then you should get a 200.
Hope this helps someone!