Skip to content

Commit

Permalink
Merge pull request #71 from intelops/vault-approle-token-fetch
Browse files Browse the repository at this point in the history
api to fetch app role token
  • Loading branch information
vramk23 authored Jan 13, 2024
2 parents e930120 + de03c60 commit c83e08b
Show file tree
Hide file tree
Showing 10 changed files with 553 additions and 51 deletions.
55 changes: 55 additions & 0 deletions internal/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import (
"github.com/pkg/errors"
)

const (
vaultPolicyReadPath = `path "secret/data/%s" {capabilities = ["read"]}`
)

type VaultCredServ struct {
vaultcredpb.UnimplementedVaultCredServer
conf config.VaultEnv
Expand Down Expand Up @@ -84,3 +88,54 @@ func (v *VaultCredServ) DeleteCred(ctx context.Context, request *vaultcredpb.Del
v.log.Infof("delete credential request processed for %s", secretPath)
return &vaultcredpb.DeleteCredResponse{}, nil
}

func (v *VaultCredServ) GetAppRoleToken(ctx context.Context, request *vaultcredpb.GetAppRoleTokenRequest) (*vaultcredpb.GetAppRoleTokenResponse, error) {
v.log.Infof("app role token request for vault path %s with role %s", request.CredentialPath, request.AppRoleName)
vc, err := client.NewVaultClientForTokenFromEnv(v.log, v.conf)
if err != nil {
return nil, err
}

err = vc.EnableAppRoleAuth()
if err != nil {
return nil, err
}

policyData := fmt.Sprintf(vaultPolicyReadPath, request.CredentialPath)
v.log.Infof("creating policy %s", policyData)
policyName := request.AppRoleName + "-policy"
err = vc.CreateOrUpdatePolicy(policyName, policyData)
if err != nil {
v.log.Errorf("error while creating Vault policy for app role %s", request.AppRoleName, err)
return nil, err
}

err = vc.CreateOrUpdateAppRole(request.AppRoleName, []string{policyName})
if err != nil {
v.log.Errorf("error while creating Vault policy for app role %s", request.AppRoleName, err)
return nil, err
}

token, err := vc.AuthenticateWithAppRole(request.AppRoleName)
if err != nil {
return nil, err
}

v.log.Infof("app role token generated for path %s with role %s", request.CredentialPath, request.AppRoleName)
return &vaultcredpb.GetAppRoleTokenResponse{Token: token}, nil
}

func (v *VaultCredServ) GetCredentialWithAppRoleToken(ctx context.Context, request *vaultcredpb.GetCredentialWithAppRoleTokenRequest) (*vaultcredpb.GetCredentialWithAppRoleTokenResponse, error) {
vc, err := client.NewVaultClientForToken(v.log, v.conf, request.Token)
if err != nil {
return nil, err
}

credential, err := vc.GetCredential(ctx, CredentialMountPath(), request.CredentialPath)
if err != nil {
v.log.Error("app role get credential request failed for %s, %v", request.CredentialPath, err)
return nil, err
}
v.log.Infof("app role get credential request processed for %s", request.CredentialPath)
return &vaultcredpb.GetCredentialWithAppRoleTokenResponse{Credential: credential}, nil
}
13 changes: 11 additions & 2 deletions internal/client/vault.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ type VaultClient struct {

func NewVaultClientForServiceAccount(ctx context.Context, log logging.Logger, conf config.VaultEnv) (*VaultClient, error) {
if conf.VaultTokenForRequests {
return NewVaultClientForVaultToken(log, conf)
return NewVaultClientForTokenFromEnv(log, conf)
}

vc, err := NewVaultClient(log, conf)
Expand All @@ -42,7 +42,7 @@ func NewVaultClientForServiceAccount(ctx context.Context, log logging.Logger, co
return vc, nil
}

func NewVaultClientForVaultToken(log logging.Logger, conf config.VaultEnv) (*VaultClient, error) {
func NewVaultClientForTokenFromEnv(log logging.Logger, conf config.VaultEnv) (*VaultClient, error) {
vc, err := NewVaultClient(log, conf)
if err != nil {
return nil, err
Expand Down Expand Up @@ -70,6 +70,15 @@ func NewVaultClientForVaultToken(log logging.Logger, conf config.VaultEnv) (*Vau
return vc, nil
}

func NewVaultClientForToken(log logging.Logger, conf config.VaultEnv, token string) (*VaultClient, error) {
vc, err := NewVaultClient(log, conf)
if err != nil {
return nil, err
}
vc.c.SetToken(token)
return vc, nil
}

func NewVaultClient(log logging.Logger, conf config.VaultEnv) (*VaultClient, error) {
cfg, err := prepareVaultConfig(conf)
if err != nil {
Expand Down
26 changes: 25 additions & 1 deletion internal/client/vault_auth.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package client

import (
"fmt"
"strings"

"github.com/hashicorp/vault/api"
Expand Down Expand Up @@ -93,7 +94,7 @@ func (v *VaultClient) EnableAppRoleAuth() error {
return err
}

func (v *VaultClient) CreateAppRole(roleName string) (string, string, error) {
func (v *VaultClient) createOrUpdateAppRole(roleName string) (string, string, error) {
roleIDResponse, err := v.c.Logical().Read("auth/approle/role/" + roleName + "/role-id")
if err != nil {
return "", "", err
Expand All @@ -109,3 +110,26 @@ func (v *VaultClient) CreateAppRole(roleName string) (string, string, error) {

return roleID, secretID, nil
}

func (v *VaultClient) AuthenticateWithAppRole(roleName string) (string, error) {
roleID, secretID, err := v.createOrUpdateAppRole(roleName)
if err != nil {
return "", err
}

data := map[string]interface{}{
"role_id": roleID,
"secret_id": secretID,
}

secret, err := v.c.Logical().Write("auth/approle/login", data)
if err != nil {
return "", err
}

if secret == nil || secret.Auth == nil || secret.Auth.ClientToken == "" {
return "", fmt.Errorf("authentication failed")
}

return secret.Auth.ClientToken, nil
}
19 changes: 19 additions & 0 deletions internal/client/vault_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,25 @@ func (v *VaultClient) CreateOrUpdateRole(roleName string, serviceAccounts, names
return nil
}

func (v *VaultClient) CreateOrUpdateAppRole(roleName string, policies []string) error {
roleData := make(map[string]interface{})

roleData["policies"] = policies
roleData["max_ttl"] = 1800000
roleData["secret_id_ttl"] = 0
roleData["token_ttl"] = 0
roleData["token_max_ttl"] = 0

path := fmt.Sprintf("/auth/approle/role/%s", roleName)
_, err := v.c.Logical().Write(path, roleData)
if err != nil {
return err
}

v.log.Infof("Updated app role %s", roleName)
return nil
}

func (v *VaultClient) DeleteRole(roleName string) error {
path := fmt.Sprintf("/auth/kubernetes/role/%s", roleName)
_, err := v.c.Logical().Delete(path)
Expand Down
2 changes: 1 addition & 1 deletion internal/job/vault-cred-sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func (v *VaultCredSync) Run() {
}
}

vc, err := client.NewVaultClientForVaultToken(v.log, v.conf)
vc, err := client.NewVaultClientForTokenFromEnv(v.log, v.conf)
if err != nil {
v.log.Errorf("%s", err)
return
Expand Down
2 changes: 1 addition & 1 deletion internal/job/vault_policy_watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func (v *VaultPolicyWatcher) CronSpec() string {

func (v *VaultPolicyWatcher) Run() {
v.log.Debug("started vault policy watcher")
vc, err := client.NewVaultClientForVaultToken(v.log, v.conf)
vc, err := client.NewVaultClientForTokenFromEnv(v.log, v.conf)
if err != nil {
v.log.Errorf("%s", err)
return
Expand Down
5 changes: 0 additions & 5 deletions internal/policy/vault_policy_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,6 @@ func (p *VaultPolicyHandler) UpdateVaultRoles(ctx context.Context, vc *client.Va
return err
}

err = vc.EnableAppRoleAuth()
if err != nil {
return err
}

existingPolicies, err := vc.ListPolicies()
if err != nil {
return err
Expand Down
Loading

0 comments on commit c83e08b

Please sign in to comment.