diff options
Diffstat (limited to 'sms-service/src/sms/backend/vault.go')
-rw-r--r-- | sms-service/src/sms/backend/vault.go | 120 |
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 } |