How to invoke a REST service from BPEL in Oracle SOA, with Basic Authentication? - basic-authentication

I am working with the Oracle Fusion Middleware 12.1.3, and I am developing a BPEL process which has to invoke a remote REST service that needs a Basic Authentication.
I created an External reference to the Rest Service, and in my composite.xml, it looks like this :
....
<component name="MyCompositeBASProcess" version="2.0">
<implementation.bpel src="BPEL/MyCompositeBASProcess.bpel"/>
<componentType>
<service name="mycompositebasprocess_client" ui:wsdlLocation="WSDLs/MyCompositeBASProcess.wsdl">
<interface.wsdl interface="http://xmlns.oracle.com/myPartitionSOA/MyCompositeBAS/MyCompositeBASProcess#wsdl.interface(MyCompositeBASProcess)"
callbackInterface="http://xmlns.oracle.com/myPartitionSOA/MyCompositeBAS/MyCompositeBASProcess#wsdl.interface(MyCompositeBASProcessCallback)"/>
</service>
<reference name="CMProxyRS" ui:wsdlLocation="WSDLs/CMProxyRS.wsdl">
<interface.wsdl interface="http://xmlns.oracle.com/myPartitionSOA/MyCompositeBAS/CMProxyRS#wsdl.interface(CMProxyRS_ptt)"/>
</reference>
</componentType>
<property name="bpel.config.oneWayDeliveryPolicy" type="xs:string" many="false">async.persist</property>
</component>
<reference name="CMProxyRS" ui:wsdlLocation="WSDLs/CMProxyRS.wsdl">
<interface.wsdl interface="http://xmlns.oracle.com/myPartitionSOA/MyCompositeBAS/CMProxyRS#wsdl.interface(CMProxyRS_ptt)"/>
<binding.rest config="Adapters/CMProxyRS.wadl" location="http://server_WITHOUT_basic-auth/cmproxy/resources/v2/" />
</reference>
....
With this code I invoke a REST service which is not secured by a BASIC_Auth, and it works fine.
Now, when I switch to a remote environment which needs a basic authentication, I did not manage to succeed.
I found some examples to invoke SOAP services with basic auth, but nothing really interesting for REST services. But, in the Oracle Fusion stack 12.1.3, REST services are "adapted" to SOAP services before being used, so I thought that I could use the examples I found.
So, I updated my composite.xml to add the user/password and the policy :
....
<reference name="CMProxyRS" ui:wsdlLocation="WSDLs/CMProxyRS.wsdl">
<interface.wsdl interface="http://xmlns.oracle.com/myPartitionSOA/MyCompositeBAS/CMProxyRS#wsdl.interface(CMProxyRS_ptt)"/>
<binding.rest config="Adapters/CMProxyRS.wadl" location="http://server_WITH_basic-auth/cmproxy/resources/v2/">
<wsp:PolicyReference URI="oracle/wss_username_token_client_policy" orawsp:category="security" orawsp:status="enabled"/>
<!-- <property name="oracle.webservices.auth.username">weblogic</property> -->
<!-- <property name="oracle.webservices.auth.password">password</property> -->
<property name="oracle.webservices.preemptiveBasicAuth">true</property>
<property name="javax.xml.ws.security.auth.username" many="false" override="may">weblogic</property>
<property name="javax.xml.ws.security.auth.password" many="false" override="may">password</property>
</binding.rest>
</reference>
....
As you can see, I tried with the javax.xml.ws.security.auth. properties and with the oracle.webservices.auth. properties. But both failed : on the remote, I do not get any Basic Authentication in the requests.
I also updated my CMProxyRS.wadl to add the Authorization key in the HTTP Header. For example :
<resources>
<resource path="/documents">
<method name="GET" soa:wsdlOperation="searchDocument">
<request>
<param name="Authorization" style="header" soa:expression="$msg.request/tns:Authorization" default="" type="xsd:string"/>
<param name="queryText" style="query" soa:expression="$msg.request/tns:queryText" default="" type="xsd:string"/>
<param name="fields" style="query" soa:expression="$msg.request/tns:fields" default="id,name,originalName,originalFormat,originalExtension,alternateFormat,alternateExtension,revision" type="xsd:string"/>
<param name="waitForIndexing" style="query" soa:expression="$msg.request/tns:waitForIndexing" default="false" type="xsd:boolean"/>
</request>
<response status="200">
....
And this Authorization was "replicated" in the WSDL.CMProxyRS.wsdl :
<element name="searchDocument_params">
<complexType>
<sequence>
<element name="Authorization" type="string"/>
<element name="queryText" type="string"/>
<element name="fields" type="string"/>
<element name="waitForIndexing" type="boolean"/>
</sequence>
</complexType>
</element>
This did not help. In fact, I am really not sure that what I added in my composite.xml (the properties username, password, preemptiveBasicAuth) is used by the SOA Engine to build the REST request.
(I would like to specify that it is not a user/password issue : when I test this REST query with the same user/password from Postman, it work fine.)
How can I manage to invoke a REST service with basic Authentication from a soa-composite ?

