Closed ram-infrac closed 6 years ago
This looks ok to me. My only concern is that the API may be over a non-secure HTTP connection.
Openstorage should only define the Secrets interface and provide a REST layer. The actual implementation of this interface does not need to be in openstorage. We can follow the VolumeDriver model where the actual implementation may not reside in openstorage package but the volume driver is still supported.
Ques- 1 : how should we manage packages for PX API moving into osd, let's say like above should we create seperate package for each section /openstorage/schedule, openstorage/services etc?
You can keep secrets as a separate package with its own interface. But the REST server routes will have to be added in api/server/routes.go
Ques- 2 : how this interface implementation will be hooked with storage vendor specific implementation?
We do not need to have a tight coupling between a storage vendor and the secrets implementation. A storage vendor can opt out of using a Secrets interface just like it can opt out of using the Cluster interface.
So here is a rough guideline what I think we should do.
openstorage/secrets/manager.go
type SecretsManager interface {
// Register registers a new secret implementation
Register(name string, secrets Secrets)
// Get returns a secret implementation
Get(name string) Secrets
}
// Actual implementation of the above API here
openstorage/secrets/api.go
type Secrets interface {
// Login create session with secret store
SecretLogin(secretType int, secretConfig map[string]string) error
// SetClusterSecretKey sets the cluster wide secret key
SetClusterSecretKey(secretKey string, override bool) error
//CheckSecretLogin validates session with secret store
CheckSecretLogin() error
}
// Actual implementation of above API not needed.
The REST server layer would look something like this
func setClusterSecretKey(r http.Request, w http.ResponseWriter) error {
sname := r.GetParam("secretsImplementor")
secretKey := r.GetParam("secretkey")
override := r.GetParam("override")
secretManager.Get(sname).SetClusterSecretKey(secretKey, override)
}
The REST client layer would set the above secretsImplementor
param value.
This is just one way of implementing it and we can discuss other approaches here as well.
@piyush-nimbalkar What do you think?
Thanks for feedback aditya, just one question with above implementation approach for other PX API sections lets say service PX API, do we need to create similar separate model for each of them or we can combine them in some way
@adityadani , @ram-infrac , and myself met offline and came up with the following design for this (and possibly future APIs):
RegisterXXXManager
, in this case we propose to extend the clusterAPI to have a RegisterSecretManager
which would accept an implementation of the SecretManager
interface. Any call to RegisterXXXManager
would override the current handler in the server.Not implemented
or have a generic implementation. This API would have its own simple/fake implementation of the SecretManager
.Few suggestions, have commented on the PR as well, but would be good to discuss here as well -
ClusterSecretKey
, we should rename it to DefaultSecretKey
or ClusterWideSecretKey
GetClusterSecretKey/GetDefaultSecretKey
? This will not give the value of the actual cluster wide secret key but the can return the default secret key which could be used to retrieve the value using GetSecret()
SetSecret()
take a map[string]interface{}
to keep it generic and the GetSecret()
return the same?SecretLogin(secretType int, secretConfig map[string]string) error
. Instead of int secretType
, we should take string because it seems more readable and easy to manage.@lpabon @adityadani @ram-infrac
+1 for renaming ClusterSecretKey to DefaultSecretKey Yes we should have a GetDefaultSecretKey API.
Instead of a map[string]interface{} why not keep the value simple as an interface{} ?
Also the secretType should be taken from libopenstorage/secrets and enum string can be defined with all the supported secret types.
Yes interface{} is better
Instead of a map[string]interface{} why not keep the value simple as an interface{}
REST API endpoints will be called as,
GET /cluster/secret/secrets/
PUT /cluster/secret/secrets/ Body: {value: } GET /cluster/secret/defaultsecretkey PUT /cluster/secret/defaultsecretkey Body: {value: } GET /cluster/secret/secrets/verify POST /cluster/secrets/login
Should first two listen on /cluster/secret or seperate verb to be added as above?
Discussed with @adityadani. Let's have it this way, instead of the double secret/secrets paths:
GET /cluster/secrets/<secret_id>
PUT /cluster/secrets/<secret_id> Body: {value: }
GET /cluster/secrets/defaultsecretkey
PUT /cluster/secrets/defaultsecretkey Body: {value: }
GET /cluster/secrets/verify
POST /cluster/secrets/login Body: {}
Is this a BUG REPORT or FEATURE REQUEST?: FEATURE
Reason needed
To create OSD-SDK Move internal PX API to OSD to create external API SDK. This is first API set we will move to OSD.
1. Manage secret commands
Secret commands allows user to manage secret keys. You can encrypt volumes using given secret key.
a. Set Cluster Secret Key;
Cluster wide secret key is basically a key value pair where the value part is the secret that is used as a passphrase for encrypting volumes. A cluster wide secret key is a common key that can be used to encrypt all volumes.
Example Request:
POST /v1/setClusterSecretKey
Example Response: Cluster Secret Key successfully set.
b. Login to Secret
Allow login to secure secret store e.g vault, kvdb,aws etc
Example Request:
POST /v1/secretsLogin
Example Response: Secrets Login Succeeded
c. Set value for given secret key
stores the data against the given key in the secret store
Example Request:
POST /v1/setSecret
Example Response: Secret succuessfully set.
d. Get value of secret key
retrieves the data for the given key.
Example Request:
GET /v1/getSecret
Example Response: testval1
Interface
restServer
interface, also will have appropiate handler function implementation for endpoints.