POST, PUT and PATCH resources not working in WSO2 Api Gateway - wso2

I am quite new to the WSO2 tools. I recently started using the WSO2 API Manager(ver. 3.1.0).
I created an API gateway by importing the httpbin swagger specs: https://github.com/Azure/api-management-samples/blob/master/apis/httpbin.swagger.json. I published the API, subscribed to it, generated the API keys and started testing.
I imported the spec in Postman, configured the API key for authorization, changed the server to the local gateway http://localhost:8280/Api_Base/1.0
All the resources defined with GET method were accessible, but the POST, PUT and PATCH resources
were not reachable via the gateway. I received the following error response "<faultstring>unknown" for these resources. I tried with cURL as well but got the same results. When I tried POST for httpbin directly it was working just fine:
curl --location --request POST 'http://httpbin.org/post'
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Host": "httpbin.org",
"User-Agent": "curl/7.58.0",
"X-Amzn-Trace-Id": "Root=1-5e8e0d39-ddf21f1055008f60707cf150"
},
"json": null,
"origin": "95.103.xxx.xxx",
"url": "http://httpbin.org/post"
}
and via my API gateway(with API key as well):
curl --location --request POST 'http://localhost:8280/HTTP_Bin_Mock/1.0/post'
<faultstring>unknown</faultstring>
What could have gone wrong?

please try below CURL command
curl --location --request POST 'http://localhost:8280/HTTP_Bin_Mock/1.0/post' --data '{}' --header 'Content-Type: Application/JSON'

Related

Manual Authentication with Amazon Cognito

I know of two ways to authenticate as a user and obtain the access token, one is through the Hosted UI and another with various provided SDKs.
What I'm looking for is an endpoint obtain the access token directly with user credentials.
POST https://that-special-endpoint.com/login
{
username: "example#email.com",
password: "Abc123456",
...client ID, etc.
}
I've searched for some time but could not find how to do this. Is this not possible due to some security concerns that I'm not aware of?
I did consider creating a Lambda API and make use of the Cognito SDK to cater for my use case but I'm not sure if it's advisable...
Similar question is answered here. You can access https://cognito-idp.[region].amazonaws.com/ to call InitiateAuth and RespondToAuthChallenge APIs.
InitiateAuth
Create a json file, aws-auth-data.json
{
"AuthParameters": {
"USERNAME": "your-email#example.com",
"PASSWORD": "your-first-password",
"SECRET_HASH": "......(required if the app client is configured with a client secret)"
},
"AuthFlow": "USER_PASSWORD_AUTH",
"ClientId": "5m........................"
}
Send a request on https://cognito-idp.us-east-2.amazonaws.com/ (if the user pool is on us-east-2 region) to call InitiateAuth API and initiate an authentication flow.
curl -X POST --data #aws-auth-data.json \
-H 'X-Amz-Target: AWSCognitoIdentityProviderService.InitiateAuth' \
-H 'Content-Type: application/x-amz-json-1.1' \
https://cognito-idp.us-east-2.amazonaws.com/
Then you'll get the user's tokens.
{
"AuthenticationResult": {
"AccessToken": "eyJra........",
"ExpiresIn": 3600,
"IdToken": "eyJra........",
"RefreshToken": "eyJjd........",
"TokenType": "Bearer"
},
"ChallengeParameters": {}
}
RespondToAuthChallenge
You may get a challenge as InitiateAuth response. For example, you will be asked to change password when you make a first 'InitiateAuth' attempt:
{
"ChallengeName": "NEW_PASSWORD_REQUIRED",
"ChallengeParameters": {
"USER_ID_FOR_SRP": "abababab-......",
"requiredAttributes": "[]",
"userAttributes": "{\"email_verified\":\"true\",\"email\":\"your-email#example.com\"}"
},
"Session": "DNdY......"
}
In this case, change the password with RespondToAuthChallenge and you will get tokens.
{
"ChallengeName": "NEW_PASSWORD_REQUIRED",
"ChallengeResponses": {
"USERNAME": "your-email#example.com",
"NEW_PASSWORD": "your-second-password"
},
"ClientId": "5m........................",
"Session": "DNdYN...(what you got in the preceding response)"
}
curl -X POST --data #aws-change-password.json \
-H 'X-Amz-Target: AWSCognitoIdentityProviderService.RespondToAuthChallenge' \
-H 'Content-Type: application/x-amz-json-1.1' \
https://cognito-idp.us-east-2.amazonaws.com/
See also:
https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html
https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html
https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-authentication-flow.html#amazon-cognito-user-pools-client-side-authentication-flow