You can send custom HTTP headers in BPEL.
Take a look at this post. You need to add oracle.webservices.http.headers on the reference service and then you can populate variables and send them on your REST invoke acticity in BPEL.

You can try OWSM oracle/http_jwt_token_client_policy to pass the required headers in the request.

I had the same issue initially trying to invoke WADL from Oracle SOA 12c.
It started working after applying the following OWSM security policy:
oracle/http_jwt_token_client_policy

Related

APIM 4.1 Publish and Try out

im new with APIM 4.1 product. im trying for try_out my project on APIM. but when i put my request and send request request to backend. i got error details :
CORS
Network Failure
URL scheme must be "http" or "https" for CORS request.
when i try with integration studio 8.1 with micro service server 4.1 hit local endpoint API i make. i always get http 400 bad status
my project code for this :
`<?xml version="1.0" encoding="UTF-8"?>
<api context="/sample2" name="Sample2" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST">
<inSequence>
<log description="Request send to endpoint" level="custom">
<property name="Request Log" value="** Send Request To Endpoint **"/>
</log>
<send>
<endpoint key="Test1"/>
</send>
</inSequence>
<outSequence>
<log description="Response back from endpoint" level="custom">
<property name="Response Log" value="** Response Back From Endpoint **"/>
</log>
<send/>
</outSequence>
<faultSequence/>
</resource>
</api>`
<?xml version="1.0" encoding="UTF-8"?>
<endpoint name="Test1" xmlns="http://ws.apache.org/ns/synapse">
<http method="post" uri-template="http://apiceupfdev01.ptap.co.id:31065">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>1.0</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
maybe anyone can helping me with this case.
i expecting get response from backend endpoint i hit
I tried your project on a 4.1.0 pack with an HTTP URL for the endpoint.It worked with a 200 for API invocation call.
If you are getting CORS-related errors, did you try to create the API from the publisher and disable CORS from the runtime configurations[1]? (It is disabled by default for the new APIs that are created from the publisher portal)
[1] - https://apim.docs.wso2.com/en/latest/design/advanced-topics/enabling-cors-for-apis/#enabling-cors-globally

integration between bmc remedy and serviceNow using wso2

