github.com/bigcommerce/nomad@v0.9.3-bc/nomad/acl.go (about)

     1  package nomad
     2  
     3  import (
     4  	"time"
     5  
     6  	metrics "github.com/armon/go-metrics"
     7  	lru "github.com/hashicorp/golang-lru"
     8  	"github.com/hashicorp/nomad/acl"
     9  	"github.com/hashicorp/nomad/nomad/state"
    10  	"github.com/hashicorp/nomad/nomad/structs"
    11  )
    12  
    13  // ResolveToken is used to translate an ACL Token Secret ID into
    14  // an ACL object, nil if ACLs are disabled, or an error.
    15  func (s *Server) ResolveToken(secretID string) (*acl.ACL, error) {
    16  	// Fast-path if ACLs are disabled
    17  	if !s.config.ACLEnabled {
    18  		return nil, nil
    19  	}
    20  	defer metrics.MeasureSince([]string{"nomad", "acl", "resolveToken"}, time.Now())
    21  
    22  	// Check if the secret ID is the leader secret ID, in which case treat it as
    23  	// a management token.
    24  	if leaderAcl := s.getLeaderAcl(); leaderAcl != "" && secretID == leaderAcl {
    25  		return acl.ManagementACL, nil
    26  	}
    27  
    28  	// Snapshot the state
    29  	snap, err := s.fsm.State().Snapshot()
    30  	if err != nil {
    31  		return nil, err
    32  	}
    33  
    34  	// Resolve the ACL
    35  	return resolveTokenFromSnapshotCache(snap, s.aclCache, secretID)
    36  }
    37  
    38  // resolveTokenFromSnapshotCache is used to resolve an ACL object from a snapshot of state,
    39  // using a cache to avoid parsing and ACL construction when possible. It is split from resolveToken
    40  // to simplify testing.
    41  func resolveTokenFromSnapshotCache(snap *state.StateSnapshot, cache *lru.TwoQueueCache, secretID string) (*acl.ACL, error) {
    42  	// Lookup the ACL Token
    43  	var token *structs.ACLToken
    44  	var err error
    45  
    46  	// Handle anonymous requests
    47  	if secretID == "" {
    48  		token = structs.AnonymousACLToken
    49  	} else {
    50  		token, err = snap.ACLTokenBySecretID(nil, secretID)
    51  		if err != nil {
    52  			return nil, err
    53  		}
    54  		if token == nil {
    55  			return nil, structs.ErrTokenNotFound
    56  		}
    57  	}
    58  
    59  	// Check if this is a management token
    60  	if token.Type == structs.ACLManagementToken {
    61  		return acl.ManagementACL, nil
    62  	}
    63  
    64  	// Get all associated policies
    65  	policies := make([]*structs.ACLPolicy, 0, len(token.Policies))
    66  	for _, policyName := range token.Policies {
    67  		policy, err := snap.ACLPolicyByName(nil, policyName)
    68  		if err != nil {
    69  			return nil, err
    70  		}
    71  		if policy == nil {
    72  			// Ignore policies that don't exist, since they don't grant any more privilege
    73  			continue
    74  		}
    75  
    76  		// Save the policy and update the cache key
    77  		policies = append(policies, policy)
    78  	}
    79  
    80  	// Compile and cache the ACL object
    81  	aclObj, err := structs.CompileACLObject(cache, policies)
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  	return aclObj, nil
    86  }