Adding custom handler to specific API wso2 API-Manager - wso2

I need to add a custom handler and APIAuthenticationHandler to a specific API and it needs to be added below the
handler class="org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler"/>
(Note that APIAuthenticationHandler is called twice here, it's a custom requirement)
How can I do this programmatically by editing the velocity_template.xml
I'm using API-Manager 2.00
Thank you

You can use API custom properties for this. Add a custom property (e.g. auth_mode=Inhouse) to the API and then based on that, update the handler section in the velocity template like this.
<Handlers>
#foreach($handler in $handlers)
#if(($handler.className ==
"org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler") &&
($apiObj.additionalProperties.get('auth_mode') == "Inhouse"))
<handler xmlns="http://ws.apache.org/ns/synapse" class="$handler.className">
#if($handler.hasProperties())
#set ($map = $handler.getProperties())
#foreach($property in $map.entrySet())
<property name="$!property.key" value="$!property.value"/>
#end
#end
</handler>
<handler class="org.wso2.apim.custom.extensions.CustomAuthHandler"/>
<Handlers>
If you can't use custom properties, you can use $!apiName variable.

if ($!apiName.toLowerCase().endsWith("basic"))
#else

Related

Retrieve end user information from IdP in a sequence

There is a legacy Rest service which has its own authentication architecture (self-owned db to store user information and using basic auth). Other rest services are all using Keycloak as IdP (with OpenID as token).
I'm trying to use WSO2 API manager before the legacy Rest API that it can authenticate calls using OpenID just as other api services. I found there's a guide saying how to pass the end user attributes to the back-end service and also how to pass a custom authorization token to the back-end service.
And now, I want to know whether it is possible to retrieve the caller's id (viz., the end user id) in a sequence or not? It means I can get the end user's id from a property, modify it and then set it to the Authorization header.
Thus, the complete process seems as:
An end user generates a JWT token from Keycloak
The end user calls an api published by API Manager with the token
API Manager retrieves the end user's userid and sets it into the Authorization header
API Manager calls the back-end service with the changed Authorization header
You can try implementing the following sequence as an in-sequence to your API. The following sequence retrieves the End User ID using the Synapse Properties and assigns it to the Authorization Header.
<?xml version="1.0" encoding="UTF-8"?><sequence xmlns="http://ws.apache.org/ns/synapse" name="username-header">
<property name="userid" expression="$ctx:api.ut.userName"/>
<!-- property name="userid" expression="$ctx:api.ut.userId"/ -->
<log level="custom">
<property name="User ID" expression="$ctx:userid" />
</log>
<property name="Authorization" expression="$ctx:userid" scope="transport" action="set" />
</sequence>
Furthermore, you can also try using the following Synapse properties, if the above doesn't fulfil your requirement.
api.ut.username
api.ut.userId
If you are trying to read the end user's ID from the Backend JWT token that is generated by the API Manager during the API invocation, then it is required to come up with an extended mediation sequence, to read and decode the Token, and then to extract the information. Given below is a sample (not complete) if the requirement is as described above
<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="admin--AssertionAPI:v1.0.0--In">
<property name="assertion" expression="$trp:X-JWT-Assertion" />
<log level="custom">
<property name="Assertion" expression="$trp:X-JWT-Assertion" />
</log>
<property name="Body" expression="base64Decode(fn:substring-before(fn:substring-after($ctx:assertion, '.'), '.'))" />
<log level="custom">
<property name="body" expression="$ctx:Body" />
</log>
<!-- use script mediator to access required properties -->
<!-- and set the value as a header -->
</sequence>

WSO2 API Manager Mask a Service

Is possible generated a mask in services in API Manager?, similar to:
Original Services in API:
http://API/v1/profile
http://API/v1/account
With mask:
http://API/v1/user-profile
http://API/v1/user-account
My ideas are:
In Publisher Page -> Runtime Configurations add a Message Mediation that deleted the user- of the service with mask.
In API Definition, in Publisher Page, edit the JSON Swagger in the services put some mask. This is a example whit TAG in Swagger:
tags:
- "/v1/kyc-perfil"
Is Possible or not generated a mask in service in API Manager?
EDIT:
After to read the answer of Bee, works but in two or more service the request in every service is the same and diferent of the service original.
I tried to put similar this:
<property name="/v1/kyc-{DYNAMIC-PARAMETER}" expression="get-property('axis2', 'REST_URL_POSTFIX')"/>
<property name="REST_URL_POSTFIX" value="/v1/{DYNAMIC-PARAMETER}" scope="axis2"/>
You can do option 1. Use the REST_URL_POSTFIX property. Try this.
Read:
<property name="post_fix" expression="get-property('axis2', 'REST_URL_POSTFIX')"/>
Write:
<property name="REST_URL_POSTFIX" value="new_post_fix" scope="axis2"/>
Ref: https://docs.wso2.com/display/ESB470/HTTP+Transport+Properties#HTTPTransportProperties-Property:REST_URL_POSTFIXREST_URL_POSTFIX

