Add authentication to an existed API using WSO2 AM - authentication

I have created an API using WSO2 EI that looks like https://localhost:8243/services/ABC.
Then I want to create another API that gets above API as the endpoint in order to add authentication. So how can I pass value to URL pattern and endpoint to get that?
When URL pattern is /xyz, and the endpoint is https://localhost:8243/services/ABC. It points to https://localhost:8243/services/ABC/xyz that not my endpoint.
Thank you so much!

You can attach a custom sequence to the API.
<sequence xmlns="http://ws.apache.org/ns/synapse" name="header_sequence">
<property name="REST_URL_POSTFIX" scope="axis2" action="remove"/>
</sequence>
This drops the resources and not appending to the path.
Please refer - https://apim.docs.wso2.com/en/latest/deploy-and-publish/deploy-on-gateway/api-gateway/message-mediation/mapping-the-parameters-of-your-backend-urls-with-the-api-publisher-urls/#mapping-the-parameters-of-your-backend-urls-with-the-api-publisher-urls

As per my understanding, you are trying to invoke the backend https://localhost:8243/services/ABC via the API created in APIM. You can try out the following to achieve it,
In the API created in APIM, you can simply add the URL https://localhost:8243/services as the endpoint and then create a resource path as /ABC.

Related

Replicated API in multiple backends WSO2 API Manager

I have one API replicated in multiple backends. I don't have any condition that can differentiate between backends. I tried to use dynamic endpoints and change the message mediation flow:
https://apim.docs.wso2.com/en/latest/deploy-and-publish/deploy-on-gateway/api-gateway/message-mediation/changing-the-default-mediation-flow-of-api-requests/
However, the only difference between requests is the IP address of the backend server:
https://{uri.var.host}/resource
I'm thinking to create every time the API and change the endpoint address but this solution can be complex as I will have the same API replicated many times (around 100) in the wso2 api manager. There is any other solution that can fit my use case?
We can make use of Dynamic Endpoints to achieve your requirement. But, it is required that the client applications need to either send a param or a Header to filter and construct the BE server URL in the mediation sequence to route the requests in the API Manager.
If the client applications can send a header specifying a unique (server) name or any other value while invoking the API, we can use the key to filter (or perform a switch case operation) and construct the BE server URL in the mediation sequence and route them to the respective BE services. Refer to the following Docs for more information.
A sample mediation sequence will be as follows (the client application will be sending a header named as X-ServerName with a name)
<sequence xmlns="http://ws.apache.org/ns/synapse" name="dynamic-endpoint-seq">
<!-- extract the name from the header -->
<property name="server_name" expression="$trp:X-ServerName" />
<!-- switch case for all applicable names -->
<switch source="$ctx:server_name">
<case regex="server-one">
<property name="service_ep" value="http://server-one-ip/resource"/>
</case>
<case regex="server-two">
<property name="service_ep" value="http://server-two-ip/resource"/>
</case>
<default>
<property name="service_ep" value="http://server-default-ip/resource"/>
</default>
</switch>
<header name="To" expression="get-property('service_ep')"/>
</sequence>
Dynamic Endpoints in API Manager
Switch Mediator in WSO2

Adding header with username into request to backend in wso2 apimanager for all service

I am using apimanger 1.9.
I read this already : Add header with username into request to backend in wso2 apimanager.
I am able to add and forward username to backend in wso2 apimanager for specific service; but I want this for all service. I am modifying admin--<api_name>_<version>.xml for all services(50 services), which is very much manual. Something it leads to manual error.
Is there a single place configuration where I can set this (forward username to backend endpoint) for all service?
One more question - if I create and publish the APIs using "Publisher API" feature, is there a way to post something to set up the add header for each API?
Modify the velocity_template.xml which decides the template of an API. Please read my answer given to a similar requirement. You need to modify the relevant section in the velocity_template.xml.

WSO2 API Manager - "Make this the default version" causes authentication errors?

