wso2esb - Dynamic proxy security configuration – one proxy to secure them all - wso2

I’m using wso2esb-4.9.0, then wso2-5.0.0, and now working on wso2ei-6.0.0
I would like to create a secured proxy service that could be used by different clients.
Required security is scenario 5 (sign and encrypt – x509 authentication) : Messages are encrypted using service (server) public certificate and signed using client private key. Since multiple client will use the service, each client should sign the message using client private key.
At the server side, the public certificate for each client should be already be in the trust store of the server.
At server side, I can do a hardcoded configuration for rampart in order to respond correctly for incoming request from client1 OR for client2. This means that, for now, the only solution I found in order to support 2 clients, for the same backend service, is through the use of two proxy service, each configured to verify the signature of exactly one client.
I would like to get advice or pointers in order to configure the server side in a dynamic way, where only one proxy service is used. This proxy service should be able to configure at run time correctly rampart, in order to decrypt and verify the signature of the incoming message (one proxy, for N clients).
Thanks,

So, in fact nothing extra needs to be done at configuration level of rampat, since the harcoded configuration is related to the server side, when it would like to consume smthg for other party.
Since the incomming request contains informations related to certificate data, server will dynamically check his keystore in order to verify the incomming signed message... so once again, just configure rampart, at service side, and at client side and let the magic happen.
thanks to wso2 team for great product suite !

Related

Hostname/IP does not match certificate's altnames

I'm working on a REST API that itself makes requests to another REST API -- basically, it provides a more convenient interface and also some extra functionality. Let's call my REST API X and the REST API to which my API calls Y.
Whenever I make requests to the endpoints of Y on my machine with cURL, REST Client, etc; all requests are successful. Like I mentioned, my API X is acting as a wrapper to Y, so when I upload my API to aws Lambda and create the respective endpoints in API Gateway, when I make a request to one of the endpoints I get this message:
Hostname/IP does not match certificate's altnames: Host:
X.execute-api.us-west-2.amazonaws.com. is not in the cert's altnames:
DNS:somehostname.com
So far, I have uploaded two lambdas with their respective endpoints, and the problem above only seems to be happening for one of the endpoints (the request to the other endpoint happens without problem).
I would like to know why this is happening and if this is a problem on my side? Meaning, is there something I am forgetting or something I can do -- except bypassing some security mechanism -- to fix this on my side? Whenever I make requests to the original API Y on my machine I'm not getting any errors so I'm a bit puzzled by this.
I think you're missing how SSL certificates work. Depending on how the certificate is setup for "API Y" you can't just connect to a different server and have it work. While you are conceptually a proxy to the real back end from the client perspective, you're a totally different host and the SSL certificate is for "API Y" only.
This is the same reason that you can't decide that you want to have an API named trustme.google.com - you don't have control over the google.com domain (presumably).
If there is a way to change the hostname that your client connections are using (to something like proxy.yourdomain.tld) then you can setup an SSL certificate for that domain and things should work. However, at that point you may run into CORS issues - post again if you have that issue.
AWS documents how to setup your own SSL certificate for API gateway. It's pretty easy though if you have an existing certificate you may need to use the AWS certificate manager to get a (free) certificate for your API.
Update 03/10/2022: Before your proxy hands off the request to the real backend service, make sure to set Host header to the hostname of the real service, see here.
I also developed a HTTP client -> APIG endpoint -> Lambda -> Host application, where the Lambda acts as a proxy between the client and the 3rd party Host. My Lambda is written in Node.js. I was getting this same exact error when the Lambda tried to invoke the 3rd party Host,
{
"statusCode": 500,
"body": "Hostname/IP does not match certificate's altnames: Host: zyxfghsk.execute-api.us-east-1.amazonaws.com. is not in the cert's altnames: DNS:*.somehost.com, DNS:somehost.com"
}
My setup uses Lambda Proxy integration with APIG, and I pass the set of HTTP headers from the client as-is to the 3rd party Host. I noticed the headers contained header Host: zyxfghsk.execute-api.us-east-1.amazonaws.com, which I think comes from the client. So in the Lambda code, right before passing the request to the 3rd party Host, I just simply delete the Host header from the request, and the problem went away. Another approach I was trying earlier, which also works, but not as ideal is that I was setting NODE_TLS_REJECT_UNAUTHORIZED=0 in the Node.js environment, which effectively disables SSL certificate validation by Node.js.
I believe, though not 100% certain, that in my case at least the error was getting thrown by Node.js certificate validation.
Update 03/10/2022: Before your proxy hands off the request to the real backend service, make sure to set Host header to the hostname of the real service, see here.

Manually creating a HTTP SOAP Request with Signing SOAP messages using X.509 certificate

