-
Notifications
You must be signed in to change notification settings - Fork 370
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
Implement openpgp.cert.d based keystore #3437
Conversation
lib/keystore.cc
Outdated
|
||
/*****************************************************************************/ | ||
|
||
static rpmRC acquire_write_lock(rpmtxn txn) |
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.
The txn handle is the lock, that's the whole point of those things. There's no other locking needed.
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 know. But the standard requires a lockfile on disk as part of the openpgp.cert.d format. If we want other tools to be able to read it we should try to adhere to that.
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 don't see concurrent access with other tools being something we need to support. Poking at rpm directories with external tools is more like a developer convenience thing rather than something we'd be suggesting to users. But, if you want to support locking then the actual lock seems to be missing, https://www.ietf.org/archive/id/draft-nwjw-openpgp-cert-d-00.html#platform-specifics says it should use flock().
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.
...ie it's not the existence of 'writelock' file that is the lock, but a flock() on that file. Mere file existence would be broken lock mechanism because if the process dies in the middle it de-facto leaves a stale lock behind, whereas locks on the file are cleaned up by the OS.
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.
urgs should have read the last sentence, too...
If I read that correctly you are not actually required to delete writelock
the file again. Just to be fine if it doesn't exist. @nwalfield any opinion on that?
Anyway implemented the flock and adjusted the test case.
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.
If I read that correctly you are not actually required to delete writelock the file again. Just to be fine if it doesn't exist.
Yup, that's how such lockfiles commonly work, including our own transaction lock. Only the term "lockfile" is misleading because it makes you think the file itself is the lock, when it's only a placeholder for it.
@@ -275,6 +275,8 @@ static keystore *getKeystore(rpmts ts) | |||
ts->keystore = new keystore_fs(); | |||
} else if (rstreq(krtype, "rpmdb")) { | |||
ts->keystore = new keystore_rpmdb(); | |||
} else if (rstreq(krtype, "openpgp")) { |
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've a feeling we want to leave this name for a proper implementation from Sequoia side, this being a simple standalone version that does not deal with the trust stuff. But lets bikeshed that in the ticket instead.
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.
yeah, I am not too sold on the name either.
This will be useful for the next commit. This still is a mess of C and C++ style strings that we want to clean up later by adding C++ string based path handling and may be using the filesystem C++ library. Related: rpm-software-management#3341
6b56079
to
11bf961
Compare
Another random thought on standard compliance: since this does not process trust-root, it should probably emit a warning if that file exists (eg from doing stuff with an external tool) to make it clear it's not handled. Oh, and on a related note: since the interoperability with other tools is a goal, what better test than actually do so, ie check that sq can read what we produced. |
tests/rpmsigdig.at
Outdated
RPMTEST_CLEANUP | ||
# ------------------------------ | ||
# Test rpmkeys write errors | ||
AT_SETUP([[rpmkeys -K no space left on stdout]]) |
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 looks like a copy-paste leftover, we already have such a test.
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.
Deleted.
11bf961
to
b8599f9
Compare
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.
Overall LGTM, some comments in line.
return RPMRC_FAIL; | ||
|
||
string fp = rpmPubkeyFingerprintAsHex(key); | ||
string dir = fp.substr(0, 2); |
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 routine of obtaining the storage location (where the first two hex chars are the directory name) is a specific thing in this keystore implementation and it's currently duplicated in two places so maybe deserves a separate private method.
That said, we can always do that later, when there's the third use, so feel free to ignore.
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 have considered that, but it doesn't really make things that much better. Guess it really is missing the third place.
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.
Works for me.
@@ -275,6 +275,8 @@ static keystore *getKeystore(rpmts ts) | |||
ts->keystore = new keystore_fs(); | |||
} else if (rstreq(krtype, "rpmdb")) { | |||
ts->keystore = new keystore_rpmdb(); | |||
} else if (rstreq(krtype, "openpgp")) { | |||
ts->keystore = new keystore_openpgp_cert_d(); |
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.
The class name seems a bit verbose to me, how about just keystore_openpgp
? I suppose this would be the defacto standard openpgp keystore implementation so it doesn't have to be more specific than that.
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.
Nevermind the above; I've realized that openpgp
is way too generic, this whole signature business is about OpenPGP (at least keystore_rpmdb
is, too) so just keep the name as is, it's good.
string fp = rpmPubkeyFingerprintAsHex(key); | ||
string dir = fp.substr(0, 2); | ||
string filename = fp.substr(2); | ||
char * filepath = rpmGetPath(rpmtxnRootDir(txn), "%{_keyringpath}/", dir.c_str(), "/", filename.c_str(), NULL); |
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 see a mixed use of rpmGetPath()
and rpmGenPath()
in the keystore.cc module. Is there a reason for preferring one over the other in those places?
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.
Well, rpmGenPath was originally used. But as it only supports 3 pieces I used rpmGetPath 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.
Ack, thanks.
Insertion doesn't seem to follow the spec:
|
That said, it's fine if this is not the goal of this (initial) implementation, in that case having a short note in the commit message would suffice. |
As people don't believe me otherwise: rpmtxnImportPubkey does indeed merge keys... This is a low level storage interface. A lot of functionality about handling keys is in other parts of the code. E.g. the keyring and the rpmts and rpmtxn key handling functions. |
Oh, so it's handled at the level above the keystore itself. Checking that didn't occur to me. I did notice your reply to Neal above regarding "merging is handled" but didn't connect the dots, so thanks for the context! |
This does implement the layout on the file system and the write lock of the openpgp.cert.d proposal according to https://www.ietf.org/archive/id/draft-nwjw-openpgp-cert-d-00.html but not the Trust root, Petname mapping or Trusted introducers. Resolves: rpm-software-management#3341
b8599f9
to
427e5f9
Compare
The latest version you've pushed looks fine. The only remaining questions are:
|
Replying to the first question myself:
That still doesn't ensure true atomicity but this is the best we can do without refactoring |
Well, it kinda does. By not replacing you make sure you fail if a key was added in the mean time instead of just overwriting it without merging. Also as far as rpm is concerned we do have the transaction log (which is represented by the txn parameter passed down) whihc protects parallel access from other rpm instances. |
I would suggest to not get hung up on the names especially as long as they are only internal. We might even still change the name in the configuration as soon as we know what back ends we'll end up with and what exactly they do. |
Ack, let's merge this then. |
Refactor code from the fs backend into shared helper functions
This does implement the layout on the file system and the write lock of the openpgp.cert.d proposal according to
https://www.ietf.org/archive/id/draft-nwjw-openpgp-cert-d-00.html but not the Trust root, Petname mapping or Trusted introducers.
This still is a mess of C and C++ style strings that we want to clean up later by adding C++ string based path handling and may be using the filesystem C++ library.
Resolves: #3341