notary
notary copied to clipboard
grpc key store client feature
Reconnecting on the feature request discussed in Issue #1388 "Generalized Notary Client External Signer/HSM Interface". To refresh your memory, this was a request that notary offer an option to interface with HSMs external to the notary client that are typically used in enterprise environments. In addition to the discussion linked in the issue above, I submitted an initial discussion/review PR on a proposed GRPC proto file last fall, under PR https://github.com/theupdateframework/notary/pull/1393 for detailed discussion.
Since then, I've coded up the functionality discussed and have it up and running. I would love to contribute this proposal back to the notary project. As this is a fairly large PR and I am not a previous contributor to Notary, please coach me if any part of this PR doesn't meet expectations or needs additional work and/or explanation. I'm happy to make any changes necessary to make this a worthwhile and acceptable contribution.
Some notes on the new functionality:
This PR provides for client GRPC key store functionality that resides within the notary client as a new key store option (in addition to the current fileKeyStore
and yubiKeyStore
). The new feature is centered in notary/trustmanager/grpckeystore/client.go
, which implements the trustmanager.KeyStore
and data.PrivateKey
interfaces on the notary side of things, and translates those to GRPC calls to a GRPC server. The GRPC communication is specified in the trustmanager/grpckeystore/grpckeystore.proto
file which defines the communication between the grpc key store client (notary) and the grpc key store server (connected to an HSM).
The enterprise HSM owner is expected to write GRPC server functionality and integrate with their specific HSM solution. With that said,trustmanager/grpckeystore/client_test.go
has an imbedded GRPC server for testing which would be a good starting point for anyone interested in coding a working server.
In addition to the tests specified in trustmanager/grpckeystore/client_test.go
, this functionality has been tested against a live enterprise level HSM. Both RSA and ECDSA keys were tested. For RSA, both rsapkcs1v15 and rsapss signature algorithms have been tested. I didn't get ED25519 keys up and running since go's x509.ParsePKIXPublicKey
doesn't seem to have support for parsing ED25519 ASN.1 public keys, but it should work fine once that is added.
In the issue #1388 discussion, we chatted about the need for a secure HSM to never divulges its private key data. To implement this in notary, I added a new GenerateKey
method to the trustmanager.Keystore
interface, and modified the current key stores (generic and yubi) to simply return "not supported" when their GenerateKey
implementations. At some point, the yubi key store might be interested in supporting this too.
This PR hits quite a few files, but hopefully it's not as bad as it looks...the changes to many files are simply related to the need for the GRPC key store client to have a bit of configuration which added a new parameter to the commonly used NewFileCachedRepository
calls.
For additional detail/context, I've added notes below what was changed in each file, but please don't hesitate to ask me to provide more information on any approach or clarify any detail.
notary/client/client.go:
-
getKeyStores
call modified to pass through GRPC key store configuration when key stores are launched.
notary/client/repo_pkcs11.go notary/client/repo.go:
- changed the list building logic for the the key store list to be a bit more flexible for adding more key stores - previously it was a bit too focused just on just file keystore and/or yubikey. Now easily accept more key stores.
- added GRPC key store as the preferred key store to try first, when configured and active.
notary/client/backwards_compatiblity_test.go notary/client/client_test.go notary/client/client_update_test.go notary/client/example_client_test.go notary/cmd/notary/keys_test.go
- all these test files contain calls to
NewFileCachedRepository
. Added a blankgrpckeystore.GRPCClientConfig{}
as a new parameter.
notary/cmd/notary/delegations.go notary/cmd/notary/keys.go notary/cmd/notary/repo_factory.go
- all of these are callers of
NewFileCachedRepository
. As such, they all now callgetGRPCKeyStore
to get the GRPC key store configuration, and use that configuration when callingNewFileCachedRepository
notary/cmd/notary/tuf.go
- Implements
getGRPCKeyStore
which parses the new GRPC key store configuration. The new configuration elements for the GPRC key store are:
grpc_keystore
url: (required) The destination url for the GRPC key store server. Its
configuration is required if a GRPC key store is in use. If not
configured, the GRPC key store functionality will not be activated.
root_ca: (optional) Full path for trusted root CA file used verifying the
server's TLS certificate. If not configured, the server's certificate
is not verified. The GRPC client does require TLS connections.
tls_client_cert: (optional) Full path for TLS client certificate file. It
must be configured when TLS client authentication is in use on the
server. It does not need to be configured if the server is not
authenticating the client via TLS.
tls_client_key: (optional) Full path for TLS client key file. It
must be configured when TLS client authentication is in use on the
server. It does not need to be configured if the server is not
authenticating the client via TLS.
dial_timeout: (optional) This is the duration that notary will wait when
first attempting to connect to a GRPC key store server. The default is
5 seconds. If the timeout expires without connecting to a server,
the GRPC key store functionality will not be activated.
blocking_timeout: (optional) This is the duration that notary will wait
for an in-progress remote request to the GRPC key store server after
an initial connection has succeeded. The default is 30 seconds.
If the timeout expires, the in-progress operation will fail.
metadata: (optional) These are optional key/value pairs of metadata passed
to the grpc server using grpc's metadata facility
notary/cryptoservice/crypto_service.go
-
Create
is called when a new key needs to be generated by the notary client. It has been enhanced to query all key stores if they wish to generate keys for the gun/role instead of notary generating a key internally. Key stores are asked in priority order and if any return a key, that key is returned as the key for the gun/role. If no key store returns a key,Create
will generate one internally as before.
notary/trustmanager/grpckeystore/grpckeystore.proto
- This is the GRPC proto file for the GRPC connection
notary/trustmanager/grpckeystore/grpckeystore.pb.go
- This is the generated code from the GRPC proto file. That is, the output of
protoc -I ./ ./grpckeystore.proto --go_out=plugins=grpc:.
notary/trustmanager/grpckeystore/generator.go
- Allows "go generate" command to be used to generate the grpckeystore.pb.go file.
notary/trustmanager/grpckeystore/client.go
- Implements the GRPC key store client functionality by implementing
notary's
trustmanager.KeyStore
interface and also acts GRPC client. An externally supplied GRPC server must also be supplied to complete the remote
notary/trustmanager/grpckeystore/client_test.go
- Tests for client.go. To properly test the client, an entire test GRPC server is provided.
notary/trustmanager/yubikey/yubikeystore.go
- Added the new
GenerateKey
method of thetrustmanager.keystore
interface which returns "Not Supported" for now. At some point in the future, if it was deemed useful for yubi to generate keys, this feature could easily be added.
notary/trustmanager/interfaces.go
- Added GenerateKey(keyInfo KeyInfo) (data.PrivateKey, error) to the KeyStore interface
notary/trustmanager/keystore.go
- Added the new GenerateKey method of the
trustmanager.keystore
interface which returns "Not Supported" to the GenericKeyStore.
notary/tuf/utils/pkcs8.go
- added a new function
ParseECDSASignature
that accepts an ASN.1 encoded ECDSA signature and returns the R,S concatenated format. I put this function here instead of in grpckeystore since it seemed it could be reused by other packages (for example, yubikeystore could certainly use it).
notary/tuf/utils/pkcs8.go
- added a new function
ParsePublicKey
that accepts an ASN.1 encoded public key and parses it to a data.PublicKey. I put this function here instead of in grpckeystore since it seemed it could be reused by other packages.
Signed-off-by: Dave Billing [email protected]
Can one of the admins verify this patch?
Hi admins, can I get some preliminary feedback on this PR in the next week or so? doesn't have to be a fine tooth comb review, just hoping to get some feedback whether or not I'm on the right track with this feature since it's been some time since our last discussions under https://github.com/theupdateframework/notary/pull/1393. I'm quite happy to continue to improve the submission and get the code coverage up, just want to avoid wrapping things too tight in the tests without first getting admin feedback on the overall feature design and code structuring.
Hi admins, I would like to echo @dbilling's request to get feedback on this so this can get merged. My company has the same requirement that @dbilling is solving and this would make Notary something we could use enterprise-wide, which we are eager to do.
Please sign your commits following these rules: https://github.com/moby/moby/blob/master/CONTRIBUTING.md#sign-your-work The easiest way to do this is to amend the last commit:
$ git clone -b "1388-grpc-keystore-client" [email protected]:dbilling/notary.git somewhere
$ cd somewhere
$ git rebase -i HEAD~842359064784
editor opens
change each 'pick' to 'edit'
save the file and quit
$ git commit --amend -s --no-edit
$ git rebase --continue # and repeat the amend for each commit
$ git push -f
Amending updates the existing PR. You DO NOT need to open a new one.
👍 I work for a large organization that is looking to back our software signing solution with an HSM. I am very interested in getting this PR reviewed/merged into Notary to enable this capability. I like that GRPC will abstract the HSM communication since PKCS11 may lead to manufacturer-specific implementation problems (i.e. yubikey and the touch to sign feature)
Following up on this to get more attention on it. There are now quite a few large companies interested in getting this feature ASAP. What can we do to help expedite the merge of this PR?
Happy new year everyone. Any chance we can see this merged early this year? It looks like it would help a lot of large organizations be able to use Notary with their more sensitive signing keys.
I work for a large organization too and we also like this feature to be merged, so that we could use one solution for all signing stuff.
Can we please get this feature implemented or at least use a standard PKCS11 interface for signing? This really is a road block for large enterprises who want to sign using keys in their HSM (and not just the root key).