Combine IpWhitelist and Errors Middlewares. Is it possible? - traefik

I would like to do the following. Combine these two middlewares. If the user is not in the whitelist, then show an error page.
As far as I understand these 2 middlewares don't work together? Or can they be combined somehow? Didn't find anything in the documentation.
IpWhitelist works, but i become only text in Response, but I would like to get an error page.
................
entryPoints:
- websecure
middlewares:
- d-whitelist
- service-errorpages
.................
and
middlewares:
d-whitelist:
ipWhiteList:
sourceRange:
- "95.95.95.95/32"
service-errorpages:
errors:
status:
- "401"
- "403"
- "404"
- "500"
service: tools
query: "/{status}.html"
Thanks!

When defining middleware on a service, it is dependent on order within the array. If you flip service-errorpages and d-whitelist around, you will get a 403 response served from service-errorpages when requesting from a non-whitelisted IP.
If you have a lot of services using the same middleware (eg. both the whitelist & the error handler) with the same priority order, you may benefit from using a chain.

Related

Traefik - apply middleware to router except a specific path

I use a IP whitelist middleware to filter the access of my web application to some IPS only and it works.
But, I want to unprotect a specific path to make it public (the path is /api/transaction).
For now, I have (in my docker-comose.yml) :
varnish:
labels:
- "traefik.http.routers.api_varnish.rule=Host(`api.local`, `api`)"
- "traefik.http.routers.api_varnish.tls=true"
- "traefik.http.routers.api_varnish.middlewares=https-redirect#file"
- "traefik.http.routers.api_varnish.middlewares=https-whitelist#file"
- "traefik.http.services.api_varnish.loadbalancer.server.port=80"
This part works, then I added:
# Open middleware for payment IPN calls
- "traefik.http.routers.api_varnish_transaction.rule=(Host(`api.local`, `api`) && PathPrefix(`/api/transaction`))"
- "traefik.http.routers.api_varnish_transaction.tls=true"
- "traefik.http.routers.api_varnish_transaction.priority=2"
- "traefik.http.routers.api_varnish_transaction.middlewares=https-redirect#file"
I duplicated the lines, but I didn't apply the middleware https-whitelist#file to the new host.
It doesn't work, I can't find the correct syntax or be sure if I can do it ? documentation is pretty poor.
Any idea?
Have 2 routers, 1 for /api/transaction and another one for /* and give the first router a higher priority (set a higher number) e.g.
# ...
labels:
- traefik.http.routers.router_1.priority=2
Now requests to /api/transaction will only hit router_1
https://doc.traefik.io/traefik/routing/routers/#priority

How to validate or filter a wildcard in path for http endpoints in Serverless and AWS API gateway before the process triggs the lambda function?

I have the following http path devices/{sn} in a Serverless-AWS APIgateway API. The wildcard sn is a 15 digits [A-Z0-9] pattern.
In the API today any string that is not recognized as a valid path is redirected to this end-point. Ex: devices/test goes to devices/{sn}, devices/bla goes to devices/{sn} and so on. All those strings will query the database and return null because there is no such sn in the table. I could create a validation process inside the lambda to avoid the unnecessary database query. But I want to save lambda resource and I would like to validate before call the lambda.
This is what I have today for this endpoint:
- http:
path: devices/{sn}
method: GET
private: false
cors: true
authorizer: ${file(env.yml):${self:provider.stage}.authorizer}
request:
parameters:
paths:
sn: true
How can I setup this validation or filter in Serverless.yml?
In fact it should be a very straight-forward functionality of AWS/Serverless.
Let's say we have the following scenario: myPath/{id}. In this case id is a integer (a pk in a table). If I type myPath/blabla it will trigg the lambda. The system will spend resource. It shoul have a kind of previous validation - trig the endpoint only if the {id} === integer.
Your issue is very similar to this issue
According to the post and from my experience, No, I don't think you can perform validation in api-gateway level.

In karate mocking (karate-netty), how can we override request header value?

Objective:
We want few API calls should go to mock-server(https://192.x.x.x:8001) and others should go to an actual downstream application server(https://dev.api.acme.com).
Setup :
On local, mock server is up with standalone jar on port 8001. e.g https://192.x.x.x:8001
In application config file (config.property)downstream system(which need to mock) defined with mockserver IP i.e https://192.x.x.x:8001
Testing scenario and problem:
1.
Scenario: pathMatches('/profile/v1/users/{id}/user')
* karate.proceed('https://dev.api.acme.com')
* def response = read ('findScope.json')
* def responseStatus = 200ˀˀ
* print 'created response is: ' + response
Now, when we hit API request via postman or feature file then it does karate.proceed properly to https://dev.api.acme.com/profile/v1/users/123/user instead of 192.x.x.x. However, in this request, host is referring to https://192.x.x.x:8001 instead of https://dev.api.acme.com which create a problem for us.
How can we override request header in this case? I did try with karate.set and also with header host=https://192.x.x.x:8001 but no luck.
Thanks!
Please see if the 1.0 version works: https://github.com/intuit/karate/wiki/1.0-upgrade-guide
Unfortunately https proxying may not work as mentioned. If you are depending on this, we may need your help (code contribution) to get this working
If the Host header is still not mutable, that also can be considered a feature request, and here also I'd request you to consider contributing code

Akka http redirect but change method from POST to GET

I have endpoint using POST method ( registering token for example ), after job done I want to redirect client to "/" url, but using GET not POST.
How to achieve this ?
For now I have:
redirect("/", StatusCodes.PermanentRedirect)
What you want in this case is not a redirect with status code PermanentRedirect, but rather SeeOther (303). So you would have instead: redirect("/", StatusCodes.SeeOther)
You can check in RFC 7231, section 6.4.4: 303 See Other that this guarantees the behavior you describe.

can i use "http header" to check if a dynamic page has been changed

you can request the http header to check if a web page has been edited by looking at its date but how about dynamic pages such as - php, aspx- which grabs its data from a database?
Even though you might think it's outdated I've always found Simon Willison's article on Conditional GET to be more than useful. The example is in PHP but it is so simple that you can adapt it to other languages. Here it is the example:
function doConditionalGet($timestamp) {
// A PHP implementation of conditional get, see
// http://fishbowl.pastiche.org/archives/001132.html
$last_modified = substr(date('r', $timestamp), 0, -5).'GMT';
$etag = '"'.md5($last_modified).'"';
// Send the headers
header("Last-Modified: $last_modified");
header("ETag: $etag");
// See if the client has provided the required headers
$if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ?
stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) :
false;
$if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ?
stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) :
false;
if (!$if_modified_since && !$if_none_match) {
return;
}
// At least one of the headers is there - check them
if ($if_none_match && $if_none_match != $etag) {
return; // etag is there but doesn't match
}
if ($if_modified_since && $if_modified_since != $last_modified) {
return; // if-modified-since is there but doesn't match
}
// Nothing has changed since their last request - serve a 304 and exit
header('HTTP/1.0 304 Not Modified');
exit;
}
With this you can use HTTP verbs GET or HEAD (I think it's also possible with the others, but I can't see the reason to use them). All you need to do is adding either If-Modified-Since or If-None-Match with the respective values of headers Last-Modified or ETag sent by a previous version of the page. As of HTTP version 1.1 it's recommended ETag over Last-Modified, but both will do the work.
This is a very simple example of how a conditional GET works. First we need to retrieve the page the usual way:
GET /some-page.html HTTP/1.1
Host: example.org
First response with conditional headers and contents:
200 OK
ETag: YourETagHere
Now the conditional get request:
GET /some-page.html HTTP/1.1
Host: example.org
If-None-Match: YourETagHere
And the response indicating you can use the cached version of the page, as only the headers are going to be delivered:
304 Not Modified
ETag: YourETagHere
With this the server notified you there was no modification to the page.
I can also recommend you another article about conditional GET: HTTP conditional GET for RSS hackers.
This is the exact purpose of the ETag header, but it has to be supported by your web framework or you need to take care that your application responds properly to requests with headers If-Match, If-Not-Match and If-Range (see HTTP Ch 3.11).
You can if it uses the http response headers correctly but it's often overlooked.
Otherwise storing a local md5-hash of the content might be useful to you (unless there's an easier in-content string you could hook out). It's not ideal (because it's quite a slow process) but it's an option.
Yes, you can and should use HTTP headers to mark pages as unexpired. If they are dynamic though (PHP, ASPX, etc.) and/or database driven, you'll need to manually control setting the Expires header/sending HTTP Not Modified appropriately. ASP.NET has some SqlDependency objects for this, but they still need to be configured and managed. (Not sure if PHP has something just like it, but there's probably something in PEAR if not...)
The Last-Modified header will only be of use to you if the programmer of the site has explicitly set it to be returned.
For a regular, static page Last-Modified is the timestamp of the last modification of the HTML file. For a dynamically generated page the server can't reliably assign a Last-Modified value as it has no real way of knowing how the content has changed depending on request, so many servers don't generate the header at all.
If you have control over the page, then ensuring the Last Modified header is being set will ensure a check on Last-Modified is successful. Otherwise you may have to fetch the page and either perform a regex to find a changed section (e.g. date/time in the header of a news site). If no such obvious marker exists, then I'd second Oli's suggestion of an MD5 on the page content as a way to be sure it has changed.