Why did my POST to AWS API Gateway failed?

I use POSTMAN to test my Cloudformation created APIs
POST https://6pppnxxxh.execute-api.eu-central-1.amazonaws.com/Prod/users
I got
{
"message": "Missing Authentication Token"
}
My prod stage
I doublechecked PROD Invoke URL.
How to solve this problem?
I tried with curl
curl --header "Content-Type: application/json" --request POST --data '{ "emailaddress" : "acj#rambler.ru,"first name" : "Aca","last name" : "Ljubascikic", "password" : "bbbac_96"}' https://6pppnxxxh.execute-api.eu-central-1.amazonaws.com/Prod/users
The same issue
{"message":"Missing Authentication Token"}
How to test from CLI?
According to your screenshot /Prod/users is a PUT method and you are using POST in your command. I would confirm that first.
Hope this helps.

Difference in request body in aws api gateway test and curl

I'm trying to add a POST HTTP method to my AWS API Gateway. I'm using SAM framework with Python.
I find that there is a difference in the "body" of the response when it is generated from my desktop (curl or postman) and the AWS API Gateway 'TEST'
Right now, the "POST" command only prints the 'event' object received by the lambda_handler. (I'm using an object to store the event as you can see below)
def add(self):
response = {
"statusCode": 200,
"body": json.dumps(self._event)
}
return response
When I'm using the 'TEST' option of the API Gateway console, with the input:
{"username":"xyz","password":"xyz"}
I receive the following output:
{
"body": "{\"username\":\"xyz\",\"password\":\"xyz\"}",
<the rest of the response>
}
However, when I'm sending the curl (or postman) request:
curl --header "Content-Type: application/json" --request POST --data '{"username":"xyz","password":"xyz"}' <aws api gateway link>
I get the following response:
{
"body": "eyJ1c2VybmFtZSI6Inh5eiIsInBhc3N3b3JkIjoieHl6In0="
<the rest of the response>
}
Why do you think there is a difference between the two tests?
Curl and Postman seem to be automatically Base64 encoding your Authentication credentials.
The responses are the same. The latter response is a Base64-encoded token of the first response.

wso2 application creation using using rest api,

While creating application in wso2 i need to send Bearer token. But for login wso2 /token api i need an application
apim:subscribei
Request
POST https://localhost:9443/api/am/store/v0.12/applications
Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8
{
"throttlingTier": "Unlimited",
"description": "sample app description",
"name": "sampleapp",
"callbackUrl": "http://my.server.com/callback"
}
Ref:https://docs.wso2.com/display/AM220/apidocs/store/index.html#!/operations#ApplicationIndividual#applicationsApplicationIdKeysKeyTypeGet
Please read the Getting started link on the same page.
https://docs.wso2.com/display/AM220/apidocs/store/index.html#guide
Eg.
curl -k -X POST -H "Authorization: Basic YWRtaW46YWRtaW4=" -H "Content-Type: application/json" -d #payload.json https://localhost:9443/client-registration/v0.12/register
Sample request body:
{
"callbackUrl": "www.google.lk",
"clientName": "rest_api_store",
"owner": "admin",
"grantType": "password refresh_token",
"saasApp": true
}

number of instances the cloud foundry app is running

my app needs to get the number of instances in which its running, (in runtime my app uses this info in my program logic).
(VCAP_APPLICATION env variables cannot provide this info. )
Calling API directly and using "instances" attribute is an option, but I dont know how to call apps API directly in my app. Please let me know how to call it.
Below is the link I got for app API:
http://apidocs.cloudfoundry.org/218/apps/retrieve_a_particular_app.html
In order to use the API, you first need to authenticate. In order to authenticate, you need to retrieve the authorization endpoint.
To retrieve the authorization endpoint, issue the following curl request (I am using pivotal web services in this example, but you would replace https://api.run.pivotal.io with the cloud foundry api endpoint you are using.
curl -H 'content-type: application/x-www-form-urlencoded;charset=utf-8' \
-H 'accept: application/json;charset=utf-8' \
https://api.run.pivotal.io/v2/info
You'll get back something that looks like this:
{
"name": "vcap",
"build": "2222",
"support": "http://support.cloudfoundry.com",
"version": 2,
"description": "Cloud Foundry sponsored by Pivotal",
"authorization_endpoint": "https://login.run.pivotal.io",
"token_endpoint": "https://uaa.run.pivotal.io",
"min_cli_version": null,
"min_recommended_cli_version": null,
"api_version": "2.36.0",
"app_ssh_endpoint": "ssh.run.pivotal.io:2222",
"app_ssh_host_key_fingerprint": "e7:13:4e:32:ee:39:62:df:54:41:d7:f7:8b:b2:a7:6b",
"logging_endpoint": "wss://loggregator.run.pivotal.io:443",
"doppler_logging_endpoint": "wss://doppler.run.pivotal.io:443"
}
Grab the authorization_endpoint value, in this case it is:
https://login.run.pivotal.io
You now need to grab an authentication token. Issue the following curl command replacing the [my user name] and [my password] and [my authorization endpoint] with your values. Please note that you should url encode your password.
curl -H 'content-type: application/x-www-form-urlencoded;charset=utf-8' \
-H 'accept: application/json;charset=utf-8' \
-H 'authorization: Basic Y2Y6' \
-d "username=[my user name]&password=[my password]&grant_type=password" \
[my authorization endpoint]/oauth/token
You will get a response that looks like this:
{
"access_token": "very_long_token.very_long_token.very_long_token",
"token_type": "bearer",
"refresh_token": "very_long_token.very_long_token.very_long_token",
"expires_in": 599,
"scope": "cloud_controller.read password.write cloud_controller.write openid",
"jti": "shorter_value"
}
You are interested in the access_token value (access_token, refresh_token, and jti have been changed from the actual values in this example)
Now we are finally at the point where we can use the api to get the information about our app. You could use the link you provided above, but to use that api endpoint, you need the guid of your app. Instead I would recommend using the List all Apps endpoint and use a query filter on it to get your app information. Here is the curl command (replace [my authorization token] with your auth token from the previous step, replace [my api endpoint] with the api endpoint you use for cloud foundry, replace [my app name] with the name of your app:
curl -H "authorization: bearer [my authorization token]" \
[my api endpoint]/v2/apps?q=name:[my app name] -X GET
You'll receive a message that looks like this:
{
"total_results": 1,
"total_pages": 1,
"prev_url": null,
"next_url": null,
"resources": [
{
"metadata": {
"guid": "blah-blah",
"url": "/v2/apps/blah-blah",
"created_at": "time_stamp",
"updated_at": null
},
"entity": {
"name": "my-app",
"production": false,
"space_guid": "blah-blah",
"stack_guid": "blah-blah",
"buildpack": null,
"detected_buildpack": null,
"environment_json": {
},
"memory": 1024,
"instances": 3,
"disk_quota": 1024,
"state": "STOPPED",
"version": "blah-blah",
"command": null,
"console": false,
"debug": null,
"staging_task_id": null,
"package_state": "STAGED",
"health_check_type": "port",
"health_check_timeout": null,
"staging_failed_reason": null,
"staging_failed_description": null,
"diego": false,
"docker_image": null,
"package_updated_at": "time stamp",
"detected_start_command": "",
"enable_ssh": true,
"docker_credentials_json": {
"redacted_message": "[PRIVATE DATA HIDDEN]"
},
"space_url": "/v2/spaces/blah-blah",
"stack_url": "/v2/stacks/blah-blah",
"events_url": "/v2/apps/blah-blah/events",
"service_bindings_url": "/v2/apps/blah-blah/service_bindings",
"routes_url": "/v2/apps/blah-blah/routes"
}
}
]
}
You can grab the instances from the message. If you want to use the api in your original link, you can grab the metadata.guid for use in that call.
Hope that helps!
I was looking for something similar but using cf cli, to get the instance count of my app in a shell script. I came up with this and it works.
cf app my_app_name|grep instances|cut -d'/' -f2
I understand this post might not be related, but i would be happy if it helps someone.
Though it is late now to reply - an alternate solution would be to have a service discovery component like Eureka and let your application register to it. From the discovery client, you can get the number of instances for this application.
Be aware though, the state of instances would be eventually consistent on Eureka. We are using this pattern for a cluster broadcast use case.
create a container to container link with the name myapp.apps.internal. Then count the IP's returned by a DNS lookup of myapp.apps.internal.