WSO2 ESB. Accessing Secure Vault programmaticaly

I am implementing handler for REST API in Java (org.apache.synapse.rest.Handler interface). And there is a case, when I need to access Secure Vault and get a value.
I know that you are able to achieve this by expression="wso2:vault-lookup('YOUR.KEY.HERE')" in sequence, but can't find api to do this in handler. I believe that org.apache.synapse.MessageContext can help, but not sure how.
You can use below code segment in the custom handler.
public String getSecretPassword(String alias, MessageContext messageContext){
RegistrySecretRepository regRepo = new RegistrySecretRepository();
regRepo.setSynCtx(messageContext);
return regRepo.getSecret(alias);
}
Dependency for pom.xml, the version needs to be changed according to your product version.
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.mediation.security</artifactId>
<version>4.2.0</version>
</dependency
Please refer - http://malantech.blogspot.com/2016/10/basic-authentication-handler-with.html
Thanks
I believe you will not be able to get the value of the security vault directly from your handler so I advise you to recover the password and put it in a property and inside your handler to retrieve the property.
<property name="passwordvault"
expression="wso2:vault-lookup('YOUR.KEY.HERE')"
scope="default"/>
And use the MessageContext to get the propertie like this:
context.getProperty("passwordvault");
That's just a workaround which is not advisable , i believe you can try below code as i have used similar earlier as well and it worked
<property expression="wso2:vault-lookup('ei.training.userid')" name="UserID" scope="default" type="STRING"/>
<log>
<property expression="wso2:vault-lookup('ei.training.userid')" name="UID"/>
</log>
And I will answer my own question.
I've created a dummy sequence and placed it into Registry
<sequence name="SecureVaultSeq" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<property expression="wso2:vault-lookup('MY.PASS')" name="NAME"
scope="default" type="STRING"
xmlns:ns="http://org.apache.synapse/xsd" xmlns:ns3="http://org.apache.synapse/xsd"/>
</sequence>
Then in my handler i retrieved it like this:
messageContext.getConfiguration().getSequence("conf:Resources/sequences/SecureVaultSeq.xml").mediate(messageContext);
key = (String) messageContext.getProperty("NAME");
Hope this will help someone.

WSO2 ESB Collout address from Property or XPath-expression

I have the config with development and production sections. This sections contain the URLs of backends. In my inSequence i need it to Callout to these backends several times per request.
<config>
<env>prod</env>
<backend env="prod">http://localhost:1234/</backend>
<backend env="dev">http://localhost:2345/</backend>
</config>
I read this config from Local Entry (as XML) and want to set Callout's URL as an Property.
I don't want to hardcode these backends inside my code with "Switch" statement, because it's possible to use more than two environments.
Could you please show me an example?
Thank you.
You can read xml file in registry. Simply define property of OM type like this:
<property name="test" expression="get-property('registry','conf:/test.xml')" scope="default" type="OM" />
Then you can see the value by logging like this:
<log level="custom"> <property name="test.b" expression="$ctx:test//b" /> </log>
And in the xml file that you have put in the root of registry, you would fill it like:
<a>Hello<b>WSO2</b></a>
I have learned it from this link.
I found the answer. According to source of Callout mediator:
CalloutMediator.java
It uses "To" header if URL is not specified.

How to pass parameters to XSLT from JBoss Actions Pipeline

Say I have a given action:
<service category="MyService" name="MyFirstService">
<actions mep="RequestResponse">
<action class="actions.CXFListenerAction" name="CXFServiceListener"/>
<action class="org.jboss.soa.esb.actions.transformation.xslt.XsltAction" name="Transform XML">
<property name="templateFile" value="/stylesheets/transform_response.xslt"/>
<property name="failOnWarning" value="true"/>
</action>
</actions>
I am trying to figure out how to add a property name or parameter that I could then access from within the XSLT. I've tried add additional property names,
<property name="param1" value="Hey!"/>
but I'm not 100% sure if this is correct for adding parameters accessible by the XSLT.
Thanks.
The properties defined for the XsltAction class are properties specific to that action class and are not related to parameters in the template file.
So in short, it's not possible to pass parameters to the xslt from the JBoss ESB action pipeline. However, it would be possible to create a custom action that decorates your ESB message with data you define as a property in your jboss-esb.xml file and insert that before your XsltAction. That may be what you're looking for.