go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers-sdk/v1/vault/multivault/multivault.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package multivault 5 6 import ( 7 "context" 8 "errors" 9 10 "go.mondoo.com/cnquery/providers-sdk/v1/vault" 11 "go.mondoo.com/ranger-rpc/codes" 12 "go.mondoo.com/ranger-rpc/status" 13 ) 14 15 // New creates a new vault that can query multiple vaults. It is a 16 // read-only vault that allows the user to have a unified view for secrets 17 // located in e.g. and inmemory vault and in e.g. a keyring vault. The order 18 // matters. When a secret is requested, this implementation iterates over 19 // each vault and returns the first secret with the requested id 20 func New(vaults ...vault.Vault) *multiVault { 21 return &multiVault{ 22 vaults: vaults, 23 } 24 } 25 26 type multiVault struct { 27 vaults []vault.Vault 28 } 29 30 func (v *multiVault) About(context.Context, *vault.Empty) (*vault.VaultInfo, error) { 31 return &vault.VaultInfo{Name: "Multi Vault"}, nil 32 } 33 34 func (m *multiVault) Set(ctx context.Context, secret *vault.Secret) (*vault.SecretID, error) { 35 return nil, errors.New("this vault is read only") 36 } 37 38 func (m *multiVault) Get(ctx context.Context, id *vault.SecretID) (*vault.Secret, error) { 39 if id == nil { 40 return nil, errors.New("secret id is empty") 41 } 42 43 // iterate over each vault and return the first finding 44 for i := range m.vaults { 45 v := m.vaults[i] 46 secret, err := v.Get(ctx, id) 47 se, _ := status.FromError(err) 48 // move to next vault if we could not find the secret 49 if se != nil && se.Code() == codes.NotFound { 50 continue 51 } else if se != nil { 52 return nil, err 53 } 54 return secret, nil 55 } 56 57 return nil, vault.NotFoundError 58 }