Goal

Last time I change the configuration file to be able to specify how to get secrets for unlocking credential chunks, and then using those to list only credentials that can be unlocked. Today I'll use that logic to get the client key to unlock the client chunk to get the chunk key to encrypt and decrypt chunks.

Plan

  • Tidy up what I did last time to list valid credentials only, by default, and merge.
  • Change obnam chunk encrypt to get client key from a credential by default. This means obnam chunk decrypt needs the same change.
  • Both can get it by changing Leaf::client_key.

Notes

Tidy up and merge valid credential listing

  • Only two commits. Reviewed. Rebased and squashed, updating the commit message. Merged.

Change Leaf::client_key to use credentials, by default

  • I'm going to want a function that returns all credentials that can be unlocked. And one that returns just the first one: there's no point in opening many credentials, potentially asking the user for a password for each, if we only need one.
  • Both of these will need to get all credential chunks first. That seems like it should be a method on Store in and of itself. Actually, there is Store::find_chunks already. I'll add Store::find_credential_chunks too, for convenience.
  • Also added Store::find_client_chunks for the same reason.
  • The configuration has a list of credential specifications. There should be a method CredentialSpec::method to return an instance of impl CredentialMehotd for a specific spec. This will make it more convenient to use credentials specified in the configuration.
  • The Store::find_credential_chunks method I added only returns a list of chunk identifiers, but I'll also need to actually fetch the chunks themselves. So I'll add Store::get_credential_chunks method, too.
  • Noticed that Store::get_*chunk methods all returned a "not data chunk" error, even those that get other kinds of chunks, fixed that. Added the chunk ID to the errors.
  • Added Config::credential_methods helper method.
  • Changed Store::get_credential_chunk to return a Credential rather than a Chunk. I originally thought it'd be nice to have a chunk so one can get to the metadata, but it makes it inconvenient for the caller to get the credential, and they already know the chunk ID. The only other metadata is the label, which we know, because it's a credential chunk. Easier to use function is better.
  • Back to Leaf::client_key -- it doesn't get passed a configuration, so it can't access specified credentials. I'll make it so it does. That requires changing all call sites.
  • Hm, the client_key function also needs to access the store. I can re-open it, but that seems wasteful. Unfortunately, not all places that need a client key need to open the store for other reasons. For example, encrypting and decrypting individual chunks may access them directly via the file system and I want to keep that functionality so that troubleshooting when a store is inaccessible via normal methods is still possible.
  • I'll have both Leaf::client_key and Leaf::client_key_from_store functions to cater to both use cases. The latter will be given a store as an argument. Did that and changed everywhere that can to use the new function.
  • This is enough for today. I still need to implement creating credentials while initializing a client so I can do an end-to-end test, but I'm running out of time today.
  • Tidied up the branch, pushed to CI, waited for success, merged.

Summary

I did what I planned to do today, albeit running a little over time. Obnam can now use credential chunks to get the client key, and this should work for all commands.

What's still missing is creating a credential. I'll want to create at least one credential when a client it initialized, but I'll also want to provide ways to manage credentials: adding a new one for the existing client key, and deleting credentials unless there would be none left (i.e., to avoid locking user out of their backups).

Comments?

If you have feedback on this development session, please use the following fediverse thread: https://toot.liw.fi/@liw/115122211036992562.