Skip to content

Commit

Permalink
Merge pull request #3851 from MaxMcAdam/anax-3711
Browse files Browse the repository at this point in the history
Issue 3711 - NodeSecret: agbot adds or updates the AgbotSecret interf…
  • Loading branch information
LiilyZhang authored Jul 28, 2023
2 parents 607cbd2 + bf81d13 commit 8f02613
Show file tree
Hide file tree
Showing 10 changed files with 260 additions and 69 deletions.
4 changes: 2 additions & 2 deletions agreementbot/agreementworker.go
Original file line number Diff line number Diff line change
Expand Up @@ -922,14 +922,14 @@ func (b *BaseAgreementWorker) ValidateAndExtractSecrets(consumerPolicy *policy.P
}

// The secret name might be a user private or org wide secret. Parse the name to determine which it is.
secretUser, shortSecretName, err := compcheck.ParseVaultSecretName(secretName, msgPrinter)
secretUser, secretNode, shortSecretName, err := compcheck.ParseVaultSecretName(secretName, msgPrinter)
if err != nil {
glog.Errorf(BAWlogstring(workerId, fmt.Sprintf("error parsing secret %v for policy %v, service %v/%v %v, error: %v", secretName, consumerPolicy.Header.Name, binding.ServiceOrgid, binding.ServiceUrl, binding.ServiceVersionRange, err)))
return err
}

// Call the secret manager plugin to get the secret details.
details, err := b.secretsMgr.GetSecretDetails(b.GetExchangeId(), b.GetExchangeToken(), exchange.GetOrg(deviceId), secretUser, shortSecretName)
details, err := b.secretsMgr.GetSecretDetails(b.GetExchangeId(), b.GetExchangeToken(), exchange.GetOrg(deviceId), secretUser, secretNode, shortSecretName)

