summaryrefslogtreecommitdiffstats
path: root/sms-service/src/sms/backend/vault.go
diff options
context:
space:
mode:
Diffstat (limited to 'sms-service/src/sms/backend/vault.go')
-rw-r--r--sms-service/src/sms/backend/vault.go120
1 files changed, 107 insertions, 13 deletions
diff --git a/sms-service/src/sms/backend/vault.go b/sms-service/src/sms/backend/vault.go
index ed05835..3360197 100644
--- a/sms-service/src/sms/backend/vault.go
+++ b/sms-service/src/sms/backend/vault.go
@@ -43,6 +43,8 @@ type Vault struct {
internalDomainMounted bool
vaultTempTokenTTL time.Time
vaultToken string
+ shards []string
+ prkey string
}
// Init will initialize the vault connection
@@ -63,6 +65,11 @@ func (v *Vault) Init() error {
v.vaultMountPrefix = "sms"
v.internalDomain = "smsinternaldomain"
v.internalDomainMounted = false
+ v.prkey = ""
+
+ // Initialize vault if it is not already
+ // Returns immediately if it is initialized
+ v.initializeVault()
err = v.initRole()
if err != nil {
@@ -81,9 +88,32 @@ func (v *Vault) GetStatus() (bool, error) {
smslogger.WriteError(err.Error())
return false, errors.New("Error getting status")
}
+
return sealStatus.Sealed, nil
}
+// RegisterQuorum registers the PGP public key for a quorum client
+// We will return a shard to the client that is registering
+func (v *Vault) RegisterQuorum(pgpkey string) (string, error) {
+ if v.shards == nil {
+ smslogger.WriteError("Invalid operation")
+ return "", errors.New("Invalid operation")
+ }
+ // Pop the slice
+ var sh string
+ sh, v.shards = v.shards[len(v.shards)-1], v.shards[:len(v.shards)-1]
+ if len(v.shards) == 0 {
+ v.shards = nil
+ }
+
+ // Decrypt with SMS pgp Key
+ sh, _ = smsauth.DecryptPGPString(sh, v.prkey)
+ // Encrypt with Quorum client pgp key
+ sh, _ = smsauth.EncryptPGPString(sh, pgpkey)
+
+ return sh, nil
+}
+
// Unseal is a passthrough API that allows any
// unseal or initialization processes for the backend
func (v *Vault) Unseal(shard string) error {
@@ -257,7 +287,7 @@ func (v *Vault) CreateSecretDomain(name string) (SecretDomain, error) {
// Rollback the mount operation since we could not
// store the UUID for the mount.
v.vaultClient.Sys().Unmount(mountPath)
- return SecretDomain{}, errors.New("Unable to store Secret Domain UUID. Retry.")
+ return SecretDomain{}, errors.New("Unable to store Secret Domain UUID. Retry")
}
return SecretDomain{uuid, name}, nil
@@ -308,6 +338,7 @@ func (v *Vault) DeleteSecretDomain(name string) error {
// DeleteSecret deletes a secret mounted on the path provided
func (v *Vault) DeleteSecret(dom string, name string) error {
+
err := v.checkToken()
if err != nil {
smslogger.WriteError(err.Error())
@@ -326,12 +357,32 @@ func (v *Vault) DeleteSecret(dom string, name string) error {
return nil
}
-// initRole is called only once during the service bring up
+// initRole is called only once during SMS bring up
+// It initially creates a role and secret id associated with
+// that role. Later restarts will use the existing role-id
+// and secret-id stored on disk
func (v *Vault) initRole() error {
+
// Use the root token once here
v.vaultClient.SetToken(v.vaultToken)
defer v.vaultClient.ClearToken()
+ // Check if roleID and secretID has already been created
+ rID, error := smsauth.ReadFromFile("auth/role")
+ if error != nil {
+ smslogger.WriteWarn("Unable to find RoleID. Generating...")
+ } else {
+ sID, error := smsauth.ReadFromFile("auth/secret")
+ if error != nil {
+ smslogger.WriteWarn("Unable to find secretID. Generating...")
+ } else {
+ v.roleID = rID
+ v.secretID = sID
+ v.initRoleDone = true
+ return nil
+ }
+ }
+
rules := `path "sms/*" { capabilities = ["create", "read", "update", "delete", "list"] }
path "sys/mounts/sms*" { capabilities = ["update","delete","create"] }`
err := v.vaultClient.Sys().PutPolicy(v.policyName, rules)
@@ -340,12 +391,6 @@ func (v *Vault) initRole() error {
return errors.New("Unable to create policy for approle creation")
}
- rName := v.vaultMountPrefix + "-role"
- data := map[string]interface{}{
- "token_ttl": "60m",
- "policies": [2]string{"default", v.policyName},
- }
-
//Check if applrole is mounted
authMounts, err := v.vaultClient.Sys().ListAuth()
if err != nil {
@@ -366,6 +411,12 @@ func (v *Vault) initRole() error {
v.vaultClient.Sys().EnableAuth("approle", "approle", "")
}
+ rName := v.vaultMountPrefix + "-role"
+ data := map[string]interface{}{
+ "token_ttl": "60m",
+ "policies": [2]string{"default", v.policyName},
+ }
+
// Create a role-id
v.vaultClient.Logical().Write("auth/approle/role/"+rName, data)
sec, err := v.vaultClient.Logical().Read("auth/approle/role/" + rName + "/role-id")
@@ -385,6 +436,25 @@ func (v *Vault) initRole() error {
v.secretID = sec.Data["secret_id"].(string)
v.initRoleDone = true
+ /*
+ * Revoke the Root token.
+ * If a new Root Token is needed, it will need to be created
+ * using the unseal shards.
+ */
+ err = v.vaultClient.Auth().Token().RevokeSelf(v.vaultToken)
+ if err != nil {
+ smslogger.WriteWarn(err.Error())
+ smslogger.WriteWarn("Unable to Revoke Token")
+ } else {
+ // Revoked successfully and clear it
+ v.vaultToken = ""
+ }
+
+ // Store the role-id and secret-id
+ // We will need this if SMS restarts
+ smsauth.WriteToFile(v.roleID, "auth/role")
+ smsauth.WriteToFile(v.secretID, "auth/secret")
+
return nil
}
@@ -428,16 +498,39 @@ func (v *Vault) checkToken() error {
// vaultInit() is used to initialize the vault in cases where it is not
// initialized. This happens once during intial bring up.
func (v *Vault) initializeVault() error {
+ // Check for vault init status and don't exit till it is initialized
+ for {
+ init, err := v.vaultClient.Sys().InitStatus()
+ if err != nil {
+ smslogger.WriteError("Unable to get initStatus, trying again in 10s: " + err.Error())
+ time.Sleep(time.Second * 10)
+ continue
+ }
+ // Did not get any error
+ if init == true {
+ smslogger.WriteInfo("Vault is already Initialized")
+ return nil
+ }
+
+ // init status is false
+ // break out of loop and finish initialization
+ smslogger.WriteInfo("Vault is not initialized. Initializing...")
+ break
+ }
+
+ // Hardcoded this to 3. We should make this configurable
+ // in the future
initReq := &vaultapi.InitRequest{
- SecretShares: 5,
+ SecretShares: 3,
SecretThreshold: 3,
}
- pbkey, _, err := smsauth.GeneratePGPKeyPair()
+ pbkey, prkey, err := smsauth.GeneratePGPKeyPair()
+
if err != nil {
smslogger.WriteError("Error Generating PGP Keys. Vault Init will not use encryption!")
} else {
- initReq.PGPKeys = []string{pbkey, pbkey, pbkey, pbkey, pbkey}
+ initReq.PGPKeys = []string{pbkey, pbkey, pbkey}
initReq.RootTokenPGPKey = pbkey
}
@@ -448,8 +541,9 @@ func (v *Vault) initializeVault() error {
}
if resp != nil {
- //v.writeUnsealShards(resp.KeysB64)
- v.vaultToken = resp.RootToken
+ v.prkey = prkey
+ v.shards = resp.KeysB64
+ v.vaultToken, _ = smsauth.DecryptPGPString(resp.RootToken, prkey)
return nil
}