-
Notifications
You must be signed in to change notification settings - Fork 38.7k
Add RPC Whitelist Feature from #12248 #12763
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
Conversation
kallewoof
left a comment
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.
utACK 788b174c33896065065d1ab376d6451b0f7575cd
src/httprpc.cpp
Outdated
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.
This behavior may be fine, but this will silently turn "foo" into strUser == strWhitelist == "foo".
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.
Agree, it should check for correct format.
|
Concept ACK. This is very welcome. My block explorer only rely on |
|
concept ACK |
|
@RHavar you may be interested? |
|
Concept ACK. |
|
@instagibbs To be honest, I don't see it being that useful for me (but I don't have any objections to it either) The main advantage I can see from this change is that you could use the same bitcoin-core instance for multiple purposes, like where one only requires access to the bitcoin-related features, and the other might need wallet access. That's probably more interesting for consumer-level users, who are running core on their own computer. For more commercial users, we'd just use different instances of bitcoin-core itself. -- The PRC permission feature I'm more interested in is a lot more high-level; like applying spending limits. What I would like to do is be able to store say 300 BTC in my wallet, but never allow it drop below 250 BTC (by a particular RPC user). This way I could have only 50 BTC of "risk" (e.g. in case my service was hacked) but could benefit from having 300 BTC worth of coins (so coin-selection can do a much better job) |
|
@RHavar this prevents privkey dumps, as a first step at least |
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.
Concept ACK. Indeed a useful feature where a daemon can be shared for multiple purposes.
rpcwhitelist=user2:getnetworkinfo,getwalletinfo
Is this possible?
Doing -rpcwhitelist=user2:foo -rpcwhitelist=user2:bar will end with user2: ['bar']. Maybe it should merge or maybe we should not allow multiple methods in the same argument?
This PR could include some tests and update code style as per developer notes.
src/httprpc.cpp
Outdated
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.
New error, should have a test.
src/httprpc.cpp
Outdated
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.
rpc_whitelist?
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.
style-nit in commit b411ae6500: g_rpc_whitelist, because it is a global
src/httprpc.cpp
Outdated
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.
Agree, it should check for correct format.
|
Concept ACK |
src/httprpc.h
Outdated
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.
Why has that to be here?
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.
Wasn't sure, was just trying to follow local style. Not sure that string or map need to be there either?
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.
None needs to be there. If you want to remove, do it in a different commit.
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.
Concept ACK. I can't imagine this being a problem for exchanges, given that it's backwards compatible and uses standard bitcoind configuration logic. Definitely fine for Coinbase.
src/httprpc.cpp
Outdated
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.
I think the 403 Forbidden status is more appropriate. See https://stackoverflow.com/a/6937030.
kallewoof
left a comment
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.
utACK
src/httprpc.cpp
Outdated
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.
Should this maybe error on == case? It now silently ignores nocolonvalues.
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.
It actually doesn't silently ignore it -- it sets an empty whitelist.
eklitzke
left a comment
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.
I support adding ACLs and all that, so concept ACK.
The implementation here is problematic though. In a whitelisting approach everything should be disabled by default. This does the opposite: in this PR users have access to all RPCs by default. Adding a whitelist policy for a user implicitly restricts access to other ACLs, which is very confusing. If I am $COMPANY and I add a new engineer to the team, it is going to be very bad if I create an rpcauth for the user without remembering to also set up their ACLs. The default behavior in this situation should be safe, i.e. deny by default if any policy is defined.
There's a huge range here from really complex authorization schemes to really simple things, but I would prefer something that has at least basic steps towards a real roles/ACL system. At the minimum I think this means there should be a way to declare a default list of ACLs, and then whitelists would expand on that.
src/httprpc.cpp
Outdated
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.
You can split with a std::istream or std::getline, no need for boost::split here.
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.
I'd prefer to leave boost::split -- this is an existing dependency throughout the codebase, at some point someone will likely clean them all up consistently with an addition to util.
I'm happy to make such a PR if there is demand for it.
|
Yeah it's probably better to check if |
|
In the current scheme, a user by default has access to all RPCs to maintain backwards compatibility. Once a file has specified that a user should have a whitelist, it defaults to everything being off. I agree this is not ideal, but don't have a great workaround. Here are two potential solutions: We add: If rpcwhitelistenable is set, the by default any user has that whitelist (allowed to be empty)? If a user is marked rpcwhitelistroot, they have all RPCs enabled. If a user is marked rpcwhitelist=:blah, then they have blah. Or, we can make it such that if any rpcwhitelist is set, all users default to having an empty whitelist. Do you think this is a good tradeoff of complexity/dtrt? Which do you prefer? @promag |
|
|
@JeremyRubin I would add both. I guess my point is that if you need permissions at all you probably also want the ability to enable some kind of deny-by-default policy, to safeguard against a situation where you accidentally forget to lock down an account. You generally don't want to give your software engineers root access on production machines by default, and by the same token I don't think you would want to give people with bitcoind access root by default. The way I imagine a typical setup would be something like this (ignore the made up syntax): # Default permissions are for a bunch of read only rpcs
rpcallowed = getblock,getblockchaininfo
# Alice has the default permissions, plus stuff to admin the network
rpcallowed.alice = addnode,clearbanned,listbanned
# Bob has the default permissions, plus some basic access to the wallet
rpcallowed.bob = getbalance,getwalletinfo,getnewaddress
# Carol is an admin, she can access everything
rpcallowed.carol = !allAnd semantics something like this:
Admittedly there is an area ripe for feature creep, but I think the above would be relatively simple to implement and good enough for a lot of cases. |
|
Second idea that's much more crazy/complex. I'll throw it out there though. YAML documents have a syntax to reference other elements, which are really useful for these kinds of things. You can construct a few objects in your config and reference them elsewhere, which allows you to come up with some pseduo-role system: ---
policies:
# a default policy
- policy: &default
- getblock
- getblockchaininfo
- getblockcount
# network admin policy
- policy: &networkadmin
- addnode
- clearbanned
- getpeerinfo
users:
# alice has default plus network admin
- name: alice
policies:
- *default
- *networkadmin
# bob just has default policies
- name: bob
policies:
- *default
# syntax idea 1 for full access
- name: carol
admin: true
# syntax idea 2 for full access, !all is implicitly defined
- name: dave
policies: [*all]The The obvious drawback is that this would require linking against a YAML library. You could mitigate that by only having the user ACL list be in a YAML lib, so only users who actually want these feature would need to enable the YAML parser. |
|
@eklitzke did you check out the issue? The original proposal covered doing an inheritance scheme. @gmaxwell suggested that we should avoid doing any fancy config file, in favor of just a simple list. I do think that this could get overly verbose (especially if you want to grant network multiple times), but in general the paradigm should be to configure applications to manage multiple small credentials for specific purposes rather than one full-grant. |
43e2fe5 to
e6a75fa
Compare
|
I've updated this PR and rebased. The current version has the following changes over the previous:
Please let me know if these semantics are acceptable. |
|
LGTM. Checked code, utACK. |
|
I'm not really a fan of the |
|
We could introduce a new flag, e.g. |
|
I've always been strongly against complex authorization schemes in bitcoind. A lot of extra security critical logic to maintain. I think the place for such things is a separate authorization proxy. This is more modular, more in line with "software should do one thing well", and it depends on what security system is required, nothing can accommodate every possible separation of privileges (see also: linux security modules). That said, I like the simplicity of this scheme, simply specifying the calls that are allowed, and the small code impact, so Concept ACK. |
@JeremyRubin lgtm. |
e6a75fa to
8c45d93
Compare
|
Rebased and added documentation. Started working on tests but got a little stuck with the current test framework -- the test classes assume access to the RPCs, which doesn't let me cover all of the modes of use for rpc whitelists. |
2081442 test: Add test for rpc_whitelist (Emil Engler) 7414d38 Add RPC Whitelist Feature from #12248 (Jeremy Rubin) Pull request description: Summary ==== This patch adds the RPC whitelisting feature requested in #12248. RPC Whitelists help enforce application policies for services being built on top of Bitcoin Core (e.g., your Lightning Node maybe shouldn't be adding new peers). The aim of this PR is not to make it advisable to connect your Bitcoin node to arbitrary services, but to reduce risk and prevent unintended access. Using RPC Whitelists ==== The way it works is you specify (in your bitcoin.conf) configurations such as ``` rpcauth=user1:4cc74397d6e9972e5ee7671fd241$11849357f26a5be7809c68a032bc2b16ab5dcf6348ef3ed1cf30dae47b8bcc71 rpcauth=user2:181b4a25317bff60f3749adee7d6bca0$d9c331474f1322975fa170a2ffbcb176ba11644211746b27c1d317f265dd4ada rpcauth=user3:a6c8a511b53b1edcf69c36984985e$13cfba0e626db19061c9d61fa58e712d0319c11db97ad845fa84517f454f6675 rpcwhitelist=user1:getnetworkinfo rpcwhitelist=user2:getnetworkinfo,getwalletinfo, getbestblockhash rpcwhitelistdefault=0 ``` Now user1 can only call getnetworkinfo, user2 can only call getnetworkinfo or getwalletinfo, while user3 can still call all RPCs. If any rpcwhitelist is set, act as if all users are subject to whitelists unless rpcwhitelistdefault is set to 0. If rpcwhitelistdefault is set to 1 and no rpcwhitelist is set, act as if all users are subject to whitelists. Review Request ===== In addition to normal review, would love specific review from someone working on LN (e.g., @ roasbeef) and someone working on an infrastructure team at an exchange (e.g., @ jimpo) to check that this works well with their system. Notes ===== The rpc list is spelling sensitive -- whitespace is stripped though. Spelling errors fail towards the RPC call being blocked, which is safer. It was unclear to me if HTTPReq_JSONRPC is the best function to patch this functionality into, or if it would be better to place it in exec or somewhere else. It was also unclear to me if it would be preferred to cache the whitelists on startup or parse them on every RPC as is done with multiUserAuthorized. I opted for the cached approach as I thought it was a bit cleaner. Future Work ===== In a future PR, I would like to add an inheritance scheme. This seemed more controversial so I didn't want to include that here. Inheritance semantics are tricky, but it would also make these whitelists easier to read. It also might be good to add a `getrpcwhitelist` command to facilitate permission discovery. Tests ===== Thanks to @ emilengler for adding tests for this feature. The tests cover all cases except for where `rpcwhitelistdefault=1` is used, given difficulties around testing with the current test framework. ACKs for top commit: laanwj: ACK 2081442 Tree-SHA512: 0dc1ac6a6f2f4b0be9c9054d495dd17752fe7b3589aeab2c6ac4e1f91cf4e7e355deedcb5d76d707cbb5a949c2f989c871b74d6bf129351f429569a701adbcbf
2081442 test: Add test for rpc_whitelist (Emil Engler) 7414d38 Add RPC Whitelist Feature from bitcoin#12248 (Jeremy Rubin) Pull request description: Summary ==== This patch adds the RPC whitelisting feature requested in bitcoin#12248. RPC Whitelists help enforce application policies for services being built on top of Bitcoin Core (e.g., your Lightning Node maybe shouldn't be adding new peers). The aim of this PR is not to make it advisable to connect your Bitcoin node to arbitrary services, but to reduce risk and prevent unintended access. Using RPC Whitelists ==== The way it works is you specify (in your bitcoin.conf) configurations such as ``` rpcauth=user1:4cc74397d6e9972e5ee7671fd241$11849357f26a5be7809c68a032bc2b16ab5dcf6348ef3ed1cf30dae47b8bcc71 rpcauth=user2:181b4a25317bff60f3749adee7d6bca0$d9c331474f1322975fa170a2ffbcb176ba11644211746b27c1d317f265dd4ada rpcauth=user3:a6c8a511b53b1edcf69c36984985e$13cfba0e626db19061c9d61fa58e712d0319c11db97ad845fa84517f454f6675 rpcwhitelist=user1:getnetworkinfo rpcwhitelist=user2:getnetworkinfo,getwalletinfo, getbestblockhash rpcwhitelistdefault=0 ``` Now user1 can only call getnetworkinfo, user2 can only call getnetworkinfo or getwalletinfo, while user3 can still call all RPCs. If any rpcwhitelist is set, act as if all users are subject to whitelists unless rpcwhitelistdefault is set to 0. If rpcwhitelistdefault is set to 1 and no rpcwhitelist is set, act as if all users are subject to whitelists. Review Request ===== In addition to normal review, would love specific review from someone working on LN (e.g., @ roasbeef) and someone working on an infrastructure team at an exchange (e.g., @ jimpo) to check that this works well with their system. Notes ===== The rpc list is spelling sensitive -- whitespace is stripped though. Spelling errors fail towards the RPC call being blocked, which is safer. It was unclear to me if HTTPReq_JSONRPC is the best function to patch this functionality into, or if it would be better to place it in exec or somewhere else. It was also unclear to me if it would be preferred to cache the whitelists on startup or parse them on every RPC as is done with multiUserAuthorized. I opted for the cached approach as I thought it was a bit cleaner. Future Work ===== In a future PR, I would like to add an inheritance scheme. This seemed more controversial so I didn't want to include that here. Inheritance semantics are tricky, but it would also make these whitelists easier to read. It also might be good to add a `getrpcwhitelist` command to facilitate permission discovery. Tests ===== Thanks to @ emilengler for adding tests for this feature. The tests cover all cases except for where `rpcwhitelistdefault=1` is used, given difficulties around testing with the current test framework. ACKs for top commit: laanwj: ACK 2081442 Tree-SHA512: 0dc1ac6a6f2f4b0be9c9054d495dd17752fe7b3589aeab2c6ac4e1f91cf4e7e355deedcb5d76d707cbb5a949c2f989c871b74d6bf129351f429569a701adbcbf
|
Users arriving at this PR looking to use See discussion in #17742. |
Github-Pull: bitcoin#12763 Rebased-From: 7414d38
Github-Pull: bitcoin#12763 Rebased-From: 2081442
Summary: * test: Add test for rpc_whitelist This is a backport of Core [[bitcoin/bitcoin#12763 | PR12763]] Test Plan: ninja all check-all Reviewers: #bitcoin_abc, Fabien Reviewed By: #bitcoin_abc, Fabien Subscribers: Fabien Differential Revision: https://reviews.bitcoinabc.org/D5810
|
This has a release note in https://github.com/bitcoin-core/bitcoin-devwiki/wiki/0.20.0-Release-Notes-Draft. |
|
Is there anyway to disable specific rpc commands? |
|
You have to list out all the ones you want enabled. We don't provide specific disabling. |
|
@JeremyRubin It sure would be handy to be able to incorporate this with |
|
I think general contributor opinion on rpc whitelists is that it shouldn't scope creep any further, but I agree a limitwallets flag would be pretty useful. I think luke does a lot of multiwallet stuff @luke-jr and might have an opinion as it does seem somewhat orthogonal. Luke what do you think of some sort of loadwalletforuser/limitwallet API? |
|
See also #10615 (included in Knots) |
2081442 test: Add test for rpc_whitelist (Emil Engler) 7414d38 Add RPC Whitelist Feature from bitcoin#12248 (Jeremy Rubin) Pull request description: Summary ==== This patch adds the RPC whitelisting feature requested in bitcoin#12248. RPC Whitelists help enforce application policies for services being built on top of Bitcoin Core (e.g., your Lightning Node maybe shouldn't be adding new peers). The aim of this PR is not to make it advisable to connect your Bitcoin node to arbitrary services, but to reduce risk and prevent unintended access. Using RPC Whitelists ==== The way it works is you specify (in your bitcoin.conf) configurations such as ``` rpcauth=user1:4cc74397d6e9972e5ee7671fd241$11849357f26a5be7809c68a032bc2b16ab5dcf6348ef3ed1cf30dae47b8bcc71 rpcauth=user2:181b4a25317bff60f3749adee7d6bca0$d9c331474f1322975fa170a2ffbcb176ba11644211746b27c1d317f265dd4ada rpcauth=user3:a6c8a511b53b1edcf69c36984985e$13cfba0e626db19061c9d61fa58e712d0319c11db97ad845fa84517f454f6675 rpcwhitelist=user1:getnetworkinfo rpcwhitelist=user2:getnetworkinfo,getwalletinfo, getbestblockhash rpcwhitelistdefault=0 ``` Now user1 can only call getnetworkinfo, user2 can only call getnetworkinfo or getwalletinfo, while user3 can still call all RPCs. If any rpcwhitelist is set, act as if all users are subject to whitelists unless rpcwhitelistdefault is set to 0. If rpcwhitelistdefault is set to 1 and no rpcwhitelist is set, act as if all users are subject to whitelists. Review Request ===== In addition to normal review, would love specific review from someone working on LN (e.g., @ roasbeef) and someone working on an infrastructure team at an exchange (e.g., @ jimpo) to check that this works well with their system. Notes ===== The rpc list is spelling sensitive -- whitespace is stripped though. Spelling errors fail towards the RPC call being blocked, which is safer. It was unclear to me if HTTPReq_JSONRPC is the best function to patch this functionality into, or if it would be better to place it in exec or somewhere else. It was also unclear to me if it would be preferred to cache the whitelists on startup or parse them on every RPC as is done with multiUserAuthorized. I opted for the cached approach as I thought it was a bit cleaner. Future Work ===== In a future PR, I would like to add an inheritance scheme. This seemed more controversial so I didn't want to include that here. Inheritance semantics are tricky, but it would also make these whitelists easier to read. It also might be good to add a `getrpcwhitelist` command to facilitate permission discovery. Tests ===== Thanks to @ emilengler for adding tests for this feature. The tests cover all cases except for where `rpcwhitelistdefault=1` is used, given difficulties around testing with the current test framework. ACKs for top commit: laanwj: ACK 2081442 Tree-SHA512: 0dc1ac6a6f2f4b0be9c9054d495dd17752fe7b3589aeab2c6ac4e1f91cf4e7e355deedcb5d76d707cbb5a949c2f989c871b74d6bf129351f429569a701adbcbf
Summary
This patch adds the RPC whitelisting feature requested in #12248. RPC Whitelists help enforce application policies for services being built on top of Bitcoin Core (e.g., your Lightning Node maybe shouldn't be adding new peers). The aim of this PR is not to make it advisable to connect your Bitcoin node to arbitrary services, but to reduce risk and prevent unintended access.
Using RPC Whitelists
The way it works is you specify (in your bitcoin.conf) configurations such as
Now user1 can only call getnetworkinfo, user2 can only call getnetworkinfo or getwalletinfo, while user3 can still call all RPCs.
If any rpcwhitelist is set, act as if all users are subject to whitelists unless rpcwhitelistdefault is set to 0. If rpcwhitelistdefault is set to 1 and no rpcwhitelist is set, act as if all users are subject to whitelists.
Review Request
In addition to normal review, would love specific review from someone working on LN (e.g., @ roasbeef) and someone working on an infrastructure team at an exchange (e.g., @ jimpo) to check that this works well with their system.
Notes
The rpc list is spelling sensitive -- whitespace is stripped though. Spelling errors fail towards the RPC call being blocked, which is safer.
It was unclear to me if HTTPReq_JSONRPC is the best function to patch this functionality into, or if it would be better to place it in exec or somewhere else.
It was also unclear to me if it would be preferred to cache the whitelists on startup or parse them on every RPC as is done with multiUserAuthorized. I opted for the cached approach as I thought it was a bit cleaner.
Future Work
In a future PR, I would like to add an inheritance scheme. This seemed more controversial so I didn't want to include that here. Inheritance semantics are tricky, but it would also make these whitelists easier to read.
It also might be good to add a
getrpcwhitelistcommand to facilitate permission discovery.Tests
Thanks to @ emilengler for adding tests for this feature. The tests cover all cases except for where
rpcwhitelistdefault=1is used, given difficulties around testing with the current test framework.