-
Notifications
You must be signed in to change notification settings - Fork 511
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
adding --role flag to key import #882
Conversation
Can one of the admins verify this patch? |
This is still WIP
|
Thanks for the quick fixing! |
Do you get this error when import keys:
|
@@ -103,6 +103,9 @@ func ImportKeys(from io.Reader, to []Importer) error { | |||
toWrite []byte | |||
) | |||
for block, rest := pem.Decode(data); block != nil; block, rest = pem.Decode(rest) { | |||
if role != "" { |
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 think this conditional logic should be slightly different to match the usage comment - we should check if block.Headers["role"]
exists, and set it to role
if it's empty.
Also, I think this logic should combine with the pathing logic below since to-be-imported delegation keys may not have a path
PEM header. We can check if we have a provided role and if it's a delegation we can write it to private/tuf_keys/<KEY_ID>.key
. If we follow @cyli's suggestion for GUN headers we can include that in the path we construct for non-delegation keys as well.
@HuKeping Yep, that's what we are trying to fix. :) |
@@ -93,7 +94,7 @@ func ExportKeys(to io.Writer, s Exporter, from string) error { | |||
// Each block is written to the subpath indicated in the "path" PEM | |||
// header. If the file already exists, the file is truncated. Multiple | |||
// adjacent PEMs with the same "path" header are appended together. | |||
func ImportKeys(from io.Reader, to []Importer) error { | |||
func ImportKeys(from io.Reader, to []Importer, role string, gun string, passRet notary.PassRetriever) error { |
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.
nit: can we call role
and gun
-> fallbackRole
and fallbackGun
or some such, to make it clear they're only used if there is no provided role or gun/path?
@@ -26,7 +27,7 @@ type Importer interface { | |||
// ExportKeysByGUN exports all keys filtered to a GUN | |||
func ExportKeysByGUN(to io.Writer, s Exporter, gun string) error { | |||
keys := s.ListFiles() | |||
sort.Strings(keys) // ensure consistenct. ListFiles has no order guarantee | |||
sort.Strings(keys) // ensure consistent. ListFiles has no order guarantee |
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.
nit: I think this was originally a typo for consistency
@@ -0,0 +1,27 @@ | |||
-----BEGIN RSA PRIVATE KEY----- |
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.
nit: can we put these keys in the fixtures
directory? Also, you may not need this key without the role header because we other keys (ex: secure.example.com.key
) without headers that we can test with
ce5cf73
to
722a65d
Compare
jenkins, ok to test. |
keyID := decodedKey.ID() | ||
if block.Headers["role"] == tufdata.CanonicalRootRole { | ||
// this is a root key so import it to trustDir/root_keys/ | ||
delete(block.Headers, "gun") |
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.
Non-blocking: Should we move this logic out of the if block? E.g. after setting the path, we can delete the "gun" header if the role is root or a delegation? Since currently it's only deleted if the path is not specified.
require.Len(t, bFinal.Headers, 0) // path header is stripped during import | ||
_, ok := bFinal.Headers["path"] | ||
require.False(t, ok, "expected no path header, should have been removed at import") | ||
require.Equal(t, notary.DefaultImportRole, bFinal.Headers["role"]) // if no role is specified we assume it is a delegation key |
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.
Should we add an assertion that no gun is included in the header as well?
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.
added it, thanks 😄
from, _ := os.OpenFile("../fixtures/precedence.example.com.key", os.O_RDONLY, notary.PrivKeyPerms) | ||
} | ||
|
||
func TestBlockHeaderPrecedencePathGun(t *testing.T) { |
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.
Non-blocking nitpick: should this be "TestBlockHeaderPrecedencePathRole", since the header has both the path and the role, but not the gun?
6dbafff
to
130decd
Compare
err := ImportKeys(in, []Importer{s}, "", "", passphraseRetriever) | ||
require.NoError(t, err) | ||
|
||
bFinal, bRest := pem.Decode(s.data[filepath.Join(notary.NonRootKeysSubdir, "12ba0e0a8e05e177bc2c3489bdb6d28836879469f078e68a4812fc8a2d521497")]) |
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.
Non-blocking question, just because I don't know what we decided for this: it seems like we are ok with one of the base non-root roles not having a gun also (we don't delete it, but we don't error if we can't infer one) - we infer a path being just the non-root subdirectory + the key ID, as you've included in your test.
I'm ok with that, since the user messed this up, but this would mean that earlier versions of docker probably wouldn't be able to use this key? cc @riyazdf @endophage
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'm okay with either method, but I would be tempted to lean towards not importing it since we don't import encrypted keys without a path etc (cases where the user messed up as well). Would make sense to have some consistency there. This would mean changing the code and this test etc since as @cyli mentioned correctly we now just import the key. Happy to do it once we decide @riyazdf @endophage
…e PEM data. need to write tests + address additional concerns Signed-off-by: Avi Vaid <[email protected]>
… defaults etc, need to write tests for this new functionality Signed-off-by: Avi Vaid <[email protected]>
…rors when we don't have enough info to import a key Signed-off-by: Avi Vaid <[email protected]>
Signed-off-by: Avi Vaid <[email protected]>
Signed-off-by: Avi Vaid <[email protected]>
Signed-off-by: Avi Vaid <[email protected]>
… of tests covering more cases, added a delegation add- import and publish flow test Signed-off-by: Avi Vaid <[email protected]>
…being encryption tests and export import testflow test Signed-off-by: Avi Vaid <[email protected]>
15f51cc
to
ef393b6
Compare
LGTM when CI goes green! |
|
||
nBytes, err = tempFile3.Write(pemBytes) | ||
require.NoError(t, err) | ||
tempFile2.Close() |
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.
nit: tempFile3.Close()
@@ -408,8 +415,8 @@ func (k *keyCommander) importKeys(cmd *cobra.Command, args []string) error { | |||
for _, file := range args { | |||
from, err := os.OpenFile(file, os.O_RDONLY, notary.PrivKeyPerms) | |||
defer from.Close() | |||
|
|||
if err = utils.ImportKeys(from, importers); err != nil { | |||
passRetriever := k.getRetriever() |
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.
super non-blocking nit: we can remove this line and just directly use k.getRetriever
in the next line since we don't use the passRetriever
variable elsewhere
…ithout a gun Signed-off-by: Avi Vaid <[email protected]>
LGTM pending CI. Thank you for all of your hard work on this feature! |
Of course, thanks for the detailed review on this PR! 😄 |
Thank you for all your work on this @avaid96! :D |
closes #881
Signed-off-by: Avi Vaid [email protected]