if err != nil {
glog.Errorf(BAWlogstring(workerId, fmt.Sprintf("error retrieving secret %v for policy %v, service %v/%v %v, error: %v", secretName, consumerPolicy.Header.Name, binding.ServiceOrgid, binding.ServiceUrl, binding.ServiceVersionRange, err)))
Expand Down
6 changes: 3 additions & 3 deletions agreementbot/governance.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,19 +155,19 @@ func (w *AgreementBotWorker) GovernAgreements() int {
if smSecretName == exchange.GetId(updatedSecretName) {

// Call the secret manager plugin to get the secret details.
secretUser, secretName, err := compcheck.ParseVaultSecretName(exchange.GetId(updatedSecretName), nil)
secretUser, secretNode, secretName, err := compcheck.ParseVaultSecretName(exchange.GetId(updatedSecretName), nil)
if err != nil {
glog.Errorf(logString(fmt.Sprintf("error parsing secret %s, error: %v", updatedSecretName, err)))
continue
}

newBS := make(exchangecommon.BoundSecret)
secretLookupKey := fmt.Sprintf("%v_%v_%v", ag.Org, secretUser, secretName)
secretLookupKey := fmt.Sprintf("%v_%v_%v_%v", ag.Org, secretUser, secretNode, secretName)
//# check if new secret value already retrieved
if val, ok := updatedSecretsMap[secretLookupKey]; ok {
newBS[serviceSecretName] = val
} else {
details, err := w.secretProvider.GetSecretDetails(w.GetExchangeId(), w.GetExchangeToken(), exchange.GetOrg(updatedSecretName), secretUser, secretName)
details, err := w.secretProvider.GetSecretDetails(w.GetExchangeId(), w.GetExchangeToken(), exchange.GetOrg(updatedSecretName), secretUser, secretNode, secretName)
if err != nil {
glog.Errorf(logString(fmt.Sprintf("error retrieving secret %v for policy %v, error: %v", updatedSecretName, ag.PolicyName, err)))
continue
Expand Down
14 changes: 7 additions & 7 deletions agreementbot/secret_updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func (sm *SecretUpdateManager) CheckForUpdates(secretProvider secrets.AgbotSecre
for _, fullSecretName := range secretNames {

secretOrg := exchange.GetOrg(fullSecretName)
secretUser, secretName, err := compcheck.ParseVaultSecretName(exchange.GetId(fullSecretName), nil)
secretUser, secretNode, secretName, err := compcheck.ParseVaultSecretName(exchange.GetId(fullSecretName), nil)
if err != nil {
glog.Errorf(smlogString(fmt.Sprintf("Error parsing secret %s, error: %v", fullSecretName, err)))
continue
Expand All @@ -90,10 +90,10 @@ func (sm *SecretUpdateManager) CheckForUpdates(secretProvider secrets.AgbotSecre

// All secrets that are referenced by a policy or pattern are in the secret update tables, but some of these secrets
// might not exist yet.
secretMetadata, err := secretProvider.GetSecretMetadata(secretOrg, secretUser, secretName)
secretMetadata, err := secretProvider.GetSecretMetadata(secretOrg, secretUser, secretNode, secretName)
if err != nil {
// For secrets that dont exist yet, just ignore them.
glog.Warningf(smlogString(fmt.Sprintf("Error retrieving metadata for secret %s for user %s in org %s metadata, error: %v", secretName, secretUser, secretOrg, err)))
glog.Warningf(smlogString(fmt.Sprintf("Error retrieving metadata for secret %s for user %s for node %s in org %s metadata, error: %v", secretName, secretUser, secretNode, secretOrg, err)))
continue
}

Expand Down Expand Up @@ -180,7 +180,7 @@ func (sm *SecretUpdateManager) UpdatePolicies(org string, exchPolsMetadata map[s
_, secretFullName := bs.GetBinding()
referencedSecrets[fmt.Sprintf("%s/%s", org, secretFullName)] = true

secretUser, secretName, err := compcheck.ParseVaultSecretName(secretFullName, nil)
secretUser, secretNode, secretName, err := compcheck.ParseVaultSecretName(secretFullName, nil)
if err != nil {
glog.Errorf(smlogString(fmt.Sprintf("unable to parse secret name %s, error: %v", secretFullName, err)))
continue
Expand All @@ -192,7 +192,7 @@ func (sm *SecretUpdateManager) UpdatePolicies(org string, exchPolsMetadata map[s
secretLastUpdateTime := time.Now().Unix()

// Get the secret's metadata, if it exists
sm, err := secretProvider.GetSecretMetadata(org, secretUser, secretName)
sm, err := secretProvider.GetSecretMetadata(org, secretUser, secretNode, secretName)
if err != nil {
// The secret should be stored in the table even if it doesnt exist, so that if it is created later
// changes to it will be recognized.
Expand Down Expand Up @@ -284,7 +284,7 @@ func (sm *SecretUpdateManager) UpdatePatterns(org string, exchPatternMetadata ma
// Extract the secret manager secret name
_, secretFullName := bs.GetBinding()

secretUser, secretName, err := compcheck.ParseVaultSecretName(secretFullName, nil)
secretUser, secretNode, secretName, err := compcheck.ParseVaultSecretName(secretFullName, nil)
if err != nil {
glog.Errorf(smlogString(fmt.Sprintf("unable to parse secret name %s, error: %v", secretFullName, err)))
continue
Expand All @@ -297,7 +297,7 @@ func (sm *SecretUpdateManager) UpdatePatterns(org string, exchPatternMetadata ma
referencedSecrets[fmt.Sprintf("%s/%s", secretOrg, secretFullName)] = true

// Get the secret's metadata, if it exists
sm, err := secretProvider.GetSecretMetadata(secretOrg, secretUser, secretName)
sm, err := secretProvider.GetSecretMetadata(secretOrg, secretUser, secretNode, secretName)
if err != nil {
// The secret should be stored in the table even if it doesnt exist, so that if it is created later
// changes to it will be recognized.
Expand Down
14 changes: 12 additions & 2 deletions agreementbot/secrets/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,26 @@ type AgbotSecrets interface {
CreateOrgUserSecret(user, token, org, path string, data SecretDetails) error
DeleteOrgUserSecret(user, token, org, path string) error

ListOrgNodeSecret(user, token, org, path string) error
ListOrgNodeSecrets(user, token, org, node, path string) ([]string, error)
CreateOrgNodeSecret(user, token, org, path string, data SecretDetails) error
DeleteOrgNodeSecret(user, token, org, path string) error

ListUserNodeSecret(user, token, org, path string) error
ListUserNodeSecrets(user, token, org, node, path string) ([]string, error)
CreateUserNodeSecret(user, token, org, path string, data SecretDetails) error
DeleteUserNodeSecret(user, token, org, path string) error

// This function assumes that the plugin maintains an authentication to the secret manager that it can use
// when it doesnt need to call APIs with user creds. The creds used instead have the ability to READ secrets.
// "user" argument is the user who is accessing the secret, "secretUser" is the owner of the secret being accessed,
// if an org-level secret then this will be empty
GetSecretDetails(user, token, org, secretUser, secretName string) (SecretDetails, error)
GetSecretDetails(user, token, org, secretUser, secretNode, secretName string) (SecretDetails, error)

// This function returns the secret manager's metadata about a given secret.
// "user" argument is the user who is accessing the secret, "secretUser" is the owner of the secret being accessed,
// if an org-level secret then this will be empty
GetSecretMetadata(secretOrg, secretUser, secretName string) (SecretMetadata, error)
GetSecretMetadata(secretOrg, secretUser, secretNode, secretName string) (SecretMetadata, error)
}

type SecretDetails struct {
Expand Down
102 changes: 97 additions & 5 deletions agreementbot/secrets/vault/vault.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,20 @@ func (vs *AgbotVaultSecrets) ListOrgSecret(user, token, org, path string) error
return vs.listSecret(user, token, org, path, url)
}

// Available to all users in the org
func (vs *AgbotVaultSecrets) ListOrgNodeSecret(user, token, org, path string) error {
glog.V(3).Infof(vaultPluginLogString(fmt.Sprintf("list secret %v in org %v", path, org)))
url := fmt.Sprintf("%s/v1/openhorizon/metadata/%s"+cliutils.AddSlash(path), vs.cfg.GetAgbotVaultURL(), org)
return vs.listSecret(user, token, org, path, url)
}

// Available to admins and the user that owns the secret
func (vs *AgbotVaultSecrets) ListUserNodeSecret(user, token, org, path string) error {
glog.V(3).Infof(vaultPluginLogString(fmt.Sprintf("list secret %v in org %v as user %v", path, org, user)))
url := fmt.Sprintf("%s/v1/openhorizon/metadata/%s"+cliutils.AddSlash(path), vs.cfg.GetAgbotVaultURL(), org)
return vs.listSecret(user, token, org, path, url)
}

// Get the secret at a specified path within the vault
func (vs *AgbotVaultSecrets) listSecret(user, token, org, name, url string) error {

Expand Down Expand Up @@ -134,6 +148,44 @@ func (vs *AgbotVaultSecrets) ListOrgUserSecrets(user, token, org, path string) (
return secretList, nil
}

// List all org-level node secrets at a specified path in vault.
func (vs *AgbotVaultSecrets) ListOrgNodeSecrets(user, token, org, node, path string) ([]string, error) {

glog.V(3).Infof(vaultPluginLogString(fmt.Sprintf("listing secrets for node %v in %v", node, org)))

url := fmt.Sprintf("%s/v1/openhorizon/metadata/%s"+cliutils.AddSlash(path), vs.cfg.GetAgbotVaultURL(), org)
secrets, err := vs.listSecrets(user, token, org, url, path)
if err != nil {
return nil, err
}

// trim the node/<node> prefix from the names
secretList := make([]string, 0)
for _, secret := range secrets {
secretList = append(secretList, strings.TrimPrefix(secret, path+"/"))
}
return secretList, nil
}

// List all user-level node secrets at a specified path in vault.
func (vs *AgbotVaultSecrets) ListUserNodeSecrets(user, token, org, node, path string) ([]string, error) {

glog.V(3).Infof(vaultPluginLogString(fmt.Sprintf("listing secrets for node %v in %v as user %v", node, org, user)))

url := fmt.Sprintf("%s/v1/openhorizon/metadata/%s"+cliutils.AddSlash(path), vs.cfg.GetAgbotVaultURL(), org)
secrets, err := vs.listSecrets(user, token, org, url, path)
if err != nil {
return nil, err
}

// trim the user/<user>/node/<node> prefix from the names
secretList := make([]string, 0)
for _, secret := range secrets {
secretList = append(secretList, strings.TrimPrefix(secret, path+"/"))
}
return secretList, nil
}

// the input queue is a list of secret names and directories. this function gathers the secret names provided
// and recurses on the directories to output a list of secret names with the input path as the directory
// of the names in the input queue ("" if top-level vault directory)
Expand Down Expand Up @@ -220,7 +272,7 @@ func (vs *AgbotVaultSecrets) listSecrets(user, token, org, url, path string) ([]
secrets := make([]string, 0)
if path == "" {
for _, secret := range respMsg.Data.Keys {
if secret != "user/" {
if secret != "user/" && secret != "node/" {
secrets = append(secrets, secret)
}
}
Expand Down Expand Up @@ -254,6 +306,22 @@ func (vs *AgbotVaultSecrets) CreateOrgSecret(user, token, org, path string, data
return vs.createSecret(user, token, org, path, url, data)
}

// Available only to org admins
func (vs *AgbotVaultSecrets) CreateOrgNodeSecret(user, token, org, path string, data secrets.SecretDetails) error {
glog.V(3).Infof(vaultPluginLogString(fmt.Sprintf("creating secret %s in org %s", path, org)))

url := fmt.Sprintf("%s/v1/openhorizon/data/%s"+cliutils.AddSlash(path), vs.cfg.GetAgbotVaultURL(), org)
return vs.createSecret(user, token, org, path, url, data)
}

// Available only to all users in an org
func (vs *AgbotVaultSecrets) CreateUserNodeSecret(user, token, org, path string, data secrets.SecretDetails) error {
glog.V(3).Infof(vaultPluginLogString(fmt.Sprintf("creating secret %s in org %s", path, org)))

url := fmt.Sprintf("%s/v1/openhorizon/data/%s"+cliutils.AddSlash(path), vs.cfg.GetAgbotVaultURL(), org)
return vs.createSecret(user, token, org, path, url, data)
}

// This utility will be used to create secrets.
func (vs *AgbotVaultSecrets) createSecret(user, token, org, vaultSecretName, url string, data secrets.SecretDetails) error {

Expand Down Expand Up @@ -326,6 +394,22 @@ func (vs *AgbotVaultSecrets) DeleteOrgSecret(user, token, org, path string) erro
return vs.deleteSecret(user, token, org, path, url)
}

// Available to only org admin users
func (vs *AgbotVaultSecrets) DeleteOrgNodeSecret(user, token, org, path string) error {
glog.V(3).Infof(vaultPluginLogString(fmt.Sprintf("delete secret %s in org %s", path, org)))

url := fmt.Sprintf("%s/v1/openhorizon/metadata/%s"+cliutils.AddSlash(path), vs.cfg.GetAgbotVaultURL(), org)
return vs.deleteSecret(user, token, org, path, url)
}

// Available to all users in the org
func (vs *AgbotVaultSecrets) DeleteUserNodeSecret(user, token, org, path string) error {
glog.V(3).Infof(vaultPluginLogString(fmt.Sprintf("delete secret %s in org %s", path, org)))

url := fmt.Sprintf("%s/v1/openhorizon/metadata/%s"+cliutils.AddSlash(path), vs.cfg.GetAgbotVaultURL(), org)
return vs.deleteSecret(user, token, org, path, url)
}

// This utility will be used to delete secrets.
func (vs *AgbotVaultSecrets) deleteSecret(user, token, org, name, url string) error {

Expand Down Expand Up @@ -384,7 +468,7 @@ func (vs *AgbotVaultSecrets) deleteSecret(user, token, org, name, url string) er
return nil
}

func (vs *AgbotVaultSecrets) GetSecretDetails(user, token, org, secretUser, secretName string) (res secrets.SecretDetails, err error) {
func (vs *AgbotVaultSecrets) GetSecretDetails(user, token, org, secretUser, secretNode, secretName string) (res secrets.SecretDetails, err error) {

glog.V(3).Infof(vaultPluginLogString(fmt.Sprintf("extract secret details for %s in org %s as user %s", secretName, org, secretUser)))

Expand All @@ -408,8 +492,12 @@ func (vs *AgbotVaultSecrets) GetSecretDetails(user, token, org, secretUser, secr
// build the vault URL
url := fmt.Sprintf("%s/v1/openhorizon/data/%s/", vs.cfg.GetAgbotVaultURL(), org)
var fullSecretName string
if secretUser != "" {
if secretUser != "" && secretNode != "" {
fullSecretName = fmt.Sprintf("user/%s/node/%s/%s", secretUser, secretNode, secretName)
} else if secretUser != "" {
fullSecretName = fmt.Sprintf("user/%s/%s", secretUser, secretName)
} else if secretNode != "" {
fullSecretName = fmt.Sprintf("node/%s/%s", secretNode, secretName)
} else {
fullSecretName = secretName
}
Expand Down Expand Up @@ -495,7 +583,7 @@ func (vs *AgbotVaultSecrets) GetSecretDetails(user, token, org, secretUser, secr
}

// Retrieve the metadata for a secret.
func (vs *AgbotVaultSecrets) GetSecretMetadata(secretOrg, secretUser, secretName string) (res secrets.SecretMetadata, err error) {
func (vs *AgbotVaultSecrets) GetSecretMetadata(secretOrg, secretUser, secretNode, secretName string) (res secrets.SecretMetadata, err error) {

glog.V(3).Infof(vaultPluginLogString(fmt.Sprintf("extract secret metadata for %s in org %s as user %s", secretName, secretOrg, secretUser)))

Expand All @@ -515,8 +603,12 @@ func (vs *AgbotVaultSecrets) GetSecretMetadata(secretOrg, secretUser, secretName

// build the vault URL
url := fmt.Sprintf("%s/v1/openhorizon/metadata/%s/", vs.cfg.GetAgbotVaultURL(), secretOrg)
if secretUser != "" {
if secretUser != "" && secretNode != "" {
url += fmt.Sprintf("user/%s/node/%s/%s", secretUser, secretNode, secretName)
} else if secretUser != "" {
url += fmt.Sprintf("user/%s/%s", secretUser, secretName)
} else if secretNode != "" {
url += fmt.Sprintf("node/%s/%s", secretNode, secretName)
} else {
url += secretName
}
Expand Down
Loading

0 comments on commit 8f02613

Please sign in to comment.