Endorsement Store Interface Implementation - #435
Conversation
Definition of protobuf messages used as arguments for endorsement store interface. Signed-off-by: Dhanus M Lal <Dhanus.MLal@fujitsu.com>
The store plugin interface definition and implementation of the RPC layer (for go-plugin client and server). Endorsement store interface is an aggregation of IEndorsementStoreReader and IEndorsementStoreWriter, for read and write operations on endorsement store respectively. Signed-off-by: Dhanus M Lal <Dhanus.MLal@fujitsu.com>
Register endorsementstore targets in the build system and docker deployment. Signed-off-by: Dhanus M Lal <Dhanus.MLal@fujitsu.com>
The coserv proxy plugins are now store plugins, with only the ExecuteCoservQuery method implemented. Note: builtin loader may not work. Note: the new stores (amd and nvidia) have not been tested yet. Signed-off-by: Dhanus M Lal <Dhanus.MLal@fujitsu.com>
Add corimstore based store plugin. The implementation converts existing store implementation into a plugin. Signed-off-by: Dhanus M Lal <Dhanus.MLal@fujitsu.com>
Update VTS to use the IEndorsementStore interface. Signed-off-by: Dhanus M Lal <Dhanus.MLal@fujitsu.com>
q -> %q Signed-off-by: Dhanus M Lal <Dhanus.MLal@fujitsu.com>
Signed-off-by: Dhanus M Lal <Dhanus.MLal@fujitsu.com>
Signed-off-by: Dhanus M Lal <Dhanus.MLal@fujitsu.com>
setrofim
left a comment
There was a problem hiding this comment.
I don't think the notion of a "media type" makes sense in the context of the store backend. We don't really want to be selecting the backend based on it. I also don't like the somewhat arbitrary distinction between "primary" and "fallback" backends.
Suggestion: store backends are identified solely by name; for the sake of reusing existing plugin loader/manager the media type APIs implemented via a shim to to just return the name, and this is hidden as much as possible. Store configuration contains a list of backend names, which specifies which frontend plugins will actually be actively used by the store frontend. When servicing requests, the frontend tries the backends in the order specified until.
|
|
||
| func NewStore() *DefaultStore { | ||
| logger := log.Named(PluginName) | ||
| logger.Debug("initializing default store") |
There was a problem hiding this comment.
This log line belongs inside DefaultStore.Init() below, not here.
|
|
||
| func (s *DefaultStore) Init(params *plugin.Parameters) error { | ||
| if params == nil { | ||
| panic("parameters are required for corimstore") |
There was a problem hiding this comment.
Return an error rather than panic here.
|
|
||
| store, err := corimstore.Open(context.Background(), cfg.StoreConfig()) | ||
| if err != nil { | ||
| panic(err) |
There was a problem hiding this comment.
Return the error rather than panic.
| // initialize it here. | ||
| if strings.Contains(cfg.DSN, ":memory:") { | ||
| if err := store.Init(); err != nil { | ||
| panic(err) |
There was a problem hiding this comment.
Return the error rather than panic.
| return SchemeName | ||
| } | ||
|
|
||
| func (s *DefaultStore) GetSupportedMediaTypes() map[string][]string { |
There was a problem hiding this comment.
I don't think the concept of a "supported media type" really makes sense for a store backend. I think we may want a different plugin interface for this.
There was a problem hiding this comment.
Since store plugins can also serve CoSERV queries, the supported media types can be the CoSERV media types they support.
| return res, err | ||
| } | ||
|
|
||
| func (s *DefaultStore) ExecuteCoservQuery(mediaType, query string) (*coserv.Coserv, error) { |
There was a problem hiding this comment.
Why does this take a mediaType? It does not appear to be used, and also clashes with remaining store API that takea label instead. The media type should be resolved to a label by the time the request reaches the store.
| } | ||
|
|
||
| func (s CoservProxyHandler) GetEndorsements(tenantID string, query string) ([]byte, error) { | ||
| func (s CoservProxyHandler) ExecuteCoservQuery(mediaType, query string) (*coserv.Coserv, error) { |
There was a problem hiding this comment.
Ditto here. the media type should be resolved by this point.
|
|
||
| if err := o.CoservProxyPluginManager.Close(); err != nil { | ||
| o.logger.Errorf("coserv plugin manager shutdown failed: %v", err) | ||
| // FIXME: close stores while closing store manager |
There was a problem hiding this comment.
Why do we need Line 174..?
Should not the Sore manager be responsible for closing the Stores!
There was a problem hiding this comment.
That's correct. But with the current implementation of the store manager, it is not possible. This is because the pluggable interface lacks a Close method, which can be called at the end (similar to the Init method that gets called at the start). The StoreManager.Close method calls the plugin.Client.Kill method on the store plugin client, which terminates the plugin process, without closing the file descriptors and other resources that are in use by the plugin process. The note here was for myself and this should be fixed before the pull request can be merged.
|
|
||
| coservProxyDerived := c.assembleCoservMediaTypes( | ||
| c.CoservProxyPluginManager.GetRegisteredMediaTypes(), | ||
| c.StoreManager.GetRegisteredMediaTypes(), |
There was a problem hiding this comment.
Agree with Sergei, the Store should not have a Media Type.
The functionality must be changed!
yogeshbdeshpande
left a comment
There was a problem hiding this comment.
Have started reviewing it, will complete by the end of the day today!
thomas-fossati
left a comment
There was a problem hiding this comment.
Thanks for this!
I have inlined a few comments.
| if err != nil { | ||
| o.logger.Warnw("could not find in store", "valID", valID, "error", err) |
There was a problem hiding this comment.
When joining the dots between L526-527 and L532-533, it looks like any store errors will be seen as ENOTFOUND from the pov of the caller. If that's the case, the caller (L446) will log and move on. So, imagine the case where the DB is down, valueTriples stays empty, getValueTriples returns ENOTFONUD, the caller logs a warning and proceeds with nil endorsements into AppraiseEvidence. I don't think it's what we want, right?
There was a problem hiding this comment.
All errors other than ENOTFOUND from all the stores are logged as warning (/vts/trustedservices/store.go:122). The reason was to avoid the operation from failing some of the stores are down. But now I realized that this is a bad idea. Will update to return on unexpected store errors.
| if err := CloseCorimStore(o.StoreManager); err != nil { | ||
| o.logger.Errorf("failed to close corim store: %v", err) | ||
| } | ||
|
|
||
| if err := o.Store.Close(); err != nil { | ||
| o.logger.Errorf("store closure failed: %v", err) | ||
| if err := o.StoreManager.Close(); err != nil { | ||
| o.logger.Errorf("store plugin manager shutdown failed: %v", err) |
There was a problem hiding this comment.
Potential ENOCOFFEE :-) Would this effectively result in a double close?
There was a problem hiding this comment.
No, StoreManager.Close does not properly close the corim-store (see #435 (comment)). This is a hacky fix and should be fixed before merging the pr.
| if err != nil { | ||
| o.logger.Infof("could not find coserv result in store") |
There was a problem hiding this comment.
What is the reasoning behind masking any error as ENOTFOUND/404?
From a ReST perspective, we want to be able to tell our clinets that there is something wrong with the service (5xx) rather than with their query (4xx).
There was a problem hiding this comment.
The API layer seems to treats all errors from VTS as Internal Server Error.
coserv:
services/coserv/api/handler.go
Lines 225 to 231 in f997c52
verification:
services/verification/api/handler.go
Lines 414 to 430 in f997c52
But more context can be added to the error. I will try to do that.
|
|
||
| func (s *DefaultStore) ExecuteCoservQuery(mediaType, query string) (*coserv.Coserv, error) { | ||
| s.logger.Infof("got coserv query: %v", query) | ||
| fallbackAuthority, err := comid.NewCryptoKeyTaggedBytes([]byte("dummyauth")) |
There was a problem hiding this comment.
curious: why we need to use this "dummyauth"?
There was a problem hiding this comment.
This is a copy-paste of an older version of the code (before #420). I should update this with the latest changes. Thanks for pointing it out.
| option go_package = "github.com/veraison/services/proto"; | ||
|
|
||
| message GetEndorsementsArgs { | ||
| bytes environment = 1 [json_name = "environemnt-map"]; |
There was a problem hiding this comment.
| bytes environment = 1 [json_name = "environemnt-map"]; | |
| bytes environment = 1 [json_name = "environment-map"]; |
| if subs["coserv"].IsSet("signer") { | ||
| coservContext, err = coserv.NewCoservContextFromViper(subs["coserv"]) | ||
| if err != nil { | ||
| log.Fatal("CoSERV config initialization: %v", err) |
There was a problem hiding this comment.
| log.Fatal("CoSERV config initialization: %v", err) | |
| log.Fatalf("CoSERV config initialization: %v", err) |
This PR implements following:
Address issue #431