I've trained a model on sagemaker and have created the endpoint. I'm trying to invoke the endpoint using postman. But when training the model and even after that, I have not specified any header for the training data. I'm at a loss as to how to create payload while sending a post request to sagemaker
Here's an example for calling the sagemaker endpoint created in the quickstart guide. You can call it using text/csv or application/json formats:
In Postman:
The url you want is POST https://runtime.sagemaker.{{region}}.amazonaws.com/endpoints/{{aws_model_name}}/invocations
In the Authorization tab, choose type AWS Signature and put in the values for your AccessKey and SecretKey (recommend you use variables for these), and sagemaker for Service Name.
Under Headers add:
Content-Type : text/csv
Accept: application/json
In Body: paste in your body, separated by commas (if yr following the quickstart guide, in the notebook you can simply run print(valid_set[0][60:61]) to get an example vector. You'll need to convert that value set into comma separated values
Clicking Send and you should be good to go!
For sending JSON data, change the Content-Type to application/json and you'll want the structure to look like this:
{
"instances":[
{
"configuration": {},
"features": [...]
}
]
}
Once the endpoint is created, you can invoke it as any other restful service, with credentials and payload.
I am guessing, there could be two places where might be stuck.
One could be, sending an actual PostMan Request with all the headers and everything.
Newer version of Postman has AWS Signature as one of the Authorization types. You can use that to invoke the service. There are no other spacial headers required. Note that there is a bug in Postman still open (issue-1663) that only affects if you are a AWS federated account. Individual accounts should not be affected by this issue.
Or, you could be stuck at the actual payload. When you invoke the SageMaker endpoint, the payload is passed as is to the model. If you want to preprocess the input before feeding it to the model, you'd have to implement an input_fn method and specify that when instantiating the model.
You might also be able to invoke SageMaker endpoint using AWS SDK boto3 as follows
import boto3
runtime= boto3.client('runtime.sagemaker')
payload = getImageData()
result = runtime.invoke_endpoint(
EndpointName='my_endpoint_name',
Body=payload,
ContentType='image/jpeg'
)
Hope this helps.
Related
So I am trying trying to execute a PutItem request from my AWS API Gateway. I am trying to do this by using the path /storeid/{username}/{password}. I have done the mapping as json and the test within the API works perfectly and I see my data show up in my DynamoDB table but when I deploy the API and try to invoke this request I receive the following response: {"message":"Missing Authentication Token"}. This request does not have any authorization or API key requirement. Why does the test work but not the url when invoked.
ps-yes I entered the correct url
Please help!
A few things to check
Verify that Authorization is set to None (i.e. not IAM) in your Method request settings.
Verify that you deployed your API changes to your stage. Using the console, click Actions -> Deploy API.
Once deployed the URL to use should be displayed when you select the Stage that you deployed to. Verify you are using the correct URL.
Also, side note, it is a really bad idea to be putting passwords in your URL path or query parameters. Consider doing sending the data in the request body as a POST and doing something like HTTPS and hashing to protect the password.
Unfortunately i cannot use AWS SDK and i must use REST API AWS services(i am working with Flutter WEB).
So i start to do research on aws docs and this is what i did:
Create bucket.
make all permission to be public(for test only)
open access point
Then at the postman i am using at "Auth" aws signature and added current keys,
except session token(my bucket is open and i understood that i dont need it, if i am mistaking pls correct me).
when i am sending the request i am getting an error:
Missing required header for this request: x-amz-content-sha256
Here is attachment images:
AWS Signautre
Body Request
Error message
Just ran into this issue too - the Service Name must be 's3' vs 'S3'.
advanced authorization settings
According to the AWS documentation, you need to send the x-amz-content-sha256 header in the request:
The x-amz-content-sha256 header is required for all AWS Signature Version 4 requests. It provides a hash of the request payload. If there is no payload, you must provide the hash of an empty string.
Seems like Postman is not adding it for some reason. You should check the Headers and add manually then.
try replacing S3 with s3 for the service name.
I too faced this issue and after adding session token parameter it got resolved. Postman has the provision to generate the below parameters,
X-Amz-Content-Sha256
Authorization
x-amz-security-token
X-Amz-Date
I've successfully setup AWS Gateway to validate the body of incoming POST requests using JSON Schema. I was so thrilled! Hooray I thought ... as I tested the functionality using the internal AWS tools ... but then I tested a POST request w/invalid data from a website using AJAX and then a CURL request, again using invalid data - and wouldn't you know it, both of them got through to my integration and triggered my AWS Lambda function, something JSON Schema was supposed to block! I've deployed the latest API to my endpoint and even set all of the "Content-Type" headers being called to the same JSON Schema AWS model. I'm at a loss for what's going on ... how do I enforce that all requests must be one content-type or return an error?
Thanks in advance for any help you could provide ...
The answer to my question for those of you who will stumble upon this issue.
By default, JQuery's ".post" method sets a Content-Type to "application/x-www-form-urlencoded." The model I set in AWs Gateway was only for "application/json" POST requests. I assumed that if I set the "request validator" to use JSON Schema models for a specific content-type that only the ones I defined would allowed to pass through ... oh no, no, no! AWS Gateway conveniently let any other Content-Type pass through unchecked, bypassing my JSON Schema model validator. Unbelievable actually. So the answer to enforce only application/json was to then move to the "integration request" and configure a body mapping for application/json setting the "When there are no templates defined (recommended)" option to true. And voila, problem solved. AWS Gateway will still allow your POST request to get to this stage, but it won't get to your "action (e.g. Lambda function).
I wanted to add ... it's no longer a problem, but even by setting multiple Content-Type patterns, the model was only enforced on the first one within AWS Gateway. Strange behavior ... maybe someone could help w/this?
This works fine using proper setting. Have your model set correctly including the validation you wish to apply.
For your method, go to Method Execution section and set
Settings -> Request Validator - select option as 'Validate Body'. Your may choose other appropriate options based on your requirement.
Request Body -> create new entry as 'application/json' and select your model.
Done. This will work as expected and throw 500 error for other Content-Type or if model validation fails.
Also, you can always validate request in Lambda's entry function. Though that is what you want to avoid to escape lambda trigger cost.
Additional Tip: Make sure you have API Rate limit set properly as you will get charged if your API is caught by spammers/attackers, though validation through model will protect you but you will still get charged by AWS. In case of API Key set, this is still applicable.
I have created an API Key and added it to my functions. I have then deployed the api and tested it but still get:
"message": "Forbidden"
How do I pass the api key with my JSON request as I have been using "x-api-key": "theKey"?
The x-api-key parameter is passed as a HTTP header parameter (i.e. it is not added to the JSON body). How you pass HTTP headers depend on the HTTP client you use.
For example, if you use curl and assuming that you POST the JSON payload, a request would look something like (where you replace [api-id] with the actual id and [region] with the AWS region of your API):
$ curl -X POST -H "x-api-key: theKey" -H "Content-Type: application/json" -d '{"key":"val"}' https://[api-id].execute-api.[region].amazonaws.com
I had to add an API Usage plan, and then link the plan to the API stage.
Seems like this is the only way to link the key to the API, not sure if this is a recent change on AWS.
If you set 'API Key Required' option to true, please check below.
you have to pass 'x-api-key' HTTP Header Parameter to API Gateway.
The API Key had to be created.
In addition, you need to check a Usage Plan for the API Key on API Gateway Console.
If you set 'API' key required to true, you need to pass the api key as header.
API Key is passed as header field 'x-api-key'. Even after adding this field in header, this issue may occur. In that case, please validate below points
Do you have a Usage Plan? if not need to create one.
Link you API with Usage Plan. For that add a stage, it will link your API
Do you have API Key? if not you need to create an API Key and enable it.
Add the Usage Plan which is linked with your API to this API Key. For that, add Usage Plan.
I hope you are not missing to link the API key with the API
I was able to get a successful response from Lambda using below configuration in Postman native app -
Under authorization tab (For some reason this didn't work when i passed the same parameters under header)
Key : x-api-key
Value : your-api-key-value
Add to : Header
I don't have enough reputation to set this as a comment, But I was finally able to find the document specifying that 'x-api-key' belongs in the header for API Gateway calls that come from outside clients (like postman, swagger, etc.) in the AWS Documentation.
The relevant part:
To use header-sourced API keys:
Create an API with desired API methods. And deploy the API to a
stage.
Create a new usage plan or choose an existing one. Add the deployed
API stage to the usage plan. Attach an API key to the usage plan or
choose an existing API key in the plan. Note the chosen API key
value.
Set up API methods to require an API key.
Redeploy the API to the same stage. If you deploy the API to a new
stage, make sure to update the usage plan to attach the new API
stage.
The client can now call the API methods while supplying the x-api-key
header with the chosen API key as the header value.
Choose an API key source
For Private API Gateways accessed through public DNS, we need to pass additional header of 'x-apigw-api-id' with the api id along with 'x-api-key' if configured.
curl -v https://{vpce-id}.execute-api.{region}.vpce.amazonaws.com/test -H 'x-apigw-api-id:{api-id}'
Its documented below,
https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-private-api-test-invoke-url.html#w20aac13c16c28c11
Here a good resource explaining different reasons why we could be getting a Forbidden. The two most important are the request URL and the x-api-key header:
https://{api_id}.execute-api.{region}.amazonaws.com/{stage_name}/{resource_name}
Missing stage name will give you 403 for ex. Maybe for security reasons the response is not revealing an issue with the stage name, and thus you get a generic Forbidden.
I faced the same problem today. I had already mapped the API key to the usage plan (which was linked to the api gateway stage). I was also passing the api key in header correctly.
When none of these solutions work, do remember to check if your API is linked to WAF policy with only a certain ip-addresses permitted. Apparently, my IP address had changed today. So, WAF was blocking me. That can be an additional reason to get {"message": "Forbidden"} error.
Pretty self explanatory title. I'm using API Gateway in AWS, requiring an API key to access a backend written in Django (not using lambda). I need to know how to access the API key used in the request to keep track of who did what at the app level.
You can use mapping templates and get the API Key from the $context variable, it’s the apiKey property inside the identity object: http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html#context-variable-reference
Create a mapping template for your requests and include the property in it. For example, if you wanted to include the entire request body + the API Key you would do this:
{
"body": $input.json('$'),
"apiKey": "$context.identity.apiKey"
}
Depending on how your backend application is built, you could send the API key to your application in a HTTP parameter (path, query string, or header) or in the request body. Please have a read through the docs on how to move data between the two systems.
Thanks,
Ryan
Here is how I finally made it work. At the top or bottom of the template, include this line.
#set($context.requestOverride.header.x-api-key = $context.identity.apiKey)
When your backend receives this request, the api key will be in the header x-api-key.
Here is a basic mapping template that just forwards the (json) body and the header.
$input.json("$")
#set($context.requestOverride.header.x-api-key = $context.identity.apiKey)
API Gateway uses the X-API-Key header, so I like for my backend to also use that. That way I can use the same testing commands with only the URL being different.