we would like to integrate incident module between BMC Remedy and ServiceNow ITSM applications using ESB-WSO2, need assistance on this to achieve this integration.
Use case: Service now has to create incident then WSO2 will consume the request and process then processed request will be send to Remedy. This is nothing but a e-bonding or you can call it as ticket replication.
Any help would be much appreciated
Here is a sample API for you. Supposing that you have already installed ServiceNow connector.
You can call it from Postman using GET or browser, http://{yourWso2EiServer}:8280/serviceNow/test
After testing you can change method to POST and try to send different messages using POSTMAN. Then you will have to evaluate properties from a message, using like"expression"="json-eval($.tablename)" instead of "value"= in you Property mediators and your message must be an application/json and contain this field, like
{"tablename":"incident"....
<api xmlns="http://ws.apache.org/ns/synapse" name="ServiceNowApi" context="/serviceNow" version-type="context">
<resource methods="GET" uri-template="/test" outSequence="" faultSequence="">
<inSequence>
<property name="tablename" value="incident" description="here you can set your request variables with constants for test or read it from request using json-evalng "/>
<property name="sysparmDisplayValue" value="true"/>
<property name="sysparmFields" value="short_description,number,sys_id"/>
<property name="sysparmView" value="short_description,number,sys_id"/>
<property name="number" value="12345678"/>
<property name="shortDescription" value="Testing integration using ServiceNow connector"/>
<property name="active" value="true"/>
<property name="approval" value="owner"/>
<property name="category" value="inquery"/>
<property name="contactType" value="phone"/>
<servicenow.init>
<serviceNowInstanceURL>dev85868.service-now.com</serviceNowInstanceURL>
<username>rest_test</username>
<password>12345678</password>
</servicenow.init>
<servicenow.postRecord>
<tableName>{$ctx:tableName}</tableName>
<sysparmDisplayValue>{$ctx:sysparmDisplayValue}</sysparmDisplayValue>
<sysparmFields>{$ctx:sysparmFields}</sysparmFields>
<sysparmView>{$ctx:sysparmView}</sysparmView>
<sysparmExcludeReferenceLink>{$ctx:sysparmExcludeReferenceLink}</sysparmExcludeReferenceLink>
<sysparmInputDisplayValue>{$ctx:sysparmInputDisplayValue}</sysparmInputDisplayValue>
<number>{$ctx:number}</number>
<shortDescription>{$ctx:shortDescription}</shortDescription>
<active>{$ctx:active}</active>
<approval>{$ctx:approval}</approval>
<category>{$ctx:category}</category>
<contactType>{$ctx:contactType}</contactType>
<apiColumns>{$ctx:apiColumns}</apiColumns>
</servicenow.postRecord>
</respond>
</inSequence>
</inSequence>
</resource>
</api>

Spring Security Active Directory bad credentials handling (error 49)

I have problem with Active Directory authentication in simple Spring web application. I'm using ActiveDirectoryLdapAuthenticationProvider and it seems to work fine for empty login fields and correct credentials. The problem is with invalid credentials (wrong login/pass or both). The application throws exception (error 500) to browser:
Error processing request
Context Path: /MYAPPNAME
Servlet Path: /login_check
Path Info: null
Query String: null
Stack Trace:
org.springframework.ldap.UncategorizedLdapException: Uncategorized exception occured during LDAP processing; nested exception is javax.naming.NamingException: JBAS011843: Failed instantiate InitialContextFactory com.sun.jndi.ldap.LdapCtxFactory from classloader ModuleClassLoader for Module "deployment.MYAPPNAME.war:main" from Service Module Loader [Root exception is javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C090334, comment: AcceptSecurityContext error, data 52e, vece]] (...)
The console root error is:
javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308:
LdapErr: DSID-0C090334, comment: AcceptSecurityContext error, data 52e, vece]
If the credentials are incorrect, shouldn't Spring send user to authentication-failure-url? I don't have any "manager" account to use for ldap BIND, I believe ActiveDirectoryLdapAuthenticationProvider is supposed to bind using credentials from login form. Spring documentation doesn't have anything about binding to AD.
It can probably be solved using custom authentication provider, but I was hoping there is an out-of-the-box solution. There are some similar questions, but none of them very precise or with any useful answer.
How to approach this error?
Is there a way to configure it in XML? Perhaps, to tell AD provider to tread binding error as failed login attempt?
Is custom authentication provider the only solution?
spring-security.xml
<bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter">
<property name="rolePrefix" value="" />
</bean>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<constructor-arg name="decisionVoters" ref="roleVoter" />
</bean>
<s:http authentication-manager-ref="ldap-auth" access-decision-manager-ref="accessDecisionManager" use-expressions="false">
<s:intercept-url pattern="/list**" access="ADGROUP-XYZ" />
<s:form-login
login-page="/login"
login-processing-url="/login_check"
username-parameter="username"
password-parameter="password"
default-target-url="/list"
authentication-failure-url="/login?fail" />
<s:logout
invalidate-session="true"
logout-success-url="/login?logout"
logout-url="/logout"
delete-cookies="JSESSIONID" />
<s:csrf />
</s:http>
<s:authentication-manager id="ldap-auth">
<s:authentication-provider ref="adAuthenticationProvider" />
</s:authentication-manager>
<bean id="adAuthenticationProvider" class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
<constructor-arg value="company.local" />
<constructor-arg value="ldap://server.company.local:389/" />
<property name="useAuthenticationRequestCredentials" value="true"/>
<property name="convertSubErrorCodesToExceptions" value="true"/>
</bean>
EDIT: One ugly fix is to override ActiveDirectoryLdapAuthenticationProvider and change throw LdapUtils.convertLdapException(e); to throw badCredentials(e);.
There is a issue with JBoss EAP initial context.This has been fixed in the latest wildfly versions.check the below links
https://jira.spring.io/browse/SEC-2754
https://issues.jboss.org/browse/WFLY-4149

How to convert SOAP request to HTTP GET?

