-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Security: limit Masterkey remote access #4017
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Security: limit Masterkey remote access #4017
Conversation
Hey Thanks for the PR, can you add the option also to the CLI options? |
Hey @flovilmart thanks for a prompt feedback! I added CLI options as you suggested. let me know if there's anything else i should do. |
Codecov Report
@@ Coverage Diff @@
## master #4017 +/- ##
==========================================
+ Coverage 90.7% 90.73% +0.02%
==========================================
Files 116 116
Lines 7889 7910 +21
==========================================
+ Hits 7156 7177 +21
Misses 733 733
Continue to review full report at Codecov.
|
@pungme this is fantastic! Having the capacity to restrict requests, even with an authorized |
src/middlewares.js
Outdated
@@ -110,6 +110,11 @@ export function handleParseHeaders(req, res, next) { | |||
req.config = new Config(info.appId, mount); | |||
req.info = info; | |||
|
|||
const ip = req.ip; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hum, how does it work behind a LB? req.ip may be the LB's IP and not the original client IP right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Through a reverse proxy, yeah the IP would probably be that of the balancer :/. Although in some cases the requesting IP would be passed along in the X-Forwarded-For
header, not necessarily guaranteed however. To note this could be more than one IP, depending on how many proxies it passed through.
Perhaps we could check for that header and use it's value instead? When present that is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, express has a guide for running behind proxies. Allowing it to handle itself internally, req.ip
would just return what it can deduce as the original client ip. All that would have to be done is to add the following to the express initialization code.
app.enable('trust proxy');
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good question. let me rework a bit and test with our loadbalancer environment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @flovilmart , I think @montymxb was right. We can handle the LB case with something like:
const ip = req.headers['x-forwarded-for'] ||
req.connection.remoteAddress || ... etc
But the question is, should we try to handle that on parse-server side or let user configure that by using app.enable('trust proxy');
in the beginning?
Let me know what you think.
a better security mechanism is to use a proxy and restrict CORS (Allow Origin) |
CORS is only implemented in web browsers, and you may wanna restrict by Ip nonetheless. It isn’t better just different |
There is actually an npm cors package for connect/express, but cross origin requests, in the context of The exception being CORS does feature Still, I prefer what's being put together here, rather than to include another dependency. |
yes I do actually like the idea, we only need to make sure that the IP is passed correctly when using a reverse proxy |
maybe it is not big issue, most reserve proxy nginx, haproxy or even AWS ELB will set XFF header if configured correctly, we only need to improve the help message and let the user decide whether to use this feature or not, at the end it is not harmful .. |
The trust proxy option can always be added we should be handling for the ‘worst’ scenario :) |
@benishak as already mentioned, using CORS is a different issue that only really affects browsers. By generally restricting the ip we can make sure that, in case the master key leaks, no malicious requests get to the server, independently of origin (e.g. a node script). @pungme it's probably better to not rely on |
Hey @flovilmart just updated the pull request based on your suggestions. Let me know what else I should work on. Thanks! |
@miguel-s yes I know forget about CORS for now, I'm talking about this pull request is not harmful, we only need to improve the help message and tell the user if you want to use the masterKeyIps they need to make sure that their reverse proxy nginx, haproxy or elb is configured correctly if they are using one. If the reverse proxy is correctly configured the header pungme : just add a notice to the help message to the user that if they are using reverse proxy they need to make sure it is configured to set the https://easyengine.io/tutorials/nginx/forwarding-visitors-real-ip/ |
src/middlewares.js
Outdated
@@ -110,7 +110,11 @@ export function handleParseHeaders(req, res, next) { | |||
req.config = new Config(info.appId, mount); | |||
req.info = info; | |||
|
|||
const ip = req.ip; | |||
const ip = req.headers['x-forwarded-for'] || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Quick thing, it is possible that this value may be multiple ips. Especially if the user passed through one or more proxies before getting to a balancer, (quick breakdown here).
Considering that if you have more than 1 IP, and they are each separated by a ,
, you can just split the string apart by it's commas to and take the first 'origin' entry (or the only entry).
req.headers['x-forwarded-for'].split(',')[0]
@pungme can you add some master key allowed/denied tests accounting for the |
Could this support a subnet range instead of a specific IP? Right now I have some code that runs in AWS Lambda to perform tasks against Parse Server using the rest API and the master key. It's part of the same private network, but would never come from a guaranteed specific IP address. |
Hey @montymxb, thank you so much for your comment :-) I've updated the change as you suggested. Let me know if there are anything else I should change. |
@nbering This could be the next step of this feature. it shouldn't be too hard to support that. But i'd prefer to getting this one done first :-) |
Validating that the value is in fact an IP address would probably help to shim in subnet-based stuff later without breaking people - because a good value was enforced up-front. There's IP address validation built into NodeJS core on the https://nodejs.org/dist/latest-v6.x/docs/api/net.html#net_net_isip_input |
@nbering I like the idea of being able to match up to a subnets, but I think for step one let's go with what we have here. Assuming this plays nice once merged, and we don't have any issues regarding @pungme no problem! I like the test cases 👍 . Can't think of too much else besides the aformentioned ip validation via |
Excellent! Well this looks pretty good to me. @flovilmart any thoughts or concerns on this as it stands? |
src/middlewares.js
Outdated
@@ -110,6 +110,15 @@ export function handleParseHeaders(req, res, next) { | |||
req.config = new Config(info.appId, mount); | |||
req.info = info; | |||
|
|||
const ip = (req.headers['x-forwarded-for'] && req.headers['x-forwarded-for'].split(',')[0]) || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe extract this into a function getClientIp and document each check?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
One small nit for the ip extraction otherwise it’s great! |
@flovilmart thanks a lot for your reply, I've changed as you suggested. Let me know if there are anything else 😊 |
Let's see how it goes! |
Uh oh!
There was an error while loading. Please reload this page.