This argument is similar to -rpcauth but takes the value from the specified file content and can be specified from the command line.
Fixes #20387.
@MarcoFalke I thought about suggesting that but main issue is that -includeconf
can’t be specified in the command line. Also the file pointed by -includeconf
can have more configurations.
Maybe @ruimarinho and @NicolasDorier can weight on the the approach.
This argument is similar to -rpcauth but takes the value from the
specified file content
To be used with -rpcauthfile
255 {
256 LogPrintf("Using rpcauth authentication.\n");
257+ for (std::string rpcauth : gArgs.GetArgs("-rpcauth")) {
258+ std::vector<std::string> fields;
259+ boost::split(fields, rpcauth, boost::is_any_of(":$"));
260+ if (fields.size() == 3) g_rpcauth.push_back(fields);
-rpcauth
values are now processed once.
-rpccookiegenerate=false
option is what I had in mind in #20387. I would prefer that exactly for the simplicity of using an arbitrary string as cookie (which I can share via Docker’s secret mechanism).
Syntax isn’t necessarily wrong. It could be a 4th field added (eg, Knots uses it to restrict access to the named wallet).
A debug log line can’t hurt though.
This seems like a reasonable option to add.
Allowing -includeconf
to be specified on the command line would also be reasonable way to help address #20387.
However, both of these approaches seem more cumbersome to use and implement than the -norpccookiegenerate
option suggested #20387 (comment).
It seems like that option could be implemented with simple logic like:
0bool have_cookie = GetBoolArg("-rpccookiegenerate", true) ? GenerateAuthCookie(&cookie) : GetAuthCookie(&cookie);
and unlike the rpcauth
value, the cookie value would be automatically picked up by bitcoin-cli
client and potentially the electrs
client. There wouldn’t be a need to generate username, password, and hashed auth strings, pass the hashed auth string to the server, and pass the username and password strings to each client separately. The cookie value could be any random string with no need for hashing at all and placed in a common location where it is available to the server and every client that needs to read it.
@laanwj while @ryanofsky approach is indeed simple (just misses the detail of not erasing cookie file on shutdown) it doesn’t support different users with different whitelists. Also note that @ryanofsky approach changes cookie semantic - the cookie is available while the daemon is running. I’d even limit cookie authentication to loopback interface.
the cookie value would be automatically picked up by
bitcoin-cli
client and potentially theelectrs
client. @ryanofsky executingbitcoin-cli
on the bitcoind container will always works - cookie is there. And forelectrs
it might be easier to just use config `cookie=USER:PASSWORD".
There wouldn’t be a need to generate username, password, and hashed auth strings, pass the hashed auth string to the server, and pass the username and password strings to each client separately. The cookie value could be any random string with no need for hashing at all and placed in a common location where it is available to the server and every client that needs to read it. @ryanofsky this is not really necessary. Looks like we should just add support for bearer authentication in addition to basic authentication. In this case we could support
-rpcauth=user:token
and-rpcauthfile=user:path
and then clients could just sendAuthorization: Bearer <token>
header (the server would be able to identify the user and check its whitelist).
It just sounds reasonable to me to support different credentials and whitelists and make this easy to setup with docker containers and secrets.
@promag sure, and thanks for implementing this. I just suggested the -rpccookiegenerate
boolean option because it seemed to directly address the reported issue, because it seemed simple to implement as a ~one-line change, and because it seemed like a simpler configuration to set up: not requiring any scripting or hashing, not requiring any client configuration if using bitcoin-cli
or using the default cookie path with another client.
Also, it’s been said a few times that -norpccookiegenerate
wouldn’t support multiple credentials, but this would be a easy restriction to lift now or in the future by replacing GetArg("-rpccookiefile")
with GetArgs("-rpccookiefile")
and std::string
with std::set<std::string>
a few places.
I do agree with you that it would probably make sense to stop allowing cookie authentication from non-local connections by default. I also think the -rpcauthfile
option implemented here would be a useful thing to have (though allowing -includeconf
on the command line could be more flexible). I can see how there might be security concerns and potential for insecure misconfiguration with cookie files since the secret isn’t hashed. But I think all the solutions that have been discussed have been reasonable.
-rpcauthfile
is to have a file with just the token and so more suitable as a shared secret.
I do agree with you that it would probably make sense to stop allowing cookie authentication from non-local connections by default.
Ok, this can be submitted on a separate branch.
265+ if (!file.is_open()) continue;
266+ std::string rpcauth;
267+ std::getline(file, rpcauth);
268+ std::vector<std::string> fields;
269+ boost::split(fields, rpcauth, boost::is_any_of(":$"));
270+ if (fields.size() == 3) g_rpcauth.push_back(fields);
In commit “rpc: Support -rpcauthfile argument” (10ef7321f0dab8cb7dfe79f7c0f9d886d8fe0097)
I think this should refuse to load if the rpcauthfile isn’t formatted correctly. Logging and error and returning false might be sufficient to do this.
I think an invalid -rpcauth option above should also trigger an error, or at least report an error, but it’s pre-existing code so not directly related
I think this should refuse to load
You mean the process should exit?
re: #20407 (review)
I think this should refuse to load
You mean the process should exit?
I would exit, but don’t think it would be crazy not to exit, do think it would be crazy to silently ignore a configuration error giving no feedback. I am presuming returning false exits, but didn’t check.
43- print('rpcauth={0}:{1}${2}'.format(args.username, salt, password_hmac))
44- print('Your password:\n{0}'.format(args.password))
45+ if args.output:
46+ file = open(args.output, "x")
47+ file.write('{0}:{1}${2}'.format(args.username, salt, password_hmac))
48+ print('Your password:\n{0}'.format(args.password))
In commit “rpcauth: Support storing credentials in a file” (ff5d7fa1e4c340657110436a29aecff85de6eb80)
Same line is printed in else branch, could dedup.
38@@ -38,9 +39,14 @@ def main():
39 salt = generate_salt(16)
40 password_hmac = password_to_hmac(salt, args.password)
41
42- print('String to be appended to bitcoin.conf:')
43- print('rpcauth={0}:{1}${2}'.format(args.username, salt, password_hmac))
44- print('Your password:\n{0}'.format(args.password))
45+ if args.output:
46+ file = open(args.output, "x")
In commit “rpcauth: Support storing credentials in a file” (ff5d7fa1e4c340657110436a29aecff85de6eb80)
Doesn’t really matter but
0with open(args.output, "x") as file:
1 file.write(...)
Is slightly better style because it ensures that the file is closed immediately after the write.
Also may wish to avoid file
variable name and use something like f
or fp
since file
is a builtin function.
'a'
Needs to specify encoding
0 file = open(args.output, "x", encoding="utf8")
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
Reviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.
249@@ -256,9 +250,24 @@ static bool InitRPCAuthentication()
250 LogPrintf("Config options rpcuser and rpcpassword will soon be deprecated. Locally-run instances may remove rpcuser to use cookie-based auth, or may be replaced with rpcauth. Please see share/rpcauth for rpcauth auth generation.\n");
251 strRPCUserColonPass = gArgs.GetArg("-rpcuser", "") + ":" + gArgs.GetArg("-rpcpassword", "");
252 }
253- if (gArgs.GetArg("-rpcauth","") != "")
254+ if (gArgs.GetArg("-rpcauth", "") != "" || gArgs.GetArg("-rpcauthfile", "") != "")
-rpcauth=
to void all prior -rpcauth
parameters.
🐙 This pull request conflicts with the target branch and needs rebase.
Want to unsubscribe from rebase notifications on this pull request? Just convert this pull request to a “draft”.