Say an instance of WSO2's API Manager receives API calls from an external client, it is possible to pass the caller's IP address to the backend (in the header for example, other solutions are welcome too)? If yes how?
HTTP Header is the way to do it. You can create a sequence like this and attach to API.
<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="sample">
<property name="client_ip" expression="get-property('axis2', 'REMOTE_ADDR')" scope="transport"/>
</sequence>
If you have a proxy before API Manager, you may not be able to identify the real client using REMOTE_ADDR. It will be the IP of the proxy. In such cases you can use X-Forwarded-For http header.
Related
Microsoft's own documentation on HSTS says the following regarding HSTS, HTTPS redirection, and APIs:
Web APIs should either:
Not listen on HTTP.
Close the connection with status code 400 (Bad Request) and not serve the request.
…
… a single authenticated call to an API over HTTP has risks on insecure networks. The secure approach is to configure API projects to only listen to and respond over HTTPS.
My takeaway is: APIs should not redirect, since clients may happily send sensitive data over HTTP and everything "just works" due to the redirection. Even for browsers and when using HSTS, the first request (with potentially sensitive data) may be done using HTTP. Instead, APIs should fail HTTP requests and respond only via HTTPS.
After having spent the better part of the day researching this, I find that in Azure App Service / Web App, there seems to be no simple way to follow these recommendations. Regardless of whether "HTTPS Only" is On or Off, the API can be called via HTTP: If On, it redirects to HTTPS, and if Off, it's fully available with HTTP without redirection. One would think there'd be a simple way to make the app service / web app listen only over HTTPS. For example if the "HTTPS Only" button was Off/Redirect/On.
The documentations says that:
To disable HTTP redirection in an API, set the ASPNETCORE_URLS environment variable or use the --urls command line flag. For more information, see Use multiple environments in ASP.NET Core and 5 ways to set the URLs for an ASP.NET Core app by Andrew Lock.
Unfortunately, neither of these two links describe whether this is relevant for App Service / Web App, or what the environment variables should be. I have not been able to get it to work. It also seems that this would require duplicating any custom domains, forcing you to remember to keep the environment variable in sync with changes to custom domains.
How can I make Azure App Service / Web App listen only on HTTPS?
My current workaround is to deploy the following web.config which, ironically, requires "HTTPS Only" to be Off for the HTTP request to reach the app service and be rejected. However, it does do the job of ensuring that no HTTP-only API clients will be developed, since they simply won't work from the outset.
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Disable HTTP" enabled="true" stopProcessing="true">
<match url="(.*)" ignoreCase="false" />
<conditions>
<add input="{HTTPS}" pattern="off" />
<add input="{WARMUP_REQUEST}" pattern="1" negate="true" />
<add input="{REMOTE_ADDR}" pattern="^100?\." negate="true" />
</conditions>
<action type="CustomResponse" statusCode="400" statusReason="HTTPS Required" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
(Conditions from this blog post.)
If anyone has a better, simpler, or more official method, I'll gladly accept that answer. Also, I'm not sure the the WARMUP_REQUEST part works (copied from elsewhere); if I change CustomResponse to AbortRequest, the slot swap operation fails because the warmup requests are dropped.
We are using mulesoft proxy api as proxy for another api. We need to know the X-Forwarded-For of the originating requestor.
If you are creating the proxy with API Manager you could add a Header Injection policy to it to add the header. You could use as the value the expression #[attributes.remoteAddress] so it takes the IP of the client of the IP.
If the proxy is deployed to CloudHub it might be receiving the IP of CloudHub load balancer and the load balancer may be already adding the X-Forwarded-For header.
I need to publish a JAX-WS webservice on a Weblogic application server behind a local Apache proxy. The Weblogic server is configured to listen to localhost requests only, and the Apache proxy redirects incoming requests to the application server via http://myServer/myService to http://localhost:1234/myService using ProxyPass and ProxyPassReverse (there is a RewriteRule in effect to transfer al http: traffic to https:).
When I request the WSDL of my SOAP Service via http://myServer/myService?wsdl, I get the WSDL as I would expect, but the xsd schemaLocation part of the WSDL points to localhost, again as expected (since the webservice is effectively called from localhost):
<types>
<xsd:schema>
<xsd:import schemaLocation="http://localhost:1234/myService?xsd=1" namespace="http://myService.myCompany.com"/>
</xsd:schema>
</types>
When I request the xsd by the schemaLocation xsd URL replacing localhost by the correct Server name, the xsd looks as I would expect. Since the localhost part is definitely wrong, I changed the Apache configuration to preserve the callers hostname by adding ProxyPerserveHost On to my httpd configuration file, the returned wsdl points to myServer, again as I would expect:
<types>
<xsd:schema>
<xsd:import schemaLocation="http://myServer:80/myService?xsd=1" namespace="http://myService.myCompany.com"/>
</xsd:schema>
</types>
Again, retrieving the xsd from that URL works fine, the xsd is valid and looks as expected. When I try to create a SoapUI SOAP Project from the URL http://myServer/myService?wsdl I get an error org.apache.xmlbeans.XmlException: error: Unexpected end of file after null
When I retrieve the same WSDL from an identical deployment on a Weblogic server without an Apache proxy and even if I call the service directly without the proxy on the original server, everything works fine.
How would I have to configure my Apache Proxy correctly to be able to use dynamic WSDL delivery and to return valid wsdl and xsd without having to manually create a wsdl file with embedded xsd?
O.k., it seems I figured it out by myself...
The problem seemed to be the port. Originally, the xsd schemaLocation was given as http://myServer:80. After disallowing http: traffic to my deployment in the application server deployment configuration, the port was returned correctly as 443, which made everything else work correctly, too:
<types>
<xsd:schema>
<xsd:import schemaLocation="https://myServer:443/myService?xsd=1" namespace="http://myService.myCompany.com"/>
</xsd:schema>
</types>
Within the web.xml of a Java EE Servlet Container (Tomcat, Glassfish etc.) I can set a security constraint to restrict the access to a certain resource.
Is it possible to make a distinction between access from localhost and all the others? I want to enable authentication in a glassfish server for all external calls to a webapp but not from localhost. Is that possible?
Put this in your /META-INF/context.xml:
<Context>
<Valve className="org.apache.catalina.valves.RemoteAddrValve" deny="127\.0\.0\.1"/>
</Context>
I have Apache as front-end to my Tomcat server where I have deployed a CXF web service. All access to my web service happens through SSL which is handled by Apache web server. This means that my Tomcat server is totally unaware of SSL. As a result my CXF generated web service has a http endpoint URL. How do I make it HTTPS while giving the opportunity of handling SSL to Apache web server. Any clue to override endpoint URL scheme?
If you do that, you should also set proper address (that with HTTPS) in publishedEndpointURL.
Like here: How to start cxf service on localhost but return external address in wsdl?
This will make imports in generated WSDL point to proper URLs.
In you case you need to enable SSL connector for Tomcat (in case you use mod_proxy in Apache), or you need to to enable secured AJP connector (in case you use mod_jk):
<Connector protocol="AJP/1.3" redirectPort="443" scheme="https" secure="true" address="127.0.0.1" port="8009" />
CXF is out of game here.
I had the same problem, and solved it by using a JNDI lookup for a base URL, then constructing a url for publishEndpointUrl. In XML config, it looks something like this:
<jee:jndi-lookup id="ProxyURL" jndi-name="myProxyURL" resource-ref="true" cache="true" />
<bean id="EndpointURL" class="java.lang.String">
<constructor-arg value="#{ProxyURL+'/myServiceAddress'}"/>
</bean>
<jaxws:endpoint
id="myServiceEndpoint"
...[other parameters]...
publishedEndpointUrl="#EndpointURL">