I am trying to construct an REST service query parameters from an incoming SOAP request, and I need GET mode request(doGet:http://localhost:8888/XMPPService/recieveMsg?accessId=admin&accessSeq=admin&accessPwd=admin).
I use property REST_URL_POSTFIX.
My config is:
<target>
<inSequence>
<property name="REST_URL_POSTFIX" value="?accessId=accessId&accessSeq=accessSeq" scope="axis2" />
<send>
<endpoint>
<address uri="http://localhost:8888/XMPPService/recieveMsg" >
</endpoint>
</send>
</inSequence>
<outSequence>
<log level="full" />
<send />
</outSequence>
</target>
<publishWSDL key="XMPPService_wsdl" />
But is also POST mode request, it calls doPost method, not GET mode request.
The receive message is also:
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Body>
<p:XMPPService xmlns:p="http://iag.sdp.coship.com/xmpp/">
<accessId>admin</accessId>
<accessSeq>admin</accessSeq>
<accessPwd>admin</accessPwd>
</p:XMPPService>
</soapenv:Body>
</soapenv:Envelope>
I'm not clear on what you are trying. From my understanding, you are trying to construct an REST service query parameters from an incoming SOAP request.
If that is the case use REST_URL_POSTFIX property to set the query parameters.
I have written this post which may help you.

log4Net EventlogAppender does not work for Asp.Net 2.0 WebSite?

I have configured log4Net EventLogAppender for Asp.Net 2.0. However it does not log anything. I have following in my Web.Config.
<log4net>
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender">
<param name="LogName" value="Test Log" />
<param name="ApplicationName" value="Test-Web" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>
<root>
<priority value="ERROR"/>
<appender-ref ref="EventLogAppender"/>
</root>
<logger name="NHibernate">
<level value="ERROR" />
<appender-ref ref="EventLogAppender" />
</logger>
</log4net>
I already have Test-Log Event Log created and AspNet user has permission on the Event Log registry entry. I also have log4Net configured in Global.asax Application_Start.
log4net.Config.XmlConfigurator.Configure();
Update : I switched on the log4net internal debugging and found the following error in the trace.
log4net:ERROR XmlHierarchyConfigurator: Could not create Appender [EventLogAppender] of type [log4net.Appender.EventLogAppender]. Reported error follows.
System.Security.SecurityException: The source was not found, but some or all event logs could not be searched. Inaccessible logs: Security.
at System.Diagnostics.EventLog.FindSourceRegistration(String source, String machineName, Boolean readOnly)
at System.Diagnostics.EventLog.SourceExists(String source, String machineName)
at System.Diagnostics.EventLog.SourceExists(String source)
at log4net.Appender.EventLogAppender.ActivateOptions()
at log4net.Repository.Hierarchy.XmlHierarchyConfigurator.ParseAppender(XmlElement appenderElement)
Update 2 : It finally works if I create the Event Source (Test-Web) using a console based application in c# and then using the Web Application.
There's some very simple steps to get Log4Net working with the event log with ASP.NET.
Your options are:
Change the app pool
Run the application pool as LocalSystem
Or...set an application name, add a registry key
Configure your config file first so there is an application name.
This is important if you are having a permissions issue, because if you peer at the source you'll see the EventLogAppender defaults the application name (the source column in the event log) to:
System.Threading.Thread.GetDomain().FriendlyName
This requires your application to create a registry key each time the name changes, and is a bit messy. So the best solution is to set your application name. Here's an example EventLogAppender section that sends every error level, the ApplicationName line is the important part:
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender">
<param name="ApplicationName" value="MY-AWESOME-APP" />
<evaluator type="log4net.Core.LevelEvaluator">
<threshold value="INFO" />
</evaluator>
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="INFO"/>
<param name="LevelMax" value="FATAL"/>
</filter>
<layout type="log4net.Layout.PatternLayout">
<!-- The event log already logs the date so just log the message -->
<conversionPattern value="%message" />
</layout>
</appender>
Before making this change, do the following:
Create a registry key
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog\Application\MY-AWESOME-APP
Create a string value inside this
Name it EventMessageFile, set its value to
C:\Windows\Microsoft.NET\Framework\v2.0.50727\EventLogMessages.dll
That path appears to work in both 64 bit and 32 bit environments.
With this technique you don't need to set permissions in the registry, and once the key above is created it should just work.
I can't tell you exactly what might be wrong, but if you go here you will see "How do I enable log4net internal debugging?" way down at the bottom. Log4net will not throw exceptions if something is wrong, so you must enable internal debugging in order to get information from log4net.
http://logging.apache.org/log4net/release/faq.html
Edit: Also see the quesiton directly after that one that explains potential hangups with using the EventLogAppender.
I would suspect code access security is preventing you from accessing the event log. This article have information on the topic. Basically, if your ASP.Net application is running under medium trust the app will not have access to event logs.
Note: this is not a restriction built into log4net per se, it is a "feature" of the .Net Framework and ASP.Net.

Resources