open-nomad/nomad/acl.go
Drew Bailey b09abef332
Audit config, seams for enterprise audit features
allow oss to parse sink duration

clean up audit sink parsing

ent eventer config reload

fix typo

SetEnabled to eventer interface

client acl test

rm dead code

fix failing test
2020-03-23 13:47:42 -04:00

121 lines
3.2 KiB
Go

package nomad
import (
"time"
metrics "github.com/armon/go-metrics"
lru "github.com/hashicorp/golang-lru"
"github.com/hashicorp/nomad/acl"
"github.com/hashicorp/nomad/nomad/state"
"github.com/hashicorp/nomad/nomad/structs"
)
// ResolveToken is used to translate an ACL Token Secret ID into
// an ACL object, nil if ACLs are disabled, or an error.
func (s *Server) ResolveToken(secretID string) (*acl.ACL, error) {
// Fast-path if ACLs are disabled
if !s.config.ACLEnabled {
return nil, nil
}
defer metrics.MeasureSince([]string{"nomad", "acl", "resolveToken"}, time.Now())
// Check if the secret ID is the leader secret ID, in which case treat it as
// a management token.
if leaderAcl := s.getLeaderAcl(); leaderAcl != "" && secretID == leaderAcl {
return acl.ManagementACL, nil
}
// Snapshot the state
snap, err := s.fsm.State().Snapshot()
if err != nil {
return nil, err
}
// Resolve the ACL
return resolveTokenFromSnapshotCache(snap, s.aclCache, secretID)
}
// resolveTokenFromSnapshotCache is used to resolve an ACL object from a snapshot of state,
// using a cache to avoid parsing and ACL construction when possible. It is split from resolveToken
// to simplify testing.
func resolveTokenFromSnapshotCache(snap *state.StateSnapshot, cache *lru.TwoQueueCache, secretID string) (*acl.ACL, error) {
// Lookup the ACL Token
var token *structs.ACLToken
var err error
// Handle anonymous requests
if secretID == "" {
token = structs.AnonymousACLToken
} else {
token, err = snap.ACLTokenBySecretID(nil, secretID)
if err != nil {
return nil, err
}
if token == nil {
return nil, structs.ErrTokenNotFound
}
}
// Check if this is a management token
if token.Type == structs.ACLManagementToken {
return acl.ManagementACL, nil
}
// Get all associated policies
policies := make([]*structs.ACLPolicy, 0, len(token.Policies))
for _, policyName := range token.Policies {
policy, err := snap.ACLPolicyByName(nil, policyName)
if err != nil {
return nil, err
}
if policy == nil {
// Ignore policies that don't exist, since they don't grant any more privilege
continue
}
// Save the policy and update the cache key
policies = append(policies, policy)
}
// Compile and cache the ACL object
aclObj, err := structs.CompileACLObject(cache, policies)
if err != nil {
return nil, err
}
return aclObj, nil
}
// ResolveSecretToken is used to translate an ACL Token Secret ID into
// an ACLToken object, nil if ACLs are disabled, or an error.
func (s *Server) ResolveSecretToken(secretID string) (*structs.ACLToken, error) {
// TODO(Drew) Look into using ACLObject cache or create a separate cache
// Fast-path if ACLs are disabled
if !s.config.ACLEnabled {
return nil, nil
}
defer metrics.MeasureSince([]string{"nomad", "acl", "resolveSecretToken"}, time.Now())
snap, err := s.fsm.State().Snapshot()
if err != nil {
return nil, err
}
// Lookup the ACL Token
var token *structs.ACLToken
// Handle anonymous requests
if secretID == "" {
token = structs.AnonymousACLToken
} else {
token, err = snap.ACLTokenBySecretID(nil, secretID)
if err != nil {
return nil, err
}
if token == nil {
return nil, structs.ErrTokenNotFound
}
}
return token, nil
}