I am trying to send a message from NetSuite to another system via http SOAP, but I was told that I have send a signed soap message. NetSuite only has an operation called nlapiRequestURL(url, postdata, headers); I am trying to use this method to send over a manually created SOAP message. What I am having problems with is figuring out how to add the cert to the header. Has anyone does this before?
What I have learned about signing a soap message with the certificate is that I need private key and public in the local keystore. This tutorial in java shows how to do it, but how would I do something similar in NetSuite.
https://dzone.com/articles/signing-soap-messages
One possible solution is you write your own proxy web server in Java
or any other server side language for that matter.
Below is the summary of my suggestion:
1) Send the request details from NetSuite to proxy server using a
Suitelet or scheduled script.
2) In the proxy server create the signed SOAP request and send to the
vendor API
3) Now, to respond back to NetSuite there are two options a) you
keep the connection open with NetSuite until you get the response and
send it back to NetSUite's script b)you respond back to a NetSuite
RESTlet, which makes the design asynchronous and can be good specially
if the turn around time is more than 45 seconds.
Also, I would suggest to write web server using HTTPS, with your server having a trusted CA signed certificate, so, that communication between web server and NetSuite is secure. And this way your communication would be secure (P.S. I can't answer the question that is SSL 100% secure, there are good discussion on http://security.stackexchange.com on that topic).

Securing thrift based Communication

So, i have made a thrift based program with a client and a server and client can communicate well with server. Now, since the data transfer will be quite crucial, I wanted some kind of security in it.
So, I thought of login system, but the problem is I am not storing any kind of session data on server side(I don't even know, what should i store, after all the client request come and go and there is no way to differentiate them). So after much thinking, this is what i came up with
Using random numbers, i would generate some kind of random string when the server starts
Client side will enter the username and password which will be verified at the server end using PAM authentiation(just read something about it).
If verified, server will just send that random generated string to the client side
Client will send that string to server every time it tries to execute a RPC
If verified, server will do the work, else return some error code
Possible problem that i can think of
Currently, when server goes down, and client was in midst of some RPC, it would give some error message and when server restarts, we can do the task without any problem
Now, if the server goes down, then the string generated will be different. So i will again have to do the authentication part
So, what do you think of this entire schema for authentication? Are there any better or simpler way?
P.S : I am not using any kind of database. I am using C++ on both sides. My Client side uses QT
Disclaimer - I do not have much idea as to how PAM works, so I only have some high-level questions about this approach. I apologize in advance if I misunderstood any part of your approach.
When you say you want to secure the data transfer, I feel like you want to have authentication and secrecy, you only have an approach for authentication now.
For instance, if client C1 is authenticating to server(assuming credentials are not sent in cleartext), the server sends the random string in step 3. What happens when someone else is sniffing on the network? Can a rogue client not send the random string and perform RPC calls to the server, posing as C1? If username and password are sent to server in cleartext, can someone on the network get access to the credentials also? Also, what about data that is subsequently sent? It is just encoded in thrift format and can be decoded by anyone on the network, correct? Is the data sensitive?
If so, I want to suggest the use of PKI/certificates. Using a self-signed certificate must be fine. If you only want the client to authenticate to the server and prove it is legitimate, you can make all the clients present their certificate. Certificate is basically a public key for that client signed by an authority that vouches for that client.The client has the private key stored locally, that will never leave the client. Now, when client presents the certificate to server, server looks at who signed the certificate(CA). If it is a CA the server trusts, it can send the random string or just the thrift data directly, encrypted using the client's public key. The client will be able to decrypt with its private key and it looks like random bytes to anyone else who is sniffing. The server will do this for every single client and only needs to store the name of the certifying authority it trusts. This could be your name and address. You can generate the self-signed certificate on every client using openssl. But this means you have additional setup work on each client. Generate a key-pair and certificate. You can explore this approach if this constraint works for you.

calling user management services on WSO2 Identity Server

I am looking at two WSO2 client samples that call the user management web service. The first is a simple client, the second is a web app.
The first client sets the system SSL properties and then instantiates a WSUserStoreManager object.
The second one, the web app, does not set SSL properties at all, and instead instantiates a RemoteUserStoreManagerServiceStub.
Could someone please explain why these differences? What service to call when two similar are available (a regular and a 'remote' one)? Isn't it always necessary to set up the SSL properties when calling a https endpoint? Thanks.
if you are calling to HTTPS end point, you need to set the SSL trust store properties to trust the server. But it is under control of the client, If client wants, it can trust it, if not it can ignore. If you want to ignore, you want to override default TrustManager of java.
However, normally java has a trust store file called "cacerts" where it contains all trusted CA certificate. But WSO2IS server's certificate is a self signed one and java can not trust it. Therefore, if you want, you can import certificate in to the "cacerts file. I am not sure about why there are two different in client and web app. However, if you are calling HTTPS, trust must be created. Please check web app source more. Some time, it may have ignore the trust. As web app is run in a app server, sometime java SSL trust properties may have been set to correct file.

boost asio client authentication

I have a client server based c++ application which communicates over network (with boost asio) and I am planning to distribute this client application to my customers. My problem is I don't know how to prevent connection request from other applications, that is how can I make sure that only my client application is able to connect to my server. I think there is no way to do this without making the connection, than what is the best way to verify that request is coming from my client?
You can use asio's builtin SSL ability. So, you generating sertificates for each server, and client sertificates. So you can check client sertificate on server at the moment of SSL handshake. As a bonus, your traffic will be encrypted and SSL-secure. Clients can check server is not a fake; server can check clients are authorized.
Yes you have to accept the connection in order to know if it's from your application or not.
You can use a three-way handshake at the connection step:
Client connects to the server The server is sending an specific
value (integer, strings or whatever) to the new client.
The client handles this value, compute a new one with it and sends
the new value to the server.
The server checks if the returned value is correct or not.
The client will have the same compute method as the server. The others applications will not be able to use your service if they returned a bad value.