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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implement builtin mode for keepassxc #4149

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

bakito
Copy link

@bakito bakito commented Dec 20, 2024

Implements: #4148

Copy link
Owner

@twpayne twpayne left a comment

Choose a reason for hiding this comment

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

Thanks for this!

Instead of a new set of template functions, I think this different "mode" for opening KeepassXC databases. Currently chemzoi supports "cache-password" and "open" modes. I think this should be a new "builtin" mode.

What do you think?

.gitignore Outdated Show resolved Hide resolved
go.mod Outdated Show resolved Hide resolved
@bakito
Copy link
Author

bakito commented Dec 20, 2024

Thanks for this!

Instead of a new set of template functions, I think this different "mode" for opening KeepassXC databases. Currently chemzoi supports "cache-password" and "open" modes. I think this should be a new "builtin" mode.

What do you think?

Sounds reasonable.
I modified the implementation and added the functions for the new mode.

@@ -100,6 +113,18 @@ func (c *Config) keepassxcTemplateFunc(entry string) map[string]string {
}

func (c *Config) keepassxcAttributeTemplateFunc(entry, attribute string) string {
if c.Keepassxc.Mode == keepassxcModeBuiltin {
// builtin stores attributes in cache
if data, ok := c.Keepassxc.cache[entry]; ok {
Copy link
Author

Choose a reason for hiding this comment

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

As the library handles default values the same as attributes, both functions use the same cache in builtin mode.
I don't think that i makes sense to keep separate caches in this case.

@@ -329,3 +354,82 @@ func (c *Config) keepassxcClose() error {
}
return nil
}

// keepassxcBuiltinExtractValues extract builtin values
func (c *Config) keepassxcBuiltinExtractValues(
Copy link
Author

Choose a reason for hiding this comment

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

This implementation reads all values from the keepass database to reduce access to the file itself.
If this might blow the memory I can change the implementation to only cache the requested values.

Copy link
Collaborator

Choose a reason for hiding this comment

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

We don't know how large any given keepass database will be, so the memory is potentially uncontrollable this way. More problematic, though, is that this decrypts the entire database and puts it in memory. chezmoi doesn't do anything specific to harden its memory accesses (I’m not sure what one could do with Go), so this represents a much larger attack surface on a running instance of chezmoi.

If it isn't too much additional work, I think that only entries requested should be cached because to do otherwise would change chezmoi's security profile.

Copy link
Author

Choose a reason for hiding this comment

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

@halostatue @twpayne I've modified the code to only cache required entries

@bakito bakito force-pushed the keepass branch 3 times, most recently from 5396dc8 to f42961b Compare December 20, 2024 22:20
Copy link
Owner

@twpayne twpayne left a comment

Choose a reason for hiding this comment

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

Thank you, this is looking excellent, and I will do a full review after the weekend.

Please also check the contributing guide for low-hanging fruit.

But, thank you, this PR is excellent.

@bakito bakito changed the title [WIP] implement keepasslib as alternative to keepassxc feat: Implement builtin mode for keepassxc Dec 21, 2024
@@ -117,6 +117,7 @@ func TestKeepassxcTemplateFuncs(t *testing.T) {
for _, mode := range []keepassxcMode{
keepassxcModeCachePassword,
keepassxcModeOpen,
keepassxcModeBuiltin,
Copy link
Author

Choose a reason for hiding this comment

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

I'm having some issues on running this test.
When only keepassxcModeBuiltin mode is enabled, the test is running.
But when the other 2 are also enabled (or only the 2 other) the test fails.

I can't figure out the issue here. Might be some precondition in my environment.

Enter password to encrypt database (optional): 
Repeat password: 
Successfully created new database.
Enter password to unlock /tmp/TestKeepassxcTemplateFuncs1798468072/001/KeePassXC Passwords.kdbx: 
Successfully added group test group.
Enter password to unlock /tmp/TestKeepassxcTemplateFuncs1798468072/001/KeePassXC Passwords.kdbx: 
Enter password for new entry: 
Successfully added entry test entry.
Enter password to unlock /tmp/TestKeepassxcTemplateFuncs1798468072/001/KeePassXC Passwords.kdbx: 
Successfully imported attachment /tmp/TestKeepassxcTemplateFuncs1798468072/001/import file as test / attachment name to entry test group/test entry.
error: Permission denied
--- FAIL: TestKeepassxcTemplateFuncs (0.37s)
    --- FAIL: TestKeepassxcTemplateFuncs/cache-password (0.01s)
        --- FAIL: TestKeepassxcTemplateFuncs/cache-password/correct_password (0.01s)
panic: /home/bakito/bin/keepassxc-cli show '/tmp/TestKeepassxcTemplateFuncs1798468072/001/KeePassXC Passwords.kdbx' --quiet --show-protected 'test group/test entry': exit status 1 [recovered]
	panic: /home/bakito/bin/keepassxc-cli show '/tmp/TestKeepassxcTemplateFuncs1798468072/001/KeePassXC Passwords.kdbx' --quiet --show-protected 'test group/test entry': exit status 1

goroutine 415 [running]:
testing.tRunner.func1.2({0x17a2560, 0xc006f6e370})
	/home/bakito/.gimme/versions/go1.23.4.linux.amd64/src/testing/testing.go:1632 +0x230
testing.tRunner.func1()
	/home/bakito/.gimme/versions/go1.23.4.linux.amd64/src/testing/testing.go:1635 +0x35e
panic({0x17a2560?, 0xc006f6e370?})
	/home/bakito/.gimme/versions/go1.23.4.linux.amd64/src/runtime/panic.go:785 +0x132
github.com/twpayne/chezmoi/v2/internal/cmd.mustValue[...](...)
	/home/bakito/go/src/github.com/bakito/chezmoi/internal/cmd/cmd.go:254
github.com/twpayne/chezmoi/v2/internal/cmd.(*Config).keepassxcTemplateFunc(0xc0073aa008, {0xc008243e18, 0x15})
	/home/bakito/go/src/github.com/bakito/chezmoi/internal/cmd/keepassxctemplatefuncs.go:103 +0x24a
github.com/twpayne/chezmoi/v2/internal/cmd.TestKeepassxcTemplateFuncs.func1.1(0xc0072c3380)
	/home/bakito/go/src/github.com/bakito/chezmoi/internal/cmd/keepassxctemplatefuncs_test.go:130 +0x1fa
testing.tRunner(0xc0072c3380, 0xc00737b170)
	/home/bakito/.gimme/versions/go1.23.4.linux.amd64/src/testing/testing.go:1690 +0xf4
created by testing.(*T).Run in goroutine 414
	/home/bakito/.gimme/versions/go1.23.4.linux.amd64/src/testing/testing.go:1743 +0x390

Copy link
Owner

Choose a reason for hiding this comment

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

I think you've fixed this, right? I don't see this when I run the tests now.

Copy link
Author

@bakito bakito Dec 28, 2024

Choose a reason for hiding this comment

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

It seems only to be an issue on my machine. As the pre-existing tests do not run.
If the, run all on your side, that's fine for me.

@bakito bakito marked this pull request as ready for review December 21, 2024 06:27
@bakito bakito force-pushed the keepass branch 3 times, most recently from 5e0b26c to a5f1457 Compare December 23, 2024 20:45
@@ -18,3 +18,6 @@ cache it for the duration of chezmoi's execution. Setting `keepassxc.mode` to
`open` will tell chezmoi to instead open KeePassXC's console with `keepassxc-cli
open` followed by `keepassxc.args`. chezmoi will use this console to request
values from KeePassXC.
When setting the `keepassxc.mode` to `builtin`, chezmoi uses a builtin library to
access a keepassxc database. This mode becomes handy if the keepassxc-cli is not
available.
Copy link
Collaborator

Choose a reason for hiding this comment

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

When setting `keepassxc.mode` to `builtin`, chezmoi uses a builtin library to
access a keepassxc database, which can be handy if `keepassxc-cli` is not
available. Some features available in KeePassXC such as Yubikey-enhanced
encryption, may not be available with builtin support.

Note the extra blank line at the top.

Copy link
Author

Choose a reason for hiding this comment

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

When setting `keepassxc.mode` to `builtin`, chezmoi uses a builtin library to
access a keepassxc database, which can be handy if `keepassxc-cli` is not
available. Some features available in KeePassXC such as Yubikey-enhanced
encryption, may not be available with builtin support.

Note the extra blank line at the top.

Not sure what you mean wit that. What should be changed?

Copy link
Collaborator

Choose a reason for hiding this comment

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

In your original text, you had two paragraphs right next to each other. They should be separated by a blank line.

With the rest of it, I am suggesting a change.

@@ -329,3 +354,82 @@ func (c *Config) keepassxcClose() error {
}
return nil
}

// keepassxcBuiltinExtractValues extract builtin values
func (c *Config) keepassxcBuiltinExtractValues(
Copy link
Collaborator

Choose a reason for hiding this comment

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

We don't know how large any given keepass database will be, so the memory is potentially uncontrollable this way. More problematic, though, is that this decrypts the entire database and puts it in memory. chezmoi doesn't do anything specific to harden its memory accesses (I’m not sure what one could do with Go), so this represents a much larger attack surface on a running instance of chezmoi.

If it isn't too much additional work, I think that only entries requested should be cached because to do otherwise would change chezmoi's security profile.

@twpayne
Copy link
Owner

twpayne commented Dec 24, 2024

Thank you, this is looking excellent. Once you've made the small changes to the documentation, this should be ready to merge.

Signed-off-by: bakito <github@bakito.ch>
Signed-off-by: bakito <github@bakito.ch>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants