github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/agent/secrets/secrets.go (about)

     1  package secrets
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  
     7  	"github.com/docker/swarmkit/agent/exec"
     8  	"github.com/docker/swarmkit/api"
     9  	"github.com/docker/swarmkit/identity"
    10  )
    11  
    12  // secrets is a map that keeps all the currently available secrets to the agent
    13  // mapped by secret ID.
    14  type secrets struct {
    15  	mu sync.RWMutex
    16  	m  map[string]*api.Secret
    17  }
    18  
    19  // NewManager returns a place to store secrets.
    20  func NewManager() exec.SecretsManager {
    21  	return &secrets{
    22  		m: make(map[string]*api.Secret),
    23  	}
    24  }
    25  
    26  // Get returns a secret by ID.  If the secret doesn't exist, returns nil.
    27  func (s *secrets) Get(secretID string) (*api.Secret, error) {
    28  	s.mu.RLock()
    29  	defer s.mu.RUnlock()
    30  	if s, ok := s.m[secretID]; ok {
    31  		return s, nil
    32  	}
    33  	return nil, fmt.Errorf("secret %s not found", secretID)
    34  }
    35  
    36  // Add adds one or more secrets to the secret map.
    37  func (s *secrets) Add(secrets ...api.Secret) {
    38  	s.mu.Lock()
    39  	defer s.mu.Unlock()
    40  	for _, secret := range secrets {
    41  		s.m[secret.ID] = secret.Copy()
    42  	}
    43  }
    44  
    45  // Remove removes one or more secrets by ID from the secret map.  Succeeds
    46  // whether or not the given IDs are in the map.
    47  func (s *secrets) Remove(secrets []string) {
    48  	s.mu.Lock()
    49  	defer s.mu.Unlock()
    50  	for _, secret := range secrets {
    51  		delete(s.m, secret)
    52  	}
    53  }
    54  
    55  // Reset removes all the secrets.
    56  func (s *secrets) Reset() {
    57  	s.mu.Lock()
    58  	defer s.mu.Unlock()
    59  	s.m = make(map[string]*api.Secret)
    60  }
    61  
    62  // taskRestrictedSecretsProvider restricts the ids to the task.
    63  type taskRestrictedSecretsProvider struct {
    64  	secrets   exec.SecretGetter
    65  	secretIDs map[string]struct{} // allow list of secret ids
    66  	taskID    string              // ID of the task the provider restricts for
    67  }
    68  
    69  func (sp *taskRestrictedSecretsProvider) Get(secretID string) (*api.Secret, error) {
    70  	if _, ok := sp.secretIDs[secretID]; !ok {
    71  		return nil, fmt.Errorf("task not authorized to access secret %s", secretID)
    72  	}
    73  
    74  	// First check if the secret is available with the task specific ID, which is the concatenation
    75  	// of the original secret ID and the task ID with a dot in between.
    76  	// That is the case when a secret driver has returned DoNotReuse == true for a secret value.
    77  	taskSpecificID := identity.CombineTwoIDs(secretID, sp.taskID)
    78  	secret, err := sp.secrets.Get(taskSpecificID)
    79  	if err != nil {
    80  		// Otherwise, which is the default case, the secret is retrieved by its original ID.
    81  		return sp.secrets.Get(secretID)
    82  	}
    83  	// For all intents and purposes, the rest of the flow should deal with the original secret ID.
    84  	secret.ID = secretID
    85  	return secret, err
    86  }
    87  
    88  // Restrict provides a getter that only allows access to the secrets
    89  // referenced by the task.
    90  func Restrict(secrets exec.SecretGetter, t *api.Task) exec.SecretGetter {
    91  	sids := map[string]struct{}{}
    92  
    93  	container := t.Spec.GetContainer()
    94  	if container != nil {
    95  		for _, ref := range container.Secrets {
    96  			sids[ref.SecretID] = struct{}{}
    97  		}
    98  	}
    99  
   100  	return &taskRestrictedSecretsProvider{secrets: secrets, secretIDs: sids, taskID: t.ID}
   101  }