Skip to content
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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

lnconfig: Support utilizing Environment Variables in lnd.conf for rpcuser and rpcpass fields. #8310

Conversation

mohamedawnallah
Copy link
Contributor

@mohamedawnallah mohamedawnallah commented Dec 23, 2023

Change Description

  • Added supplyEnvValue function in config.go that returns The value of the specified environment variable, or the default value if provided, or the original input string if no matching variable is found or set.
  • Called supplyEnvValue function in parseRPCParams function in config.go file where rpcuser and rpcpass fields are being parsed.

Fixes #8295

Steps to Test

Added the test cases for supplyEnvVale in the config_test.go file covering the happy and sad paths.

Pull Request Checklist

Testing

  • Your PR passes all CI checks.
  • Tests covering the positive and negative (error paths) are included.
  • Bug fixes contain tests triggering the bug to prevent regressions.

Code Style and Documentation

馃摑 Please see our Contribution Guidelines for further guidance.

@mohamedawnallah mohamedawnallah force-pushed the lnconfig-support-env-vars-for-rpcuser-rpcpassword branch from 40d78af to 4f42f8b Compare January 1, 2024 21:14
@saubyk saubyk added the config Parameters/arguments/config file related issues/PRs label Jan 2, 2024
@saubyk saubyk added this to the v0.18.0 milestone Jan 2, 2024
config.go Outdated
// Returns:
// - string: The value of the specified environment variable, or the default value
// if provided, or the original input string if no matching variable is found or set.
func extractEnvVariable(value string) string {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please break everything at 80 characters (while configuring your editor to use 8 spaces for tab characters).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for letting me know! I've checked the code_formatting_rules.md and configured my Visual Studio code settings.json to reflect the Recommended settings for your editor
rules so that it would be reflected automatically in the next PRs:

"editor.insertSpaces": false,
"editor.tabSize": 8,
"editor.wordWrap": "wordWrapColumn",
"editor.wordWrapColumn": 80,
"go.formatTool": "gofmt",
"go.useLanguageServer": true,
"editor.formatOnSave": true,
"go.lintTool": "golangci-lint",
"go.lintFlags": [
  "--fast"
],
"[markdown]": {
  "files.eol": "\n",
  "files.insertFinalNewline": true,
  "editor.wordWrap": "bounded",
  "editor.wordWrapColumn": 80
}

Copy link
Collaborator

@ProofOfKeags ProofOfKeags left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! 馃檹馃徏

The main feedback I have is that the regex you put together has a slight inaccuracy to it. Other than that, there are a couple opportunities for simplification.

As @guggero points out, you should consult the style guide to ensure all those guidelines are followed. You can ensure these checks pass locally by running make fmt-check and make lint.

Finally, please add to the latest release notes a short description of this change.

config.go Outdated
// - string: The value of the specified environment variable, or the default value
// if provided, or the original input string if no matching variable is found or set.
func extractEnvVariable(value string) string {
re := regexp.MustCompile(`^(?:\${([a-zA-Z_][a-zA-Z0-9_]*)?(:-(\S+))?})|(?:\$([a-zA-Z_][a-zA-Z0-9_]*))$`)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I plug this into a diagram tool, I notice that the start of line and end of line characters are broken up across the branches. I don't believe you intended this. I would suggest making it so that both branches are anchored at the beginning and end of line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, this makes sense, and thanks a lot for mentioning this diagram tool the regular expressions make more sense now :)

Here is after updating the regular expression in the diagram tool so that both branches are anchored at the beginning and end of the line.
Screenshot 2024-01-05 at 7 03 46鈥疨M

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I wasn't going to eyeball that regex and be like "LGTM" 馃槄

config.go Outdated Show resolved Hide resolved
config.go Outdated
Comment on lines 1947 to 1955
matches := re.FindStringSubmatch(value)

if len(matches) > 0 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd combine these lines to make it such that the matches variable is only valid in the block scope.

config.go Outdated Show resolved Hide resolved
config.go Outdated Show resolved Hide resolved
config.go Outdated Show resolved Hide resolved
@mohamedawnallah mohamedawnallah force-pushed the lnconfig-support-env-vars-for-rpcuser-rpcpassword branch from 75b8252 to 187c4df Compare January 5, 2024 17:21
@mohamedawnallah
Copy link
Contributor Author

Thanks for the great feedback @guggero @ProofOfKeags I've addressed your suggestions!

@mohamedawnallah mohamedawnallah force-pushed the lnconfig-support-env-vars-for-rpcuser-rpcpassword branch 2 times, most recently from 6f8b242 to e489af2 Compare January 5, 2024 18:36
@guggero
Copy link
Collaborator

guggero commented Jan 8, 2024

Before I'm going to review in detail again, just one comment: It feels weird to me that we would want to support different formats and even fall back values within the parsing code in lnd itself.
It makes the regular expression quite complicated and hard to maintain. What's the use case you see for allowing to specify a fall back value? This would need to be documented really well, otherwise I can already see all the support issues being created because users unfamiliar with the bash like syntax remove the - character after the colon because they think it's part of the fall back value instead of the actual bash syntax.

Copy link
Collaborator

@ProofOfKeags ProofOfKeags left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems good. Gonna defer to @guggero as far as "should we do this". But assuming we want to, the change itself seems good to go.

@guggero guggero removed their request for review January 9, 2024 11:45
@saubyk saubyk removed this from the v0.18.0 milestone Jan 10, 2024
@lightninglabs-deploy
Copy link

@mohamedawnallah, remember to re-request review from reviewers when ready

@ProofOfKeags
Copy link
Collaborator

I'm going to unsubscribe from this since I have approved. Please ping me if my input is needed again.

@mohamedawnallah
Copy link
Contributor Author

mohamedawnallah commented Mar 9, 2024

@guggero I'd like to discuss this issue again anytime you're available. I agree with your thoughts That the changes that this PR proposes add much complexity compared to the value it added. I made the fallback value since the main issue #8295 mentioned that in the demo rpcuser=${BTC_RPCUSER:-btc} also that bitcoind does support this fall-back value and To be honest I don't have any use case in mind in the meantime for allowing to specify a fall-back value. That said I'm very open to suggestions e.g. having one format something like ${ENVIRONMENT_VARIABLE} would solve the issue?

What's the use case you see for allowing to specify a fallback value?

cc: @ProofOfKeags

@guggero
Copy link
Collaborator

guggero commented Mar 11, 2024

@guggero I'd like to discuss this issue again anytime you're available. I agree with your thoughts That the changes that this PR proposes add much complexity compared to the value it added. I made the fallback value since the main issue #8295 mentioned that in the demo rpcuser=${BTC_RPCUSER:-btc} also that bitcoind does support this fall-back value and To be honest I don't have any use case in mind in the meantime for allowing to specify a fall-back value. That said I'm very open to suggestions e.g. having one format something like ${ENVIRONMENT_VARIABLE} would solve the issue?

Okay, I guess it could be useful to have a fall back value. Although I think that can also lead to hard-to-find errors if you're not expecting that.

So I guess my main ask here is to simplify the regular expression, so it's easier to read and understand.
My suggestion would be to have an expression per supported format, then have a switch statement that checks which one matches. Then the extraction will be easier to understand as well.

@mohamedawnallah
Copy link
Contributor Author

So I guess my main ask here is to simplify the regular expression, so it's easier to read and understand. My suggestion would be to have an expression per supported format, then have a switch statement that checks which one matches. Then the extraction will be easier to understand as well.

This looks great! I'm gonna submit a patch and will let you know. Thanks for sharing!

@mohamedawnallah mohamedawnallah force-pushed the lnconfig-support-env-vars-for-rpcuser-rpcpassword branch from e489af2 to ddb70d3 Compare March 14, 2024 15:17
Copy link

coderabbitai bot commented Mar 14, 2024

Important

Auto Review Skipped

Auto reviews are limited to the following labels: llm-review. Please add one of these labels to enable auto reviews.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository.

To trigger a single review, invoke the @coderabbitai review command.

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share

Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit-tests for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit tests for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit tests.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/coderabbit-overrides.v2.json

CodeRabbit Discord Community

Join our Discord Community to get help, request features, and share feedback.

Copy link
Collaborator

@guggero guggero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks very good now, thanks for the changes!
Just a couple of nits, then we're good to merge 馃挴

config.go Outdated
`^\$\{([a-zA-Z_][a-zA-Z0-9_]*):-([\S]+)\}$`,
)

// Match against supported formats
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: missing full stop at end of sentence.

config.go Outdated
rpcUser := supplyEnvValue(string(userSubmatches[1]))
rpcPass := supplyEnvValue(string(passSubmatches[1]))

return rpcUser, rpcPass,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can fit more on one line now (maybe even all values).

config.go Show resolved Hide resolved
config_test.go Show resolved Hide resolved
config_test.go Outdated
@@ -52,3 +53,67 @@ func TestConfigToFlatMap(t *testing.T) {
require.Equal(t, redactedPassword, result["db.etcd.pass"])
require.Equal(t, redactedPassword, result["db.postgres.dsn"])
}

func TestSupplyEnvValue(t *testing.T) {
// Mock environment variables for testing
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: missing full stop.

config_test.go Outdated
func TestSupplyEnvValue(t *testing.T) {
// Mock environment variables for testing
os.Setenv("EXISTING_VAR", "existing_value")
os.Setenv("EMPTY_VAR", "")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should use t.Setenv() instead, so they're cleaned up automatically at the end of the test.

config_test.go Outdated
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
result := supplyEnvValue(test.input)
if result != test.expected {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: should use require.Equal() for new code.

@mohamedawnallah mohamedawnallah force-pushed the lnconfig-support-env-vars-for-rpcuser-rpcpassword branch from ddb70d3 to fb2a634 Compare March 14, 2024 15:32
In this commit, we support utilizing the usage of enviroment variables in `lnd.conf` file
for `rpcuser` and `rpcpass` fields by adding `supplyEnvValue` function in `config.go`
that returns the value of the specified environment variable, the fall-back value
if provided, or the original input string if no matching environment variables are found or set.
@mohamedawnallah mohamedawnallah force-pushed the lnconfig-support-env-vars-for-rpcuser-rpcpassword branch from fb2a634 to 0add4fc Compare March 14, 2024 15:56
@mohamedawnallah
Copy link
Contributor Author

Thanks a lot, @guggero for your suggestion. It is now much simpler. I've addressed all of your feedback!

Copy link
Collaborator

@guggero guggero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 馃帀

Copy link
Collaborator

@ProofOfKeags ProofOfKeags left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

馃

@guggero guggero merged commit 51ebc20 into lightningnetwork:master Mar 15, 2024
26 of 27 checks passed
@mohamedawnallah mohamedawnallah deleted the lnconfig-support-env-vars-for-rpcuser-rpcpassword branch March 31, 2024 12:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
config Parameters/arguments/config file related issues/PRs
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[feature]: Support config via ENV to better protect secrets
5 participants