I have an API that works no problem providing the "Make this the default version" checkbox isnt checked, once checked I get this error back
<ams:fault
xmlns:ams="http://wso2.org/apimanager/security">
<ams:code>900906</ams:code>
<ams:message>No matching resource found in the API for the given request</ams:message>
<ams:description>Access failure for API: xxxx/xxxx, version: v0.1 with key: xxxxxx</ams:description>
</ams:fault>
Is there something I have missed at all?
Thanks,
Ash.
EDIT - Extra Detail and Logs
TID[-1234] [AM] [2014-07-10 13:05:56,238] ERROR
{org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler}
- API authentication failure org.wso2.carbon.apimgt.gateway.handlers.security.oauth.OAuthAuthenticator.authenticate(OAuthAuthenticator.java:157)
org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler.handleRequest(APIAuthenticationHandler.java:92)
org.apache.synapse.rest.API.process(API.java:285)
org.apache.synapse.rest.RESTRequestHandler.dispatchToAPI(RESTRequestHandler.java:83)
org.apache.synapse.rest.RESTRequestHandler.process(RESTRequestHandler.java:64)
org.apache.synapse.core.axis2.Axis2SynapseEnvironment.injectMessage(Axis2SynapseEnvironment.java:220)
org.apache.synapse.core.axis2.SynapseMessageReceiver.receive(SynapseMessageReceiver.java:83)
org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
org.apache.synapse.transport.passthru.ServerWorker.processNonEntityEnclosingRESTHandler(ServerWorker.java:344)
org.apache.synapse.transport.passthru.ServerWorker.run(ServerWorker.java:168)
org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
java.lang.Thread.run(Thread.java:744)
Please save and publish the API once you made the change to the API. This may be causing the issue.
Once you have published you should see 2 sets of production url (one with the version and one without the version). Please check if the same is available in the API store for your API.
You'll first want to turn on wire logs in that environment by editing your ../repository/conf/log4j.properties file and restarting the service. This will allow you to see the request headers for both the initial request to the gateway and the request from the gateway to itself (or other gateways in your cluster) since that's how requests to a default API version are resolved. This can help you identify whether your Authorization header values are actually making it to the authentication handler.
After you take a look at this, note that when you publish an API with a default version, you're actually creating (or updating) two separate synapse configurations for the API: a versioned configuration and an unversioned configuration. The portion of the latter's definition that you need to check is:
<else>
<header name="WSO2_AM_API_DEFAULT_VERSION" scope="transport" value="true"/>
<property name="uri.var.portnum" expression="get-property('https.nio.port')"/>
<send>
<endpoint>
<http uri-template="https://localhost:{uri.var.portnum}/myApi/v1">
<timeout>
<duration>60000</duration>
<responseAction>fault</responseAction>
</timeout>
</http>
</endpoint>
</send>
</else>
By default, the newly generated definition for the default version attempts to send the request to localhost, which may not be what you want. Check at ../repository/deployment/synapse-configs/default/api and make sure that this definition is correct.
Since it looks like this is actually an authentication error, you should also test a new subscription. Create a new application with some subscriber, subscribe to the API, and generate new access tokens. I wouldn't understand why (since setting a default version doesn't create a new API entry in the AM_API table) but this could possibly be due to the access token credentials being invalid for the default version, and generating new tokens should (in theory) test against this.

One Apigee Api Proxy with a different target endpoint for each environment

I am an Apigee beginner. We are doing a migration to Apigee.
We have our environments in our host names, for example:
something.int.other.thing.co.uk
something.test.other.thing.co.uk
something.stage.other.thing.co.uk
something.prod.other.thing.co.uk
I would like to be able to map them to the 4 environments of the apigee api proxy itself, respectively int, test, stage, prod.
I currently have one Rest resource for them, for example: /resource
Basically I would like the apigee api proxy with one rest resource, to map to 4 different target endpoints, depending on the environment.
So far I have tried to do it from the UI and have not been able to do so.
I have been going through the documentation and I have found these so far:
According to this it should be possible:
"An API proxy can contain zero or more TargetEndpoints." (TargetEndpoint section)
http://apigee.com/docs/api-services/content/api-proxy-configuration-reference
According to these, you can make routerules to the proxy endpoint, but I have not been able to implement it to the targetendpoint:
Create a New Endpoint on an existing API Proxy with "No Target Endpoint"
One API proxy calling two different target endpoints
I also tried doing something along the lines of this, for TargetEndpoint, where I tested for the environment name, but it didn't work:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<TargetEndpoint name="default">
<Description/>
<Flows/>
<PreFlow name="PreFlow">
<Request/>
<Response/>
</PreFlow>
<HTTPTargetConnection>
<URL>something.int.other.thing.co.uk</URL>
</HTTPTargetConnection>
<RouteRule name="int">
<Condition>environment.name == "int"</Condition>
<TargetEndpoint>something.int.other.thing.co.uk</TargetEndpoint>
</RouteRule>
<RouteRule name="test">
<Condition>environment.name == "test"</Condition>
<TargetEndpoint>something.test.other.thing.co.uk/</TargetEndpoint>
</RouteRule>
<RouteRule name="stage">
<Condition>environment.name == "stage"</Condition>
<TargetEndpoint>something.stage.other.thing.co.uk/</TargetEndpoint>
</RouteRule>
<RouteRule name="prod">
<Condition>environment.name == "prod"</Condition>
<TargetEndpoint>something.prod.other.thing.co.uk</TargetEndpoint>
</RouteRule>
<PostFlow name="PostFlow">
<Request/>
<Response/>
</PostFlow>
</TargetEndpoint>
So is this possible?
Apigee supports the concept of Target Servers -which abstracts the backend host from the proxies and also provides load balancing. Same target servers can be configured to point to different host for each environment (this concept is built in to Apigee already).
Take a look, this should help.
Srikanth
LoadBalancer and TargetServer settings go in the TargetEndpoint definition, specifically in the HTTPTargetConnection element.
Check the example here:
http://apigee.com/docs/api-services/content/load-balancing-across-backend-servers
If you do want to curl a TargetEndpoint definition to your API proxy, have a look at the following sample script to see working API calls:
https://github.com/apigee/api-platform-samples/blob/master/tools/proxy_gen.sh
This script shows you how to create an API proxy and update ProxyEndpoint and TargetEndpoints via API calls.

REST-Apache CXF-Schema validation

I am using RESTful Webservice using Apache CXF (blended with spring).
I am exposing two services in my WADL.
For every request to my Webservice,I need to validate request to a particular schema.One of my exposed service use a specific schema and other service complies to other specific schema.
Can you help me?
There is a couple of ways to do what you need. One way is using jaxrs:schemaLocations element:
<beans>
<jaxrs:server address="/" serviceClass="com.something.ServiceClass">
<jaxrs:schemaLocations>
<jaxrs:schemaLocation>classpath:/schemas/a.xsd</jaxrs:schemaLocation>
<jaxrs:schemaLocation>classpath:/schemas/b.xsd</jaxrs:schemaLocation>
</jaxrs:schemaLocations>
</jaxrs:server>
</beans>
For more information and examples please see this link.