1package consul
2
3import (
4	"context"
5	"encoding/json"
6	"errors"
7	"fmt"
8	"io/ioutil"
9	"os"
10	"path/filepath"
11	"regexp"
12	"time"
13
14	"github.com/armon/go-metrics"
15	"github.com/armon/go-metrics/prometheus"
16	"github.com/hashicorp/go-bexpr"
17	"github.com/hashicorp/go-hclog"
18	memdb "github.com/hashicorp/go-memdb"
19	uuid "github.com/hashicorp/go-uuid"
20
21	"github.com/hashicorp/consul/acl"
22	"github.com/hashicorp/consul/agent/consul/authmethod"
23	"github.com/hashicorp/consul/agent/consul/state"
24	"github.com/hashicorp/consul/agent/structs"
25	"github.com/hashicorp/consul/lib"
26	"github.com/hashicorp/consul/lib/template"
27)
28
29const (
30	// aclBootstrapReset is the file name to create in the data dir. It's only contents
31	// should be the reset index
32	aclBootstrapReset = "acl-bootstrap-reset"
33)
34
35var ACLEndpointSummaries = []prometheus.SummaryDefinition{
36	{
37		Name: []string{"acl", "token", "clone"},
38		Help: "",
39	},
40	{
41		Name: []string{"acl", "token", "upsert"},
42		Help: "",
43	},
44	{
45		Name: []string{"acl", "token", "delete"},
46		Help: "",
47	},
48	{
49		Name: []string{"acl", "policy", "upsert"},
50		Help: "",
51	},
52	{
53		Name: []string{"acl", "policy", "delete"},
54		Help: "",
55	},
56	{
57		Name: []string{"acl", "policy", "delete"},
58		Help: "",
59	},
60	{
61		Name: []string{"acl", "role", "upsert"},
62		Help: "",
63	},
64	{
65		Name: []string{"acl", "role", "delete"},
66		Help: "",
67	},
68	{
69		Name: []string{"acl", "bindingrule", "upsert"},
70		Help: "",
71	},
72	{
73		Name: []string{"acl", "bindingrule", "delete"},
74		Help: "",
75	},
76	{
77		Name: []string{"acl", "authmethod", "upsert"},
78		Help: "",
79	},
80	{
81		Name: []string{"acl", "authmethod", "delete"},
82		Help: "",
83	},
84	{
85		Name: []string{"acl", "login"},
86		Help: "",
87	},
88	{
89		Name: []string{"acl", "login"},
90		Help: "",
91	},
92	{
93		Name: []string{"acl", "logout"},
94		Help: "",
95	},
96	{
97		Name: []string{"acl", "logout"},
98		Help: "",
99	},
100}
101
102// Regex for matching
103var (
104	validPolicyName              = regexp.MustCompile(`^[A-Za-z0-9\-_]{1,128}$`)
105	validServiceIdentityName     = regexp.MustCompile(`^[a-z0-9]([a-z0-9\-_]*[a-z0-9])?$`)
106	serviceIdentityNameMaxLength = 256
107	validNodeIdentityName        = regexp.MustCompile(`^[a-z0-9]([a-z0-9\-_]*[a-z0-9])?$`)
108	nodeIdentityNameMaxLength    = 256
109	validRoleName                = regexp.MustCompile(`^[A-Za-z0-9\-_]{1,256}$`)
110	validAuthMethod              = regexp.MustCompile(`^[A-Za-z0-9\-_]{1,128}$`)
111)
112
113// ACL endpoint is used to manipulate ACLs
114type ACL struct {
115	srv    *Server
116	logger hclog.Logger
117}
118
119// fileBootstrapResetIndex retrieves the reset index specified by the administrator from
120// the file on disk.
121//
122// Q: What is the bootstrap reset index?
123// A: If you happen to lose acess to all tokens capable of ACL management you need a way
124//    to get back into your system. This allows an admin to write the current
125//    bootstrap "index" into a special file on disk to override the mechanism preventing
126//    a second token bootstrap. The index will be retrieved by a API call to /v1/acl/bootstrap
127//    When already bootstrapped this API will return the reset index necessary within
128//    the error response. Once set in the file, the bootstrap API can be used again to
129//    get a new token.
130//
131// Q: Why is the reset index not in the config?
132// A: We want to be able to remove the reset index once we have used it. This prevents
133//    accidentally allowing bootstrapping yet again after a snapshot restore.
134//
135func (a *ACL) fileBootstrapResetIndex() uint64 {
136	// Determine the file path to check
137	path := filepath.Join(a.srv.config.DataDir, aclBootstrapReset)
138
139	// Read the file
140	raw, err := ioutil.ReadFile(path)
141	if err != nil {
142		if !os.IsNotExist(err) {
143			a.logger.Error("bootstrap: failed to read path",
144				"path", path,
145				"error", err,
146			)
147		}
148		return 0
149	}
150
151	// Attempt to parse the file
152	var resetIdx uint64
153	if _, err := fmt.Sscanf(string(raw), "%d", &resetIdx); err != nil {
154		a.logger.Error("failed to parse bootstrap reset index path", "path", path, "error", err)
155		return 0
156	}
157
158	// Return the reset index
159	a.logger.Debug("parsed bootstrap reset index path", "path", path, "reset_index", resetIdx)
160	return resetIdx
161}
162
163func (a *ACL) removeBootstrapResetFile() {
164	if err := os.Remove(filepath.Join(a.srv.config.DataDir, aclBootstrapReset)); err != nil {
165		a.logger.Warn("failed to remove bootstrap file", "error", err)
166	}
167}
168
169func (a *ACL) aclPreCheck() error {
170	if !a.srv.config.ACLsEnabled {
171		return acl.ErrDisabled
172	}
173
174	if a.srv.UseLegacyACLs() {
175		return fmt.Errorf("The ACL system is currently in legacy mode.")
176	}
177
178	return nil
179}
180
181// Bootstrap is used to perform a one-time ACL bootstrap operation on
182// a cluster to get the first management token.
183func (a *ACL) BootstrapTokens(args *structs.DCSpecificRequest, reply *structs.ACLToken) error {
184	if err := a.aclPreCheck(); err != nil {
185		return err
186	}
187	if done, err := a.srv.ForwardRPC("ACL.BootstrapTokens", args, reply); done {
188		return err
189	}
190
191	if err := a.srv.aclBootstrapAllowed(); err != nil {
192		return err
193	}
194
195	// Verify we are allowed to serve this request
196	if !a.srv.InACLDatacenter() {
197		return acl.ErrDisabled
198	}
199
200	// By doing some pre-checks we can head off later bootstrap attempts
201	// without having to run them through Raft, which should curb abuse.
202	state := a.srv.fsm.State()
203	allowed, resetIdx, err := state.CanBootstrapACLToken()
204	if err != nil {
205		return err
206	}
207	var specifiedIndex uint64 = 0
208	if !allowed {
209		// Check if there is a reset index specified
210		specifiedIndex = a.fileBootstrapResetIndex()
211		if specifiedIndex == 0 {
212			return fmt.Errorf("ACL bootstrap no longer allowed (reset index: %d)", resetIdx)
213		} else if specifiedIndex != resetIdx {
214			return fmt.Errorf("Invalid bootstrap reset index (specified %d, reset index: %d)", specifiedIndex, resetIdx)
215		}
216	}
217
218	// remove the bootstrap override file now that we have the index from it and it was valid.
219	// whether bootstrapping works or not is irrelevant as we really don't want this file hanging around
220	// in case a snapshot restore is done. In that case we don't want to accidentally allow re-bootstrapping
221	// just because the file was unchanged.
222	a.removeBootstrapResetFile()
223
224	accessor, err := lib.GenerateUUID(a.srv.checkTokenUUID)
225	if err != nil {
226		return err
227	}
228	secret, err := lib.GenerateUUID(a.srv.checkTokenUUID)
229	if err != nil {
230		return err
231	}
232
233	req := structs.ACLTokenBootstrapRequest{
234		Token: structs.ACLToken{
235			AccessorID:  accessor,
236			SecretID:    secret,
237			Description: "Bootstrap Token (Global Management)",
238			Policies: []structs.ACLTokenPolicyLink{
239				{
240					ID: structs.ACLPolicyGlobalManagementID,
241				},
242			},
243			CreateTime: time.Now(),
244			Local:      false,
245			// DEPRECATED (ACL-Legacy-Compat) - This is used so that the bootstrap token is still visible via the v1 acl APIs
246			Type:           structs.ACLTokenTypeManagement,
247			EnterpriseMeta: *structs.DefaultEnterpriseMeta(),
248		},
249		ResetIndex: specifiedIndex,
250	}
251
252	req.Token.SetHash(true)
253
254	_, err = a.srv.raftApply(structs.ACLBootstrapRequestType, &req)
255	if err != nil {
256		return err
257	}
258
259	if _, token, err := state.ACLTokenGetByAccessor(nil, accessor, structs.DefaultEnterpriseMeta()); err == nil {
260		*reply = *token
261	}
262
263	a.logger.Info("ACL bootstrap completed")
264	return nil
265}
266
267func (a *ACL) TokenRead(args *structs.ACLTokenGetRequest, reply *structs.ACLTokenResponse) error {
268	if err := a.aclPreCheck(); err != nil {
269		return err
270	}
271
272	if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, false); err != nil {
273		return err
274	}
275
276	// clients will not know whether the server has local token store. In the case
277	// where it doesn't we will transparently forward requests.
278	if !a.srv.LocalTokensEnabled() {
279		args.Datacenter = a.srv.config.ACLDatacenter
280	}
281
282	if done, err := a.srv.ForwardRPC("ACL.TokenRead", args, reply); done {
283		return err
284	}
285
286	var authz acl.Authorizer
287
288	if args.TokenIDType == structs.ACLTokenAccessor {
289		var err error
290		var authzContext acl.AuthorizerContext
291		// Only ACLRead privileges are required to list tokens
292		// However if you do not have ACLWrite as well the token
293		// secrets will be redacted
294		if authz, err = a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
295			return err
296		} else if authz == nil || authz.ACLRead(&authzContext) != acl.Allow {
297			return acl.ErrPermissionDenied
298		}
299	}
300
301	return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
302		func(ws memdb.WatchSet, state *state.Store) error {
303			var index uint64
304			var token *structs.ACLToken
305			var err error
306
307			if args.TokenIDType == structs.ACLTokenAccessor {
308				index, token, err = state.ACLTokenGetByAccessor(ws, args.TokenID, &args.EnterpriseMeta)
309				if token != nil {
310					a.srv.filterACLWithAuthorizer(authz, &token)
311
312					// token secret was redacted
313					if token.SecretID == redactedToken {
314						reply.Redacted = true
315					}
316				}
317			} else {
318				index, token, err = state.ACLTokenGetBySecret(ws, args.TokenID, nil)
319				// no extra validation is needed here. If you have the secret ID you can read it.
320			}
321
322			if token != nil && token.IsExpired(time.Now()) {
323				token = nil
324			}
325
326			if err != nil {
327				return err
328			}
329
330			reply.Index, reply.Token = index, token
331			reply.SourceDatacenter = args.Datacenter
332			return nil
333		})
334}
335
336func (a *ACL) TokenClone(args *structs.ACLTokenSetRequest, reply *structs.ACLToken) error {
337	if err := a.aclPreCheck(); err != nil {
338		return err
339	}
340
341	if err := a.srv.validateEnterpriseRequest(&args.ACLToken.EnterpriseMeta, true); err != nil {
342		return err
343	}
344
345	// clients will not know whether the server has local token store. In the case
346	// where it doesn't we will transparently forward requests.
347	if !a.srv.LocalTokensEnabled() {
348		args.Datacenter = a.srv.config.ACLDatacenter
349	}
350
351	if done, err := a.srv.ForwardRPC("ACL.TokenClone", args, reply); done {
352		return err
353	}
354
355	defer metrics.MeasureSince([]string{"acl", "token", "clone"}, time.Now())
356
357	var authzContext acl.AuthorizerContext
358	authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.ACLToken.EnterpriseMeta, &authzContext)
359	if err != nil {
360		return err
361	} else if authz == nil || authz.ACLWrite(&authzContext) != acl.Allow {
362		return acl.ErrPermissionDenied
363	}
364
365	_, token, err := a.srv.fsm.State().ACLTokenGetByAccessor(nil, args.ACLToken.AccessorID, &args.ACLToken.EnterpriseMeta)
366	if err != nil {
367		return err
368	} else if token == nil || token.IsExpired(time.Now()) {
369		return acl.ErrNotFound
370	} else if !a.srv.InACLDatacenter() && !token.Local {
371		// global token writes must be forwarded to the primary DC
372		args.Datacenter = a.srv.config.ACLDatacenter
373		return a.srv.forwardDC("ACL.TokenClone", a.srv.config.ACLDatacenter, args, reply)
374	}
375
376	if token.AuthMethod != "" {
377		return fmt.Errorf("Cannot clone a token created from an auth method")
378	}
379
380	if token.Rules != "" {
381		return fmt.Errorf("Cannot clone a legacy ACL with this endpoint")
382	}
383
384	cloneReq := structs.ACLTokenSetRequest{
385		Datacenter: args.Datacenter,
386		ACLToken: structs.ACLToken{
387			Policies:          token.Policies,
388			Roles:             token.Roles,
389			ServiceIdentities: token.ServiceIdentities,
390			NodeIdentities:    token.NodeIdentities,
391			Local:             token.Local,
392			Description:       token.Description,
393			ExpirationTime:    token.ExpirationTime,
394			EnterpriseMeta:    args.ACLToken.EnterpriseMeta,
395		},
396		WriteRequest: args.WriteRequest,
397	}
398
399	if args.ACLToken.Description != "" {
400		cloneReq.ACLToken.Description = args.ACLToken.Description
401	}
402
403	return a.tokenSetInternal(&cloneReq, reply, false)
404}
405
406func (a *ACL) TokenSet(args *structs.ACLTokenSetRequest, reply *structs.ACLToken) error {
407	if err := a.aclPreCheck(); err != nil {
408		return err
409	}
410
411	if err := a.srv.validateEnterpriseRequest(&args.ACLToken.EnterpriseMeta, true); err != nil {
412		return err
413	}
414
415	// Global token creation/modification always goes to the ACL DC
416	if !args.ACLToken.Local {
417		args.Datacenter = a.srv.config.ACLDatacenter
418	} else if !a.srv.LocalTokensEnabled() {
419		return fmt.Errorf("Local tokens are disabled")
420	}
421
422	if done, err := a.srv.ForwardRPC("ACL.TokenSet", args, reply); done {
423		return err
424	}
425
426	defer metrics.MeasureSince([]string{"acl", "token", "upsert"}, time.Now())
427
428	// Verify token is permitted to modify ACLs
429	var authzContext acl.AuthorizerContext
430	if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.ACLToken.EnterpriseMeta, &authzContext); err != nil {
431		return err
432	} else if authz == nil || authz.ACLWrite(&authzContext) != acl.Allow {
433		return acl.ErrPermissionDenied
434	}
435
436	return a.tokenSetInternal(args, reply, false)
437}
438
439func (a *ACL) tokenSetInternal(args *structs.ACLTokenSetRequest, reply *structs.ACLToken, fromLogin bool) error {
440	token := &args.ACLToken
441
442	if !a.srv.LocalTokensEnabled() {
443		// local token operations
444		return fmt.Errorf("Cannot upsert tokens within this datacenter")
445	} else if !a.srv.InACLDatacenter() && !token.Local {
446		return fmt.Errorf("Cannot upsert global tokens within this datacenter")
447	}
448
449	state := a.srv.fsm.State()
450
451	var accessorMatch *structs.ACLToken
452	var secretMatch *structs.ACLToken
453	var err error
454
455	if token.AccessorID != "" {
456		_, accessorMatch, err = state.ACLTokenGetByAccessor(nil, token.AccessorID, nil)
457		if err != nil {
458			return fmt.Errorf("Failed acl token lookup by accessor: %v", err)
459		}
460	}
461	if token.SecretID != "" {
462		_, secretMatch, err = state.ACLTokenGetBySecret(nil, token.SecretID, nil)
463		if err != nil {
464			return fmt.Errorf("Failed acl token lookup by secret: %v", err)
465		}
466	}
467
468	if token.AccessorID == "" || args.Create {
469		// Token Create
470
471		// Generate the AccessorID if not specified
472		if token.AccessorID == "" {
473			token.AccessorID, err = lib.GenerateUUID(a.srv.checkTokenUUID)
474			if err != nil {
475				return err
476			}
477		} else if _, err := uuid.ParseUUID(token.AccessorID); err != nil {
478			return fmt.Errorf("Invalid Token: AccessorID is not a valid UUID")
479		} else if accessorMatch != nil {
480			return fmt.Errorf("Invalid Token: AccessorID is already in use")
481		} else if _, match, err := state.ACLTokenGetBySecret(nil, token.AccessorID, nil); err != nil || match != nil {
482			if err != nil {
483				return fmt.Errorf("Failed to lookup the acl token: %v", err)
484			}
485			return fmt.Errorf("Invalid Token: AccessorID is already in use")
486		} else if structs.ACLIDReserved(token.AccessorID) {
487			return fmt.Errorf("Invalid Token: UUIDs with the prefix %q are reserved", structs.ACLReservedPrefix)
488		}
489
490		// Generate the SecretID if not specified
491		if token.SecretID == "" {
492			token.SecretID, err = lib.GenerateUUID(a.srv.checkTokenUUID)
493			if err != nil {
494				return err
495			}
496		} else if _, err := uuid.ParseUUID(token.SecretID); err != nil {
497			return fmt.Errorf("Invalid Token: SecretID is not a valid UUID")
498		} else if secretMatch != nil {
499			return fmt.Errorf("Invalid Token: SecretID is already in use")
500		} else if _, match, err := state.ACLTokenGetByAccessor(nil, token.SecretID, nil); err != nil || match != nil {
501			if err != nil {
502				return fmt.Errorf("Failed to lookup the acl token: %v", err)
503			}
504			return fmt.Errorf("Invalid Token: SecretID is already in use")
505		} else if structs.ACLIDReserved(token.SecretID) {
506			return fmt.Errorf("Invalid Token: UUIDs with the prefix %q are reserved", structs.ACLReservedPrefix)
507		}
508
509		token.CreateTime = time.Now()
510
511		if fromLogin {
512			if token.AuthMethod == "" {
513				return fmt.Errorf("AuthMethod field is required during Login")
514			}
515		} else {
516			if token.AuthMethod != "" {
517				return fmt.Errorf("AuthMethod field is disallowed outside of Login")
518			}
519		}
520
521		// Ensure an ExpirationTTL is valid if provided.
522		if token.ExpirationTTL != 0 {
523			if token.ExpirationTTL < 0 {
524				return fmt.Errorf("Token Expiration TTL '%s' should be > 0", token.ExpirationTTL)
525			}
526			if token.HasExpirationTime() {
527				return fmt.Errorf("Token Expiration TTL and Expiration Time cannot both be set")
528			}
529
530			token.ExpirationTime = timePointer(token.CreateTime.Add(token.ExpirationTTL))
531			token.ExpirationTTL = 0
532		}
533
534		if token.HasExpirationTime() {
535			if token.CreateTime.After(*token.ExpirationTime) {
536				return fmt.Errorf("ExpirationTime cannot be before CreateTime")
537			}
538
539			expiresIn := token.ExpirationTime.Sub(token.CreateTime)
540			if expiresIn > a.srv.config.ACLTokenMaxExpirationTTL {
541				return fmt.Errorf("ExpirationTime cannot be more than %s in the future (was %s)",
542					a.srv.config.ACLTokenMaxExpirationTTL, expiresIn)
543			} else if expiresIn < a.srv.config.ACLTokenMinExpirationTTL {
544				return fmt.Errorf("ExpirationTime cannot be less than %s in the future (was %s)",
545					a.srv.config.ACLTokenMinExpirationTTL, expiresIn)
546			}
547		}
548	} else {
549		// Token Update
550		if _, err := uuid.ParseUUID(token.AccessorID); err != nil {
551			return fmt.Errorf("AccessorID is not a valid UUID")
552		}
553
554		// DEPRECATED (ACL-Legacy-Compat) - maybe get rid of this in the future
555		//   and instead do a ParseUUID check. New tokens will not have
556		//   secrets generated by users but rather they will always be UUIDs.
557		//   However if users just continue the upgrade cycle they may still
558		//   have tokens using secrets that are not UUIDS
559		// The RootAuthorizer checks that the SecretID is not "allow", "deny"
560		// or "manage" as a precaution against something accidentally using
561		// one of these root policies by setting the secret to it.
562		if acl.RootAuthorizer(token.SecretID) != nil {
563			return acl.PermissionDeniedError{Cause: "Cannot modify root ACL"}
564		}
565
566		// Verify the token exists
567		if accessorMatch == nil || accessorMatch.IsExpired(time.Now()) {
568			return fmt.Errorf("Cannot find token %q", token.AccessorID)
569		}
570		if token.SecretID == "" {
571			token.SecretID = accessorMatch.SecretID
572		} else if accessorMatch.SecretID != token.SecretID {
573			return fmt.Errorf("Changing a tokens SecretID is not permitted")
574		}
575
576		// Cannot toggle the "Global" mode
577		if token.Local != accessorMatch.Local {
578			return fmt.Errorf("cannot toggle local mode of %s", token.AccessorID)
579		}
580
581		if token.AuthMethod == "" {
582			token.AuthMethod = accessorMatch.AuthMethod
583		} else if token.AuthMethod != accessorMatch.AuthMethod {
584			return fmt.Errorf("Cannot change AuthMethod of %s", token.AccessorID)
585		}
586
587		if token.ExpirationTTL != 0 {
588			return fmt.Errorf("Cannot change expiration time of %s", token.AccessorID)
589		}
590
591		if !token.HasExpirationTime() {
592			token.ExpirationTime = accessorMatch.ExpirationTime
593		} else if !accessorMatch.HasExpirationTime() {
594			return fmt.Errorf("Cannot change expiration time of %s", token.AccessorID)
595		} else if !token.ExpirationTime.Equal(*accessorMatch.ExpirationTime) {
596			return fmt.Errorf("Cannot change expiration time of %s", token.AccessorID)
597		}
598
599		token.CreateTime = accessorMatch.CreateTime
600	}
601
602	policyIDs := make(map[string]struct{})
603	var policies []structs.ACLTokenPolicyLink
604
605	// Validate all the policy names and convert them to policy IDs
606	for _, link := range token.Policies {
607		if link.ID == "" {
608			_, policy, err := state.ACLPolicyGetByName(nil, link.Name, &token.EnterpriseMeta)
609			if err != nil {
610				return fmt.Errorf("Error looking up policy for name %q: %v", link.Name, err)
611			}
612			if policy == nil {
613				return fmt.Errorf("No such ACL policy with name %q", link.Name)
614			}
615			link.ID = policy.ID
616		} else {
617			_, policy, err := state.ACLPolicyGetByID(nil, link.ID, &token.EnterpriseMeta)
618			if err != nil {
619				return fmt.Errorf("Error looking up policy for id %q: %v", link.ID, err)
620			}
621
622			if policy == nil {
623				return fmt.Errorf("No such ACL policy with ID %q", link.ID)
624			}
625		}
626
627		// Do not store the policy name within raft/memdb as the policy could be renamed in the future.
628		link.Name = ""
629
630		// dedup policy links by id
631		if _, ok := policyIDs[link.ID]; !ok {
632			policies = append(policies, link)
633			policyIDs[link.ID] = struct{}{}
634		}
635	}
636	token.Policies = policies
637
638	roleIDs := make(map[string]struct{})
639	var roles []structs.ACLTokenRoleLink
640
641	// Validate all the role names and convert them to role IDs.
642	for _, link := range token.Roles {
643		if link.ID == "" {
644			_, role, err := state.ACLRoleGetByName(nil, link.Name, &token.EnterpriseMeta)
645			if err != nil {
646				return fmt.Errorf("Error looking up role for name %q: %v", link.Name, err)
647			}
648			if role == nil {
649				return fmt.Errorf("No such ACL role with name %q", link.Name)
650			}
651			link.ID = role.ID
652		} else {
653			_, role, err := state.ACLRoleGetByID(nil, link.ID, &token.EnterpriseMeta)
654			if err != nil {
655				return fmt.Errorf("Error looking up role for id %q: %v", link.ID, err)
656			}
657
658			if role == nil {
659				return fmt.Errorf("No such ACL role with ID %q", link.ID)
660			}
661		}
662
663		// Do not store the role name within raft/memdb as the role could be renamed in the future.
664		link.Name = ""
665
666		// dedup role links by id
667		if _, ok := roleIDs[link.ID]; !ok {
668			roles = append(roles, link)
669			roleIDs[link.ID] = struct{}{}
670		}
671	}
672	token.Roles = roles
673
674	for _, svcid := range token.ServiceIdentities {
675		if svcid.ServiceName == "" {
676			return fmt.Errorf("Service identity is missing the service name field on this token")
677		}
678		if token.Local && len(svcid.Datacenters) > 0 {
679			return fmt.Errorf("Service identity %q cannot specify a list of datacenters on a local token", svcid.ServiceName)
680		}
681		if !isValidServiceIdentityName(svcid.ServiceName) {
682			return fmt.Errorf("Service identity %q has an invalid name. Only alphanumeric characters, '-' and '_' are allowed", svcid.ServiceName)
683		}
684	}
685	token.ServiceIdentities = dedupeServiceIdentities(token.ServiceIdentities)
686
687	for _, nodeid := range token.NodeIdentities {
688		if nodeid.NodeName == "" {
689			return fmt.Errorf("Node identity is missing the node name field on this token")
690		}
691		if nodeid.Datacenter == "" {
692			return fmt.Errorf("Node identity is missing the datacenter field on this token")
693		}
694		if !isValidNodeIdentityName(nodeid.NodeName) {
695			return fmt.Errorf("Node identity has an invalid name. Only alphanumeric characters, '-' and '_' are allowed")
696		}
697	}
698	token.NodeIdentities = dedupeNodeIdentities(token.NodeIdentities)
699
700	if token.Rules != "" {
701		return fmt.Errorf("Rules cannot be specified for this token")
702	}
703
704	if token.Type != "" {
705		return fmt.Errorf("Type cannot be specified for this token")
706	}
707
708	token.SetHash(true)
709
710	// validate the enterprise meta
711	err = state.ACLTokenUpsertValidateEnterprise(token, accessorMatch)
712	if err != nil {
713		return err
714	}
715
716	req := &structs.ACLTokenBatchSetRequest{
717		Tokens: structs.ACLTokens{token},
718		CAS:    false,
719	}
720
721	if fromLogin {
722		// Logins may attempt to link to roles that do not exist. These
723		// may be persisted, but don't allow tokens to be created that
724		// have no privileges (i.e. role links that point nowhere).
725		req.AllowMissingLinks = true
726		req.ProhibitUnprivileged = true
727	}
728
729	_, err = a.srv.raftApply(structs.ACLTokenSetRequestType, req)
730	if err != nil {
731		return fmt.Errorf("Failed to apply token write request: %v", err)
732	}
733
734	// Purge the identity from the cache to prevent using the previous definition of the identity
735	a.srv.acls.cache.RemoveIdentity(tokenSecretCacheID(token.SecretID))
736
737	// Don't check expiration times here as it doesn't really matter.
738	if _, updatedToken, err := a.srv.fsm.State().ACLTokenGetByAccessor(nil, token.AccessorID, nil); err == nil && updatedToken != nil {
739		*reply = *updatedToken
740	} else {
741		return fmt.Errorf("Failed to retrieve the token after insertion")
742	}
743
744	return nil
745}
746
747func validateBindingRuleBindName(bindType, bindName string, availableFields []string) (bool, error) {
748	if bindType == "" || bindName == "" {
749		return false, nil
750	}
751
752	fakeVarMap := make(map[string]string)
753	for _, v := range availableFields {
754		fakeVarMap[v] = "fake"
755	}
756
757	_, valid, err := computeBindingRuleBindName(bindType, bindName, fakeVarMap)
758	if err != nil {
759		return false, err
760	}
761	return valid, nil
762}
763
764// computeBindingRuleBindName processes the HIL for the provided bind type+name
765// using the projected variables.
766//
767// - If the HIL is invalid ("", false, AN_ERROR) is returned.
768// - If the computed name is not valid for the type ("INVALID_NAME", false, nil) is returned.
769// - If the computed name is valid for the type ("VALID_NAME", true, nil) is returned.
770func computeBindingRuleBindName(bindType, bindName string, projectedVars map[string]string) (string, bool, error) {
771	bindName, err := template.InterpolateHIL(bindName, projectedVars, true)
772	if err != nil {
773		return "", false, err
774	}
775
776	valid := false
777
778	switch bindType {
779	case structs.BindingRuleBindTypeService:
780		valid = isValidServiceIdentityName(bindName)
781	case structs.BindingRuleBindTypeNode:
782		valid = isValidNodeIdentityName(bindName)
783	case structs.BindingRuleBindTypeRole:
784		valid = validRoleName.MatchString(bindName)
785
786	default:
787		return "", false, fmt.Errorf("unknown binding rule bind type: %s", bindType)
788	}
789
790	return bindName, valid, nil
791}
792
793// isValidServiceIdentityName returns true if the provided name can be used as
794// an ACLServiceIdentity ServiceName. This is more restrictive than standard
795// catalog registration, which basically takes the view that "everything is
796// valid".
797func isValidServiceIdentityName(name string) bool {
798	if len(name) < 1 || len(name) > serviceIdentityNameMaxLength {
799		return false
800	}
801	return validServiceIdentityName.MatchString(name)
802}
803
804// isValidNodeIdentityName returns true if the provided name can be used as
805// an ACLNodeIdentity NodeName. This is more restrictive than standard
806// catalog registration, which basically takes the view that "everything is
807// valid".
808func isValidNodeIdentityName(name string) bool {
809	if len(name) < 1 || len(name) > nodeIdentityNameMaxLength {
810		return false
811	}
812	return validNodeIdentityName.MatchString(name)
813}
814
815func (a *ACL) TokenDelete(args *structs.ACLTokenDeleteRequest, reply *string) error {
816	if err := a.aclPreCheck(); err != nil {
817		return err
818	}
819
820	if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, true); err != nil {
821		return err
822	}
823
824	if !a.srv.LocalTokensEnabled() {
825		args.Datacenter = a.srv.config.ACLDatacenter
826	}
827
828	if done, err := a.srv.ForwardRPC("ACL.TokenDelete", args, reply); done {
829		return err
830	}
831
832	defer metrics.MeasureSince([]string{"acl", "token", "delete"}, time.Now())
833
834	// Verify token is permitted to modify ACLs
835	var authzContext acl.AuthorizerContext
836	if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
837		return err
838	} else if authz == nil || authz.ACLWrite(&authzContext) != acl.Allow {
839		return acl.ErrPermissionDenied
840	}
841
842	if _, err := uuid.ParseUUID(args.TokenID); err != nil {
843		return fmt.Errorf("Accessor ID is missing or an invalid UUID")
844	}
845
846	if args.TokenID == structs.ACLTokenAnonymousID {
847		return fmt.Errorf("Delete operation not permitted on the anonymous token")
848	}
849
850	// grab the token here so we can invalidate our cache later on
851	_, token, err := a.srv.fsm.State().ACLTokenGetByAccessor(nil, args.TokenID, &args.EnterpriseMeta)
852	if err != nil {
853		return err
854	}
855
856	if token != nil {
857		if args.Token == token.SecretID {
858			return fmt.Errorf("Deletion of the request's authorization token is not permitted")
859		}
860
861		// No need to check expiration time because it's being deleted.
862
863		// token found in secondary DC but its not local so it must be deleted in the primary
864		if !a.srv.InACLDatacenter() && !token.Local {
865			args.Datacenter = a.srv.config.ACLDatacenter
866			return a.srv.forwardDC("ACL.TokenDelete", a.srv.config.ACLDatacenter, args, reply)
867		}
868	} else if !a.srv.InACLDatacenter() {
869		// token not found in secondary DC - attempt to delete within the primary
870		args.Datacenter = a.srv.config.ACLDatacenter
871		return a.srv.forwardDC("ACL.TokenDelete", a.srv.config.ACLDatacenter, args, reply)
872	} else {
873		// in Primary Datacenter but the token does not exist - return early as there is nothing to do.
874		return nil
875	}
876
877	req := &structs.ACLTokenBatchDeleteRequest{
878		TokenIDs: []string{args.TokenID},
879	}
880
881	_, err = a.srv.raftApply(structs.ACLTokenDeleteRequestType, req)
882	if err != nil {
883		return fmt.Errorf("Failed to apply token delete request: %v", err)
884	}
885
886	// Purge the identity from the cache to prevent using the previous definition of the identity
887	a.srv.acls.cache.RemoveIdentity(tokenSecretCacheID(token.SecretID))
888
889	if reply != nil {
890		*reply = token.AccessorID
891	}
892
893	return nil
894}
895
896func (a *ACL) TokenList(args *structs.ACLTokenListRequest, reply *structs.ACLTokenListResponse) error {
897	if err := a.aclPreCheck(); err != nil {
898		return err
899	}
900
901	if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, false); err != nil {
902		return err
903	}
904
905	if !a.srv.LocalTokensEnabled() {
906		if args.Datacenter != a.srv.config.ACLDatacenter {
907			args.Datacenter = a.srv.config.ACLDatacenter
908			args.IncludeLocal = false
909			args.IncludeGlobal = true
910		}
911		args.Datacenter = a.srv.config.ACLDatacenter
912	}
913
914	if done, err := a.srv.ForwardRPC("ACL.TokenList", args, reply); done {
915		return err
916	}
917
918	var authzContext acl.AuthorizerContext
919	var requestMeta structs.EnterpriseMeta
920	authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &requestMeta, &authzContext)
921	if err != nil {
922		return err
923	}
924	// merge the token default meta into the requests meta
925	args.EnterpriseMeta.Merge(&requestMeta)
926	args.EnterpriseMeta.FillAuthzContext(&authzContext)
927	if authz == nil || authz.ACLRead(&authzContext) != acl.Allow {
928		return acl.ErrPermissionDenied
929	}
930
931	var methodMeta *structs.EnterpriseMeta
932	if args.AuthMethod != "" {
933		methodMeta = args.ACLAuthMethodEnterpriseMeta.ToEnterpriseMeta()
934		// attempt to merge in the overall meta, wildcards will not be merged
935		methodMeta.MergeNoWildcard(&args.EnterpriseMeta)
936		// in the event that the meta above didn't merge due to being a wildcard
937		// we ensure that proper token based meta inference occurs
938		methodMeta.Merge(&requestMeta)
939	}
940
941	return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
942		func(ws memdb.WatchSet, state *state.Store) error {
943			index, tokens, err := state.ACLTokenList(ws, args.IncludeLocal, args.IncludeGlobal, args.Policy, args.Role, args.AuthMethod, methodMeta, &args.EnterpriseMeta)
944			if err != nil {
945				return err
946			}
947
948			now := time.Now()
949
950			stubs := make([]*structs.ACLTokenListStub, 0, len(tokens))
951			for _, token := range tokens {
952				if token.IsExpired(now) {
953					continue
954				}
955				stubs = append(stubs, token.Stub())
956			}
957
958			// filter down to just the tokens that the requester has permissions to read
959			if err := a.srv.filterACLWithAuthorizer(authz, &stubs); err != nil {
960				return err
961			}
962
963			reply.Index, reply.Tokens = index, stubs
964			return nil
965		})
966}
967
968func (a *ACL) TokenBatchRead(args *structs.ACLTokenBatchGetRequest, reply *structs.ACLTokenBatchResponse) error {
969	if err := a.aclPreCheck(); err != nil {
970		return err
971	}
972
973	if !a.srv.LocalTokensEnabled() {
974		args.Datacenter = a.srv.config.ACLDatacenter
975	}
976
977	if done, err := a.srv.ForwardRPC("ACL.TokenBatchRead", args, reply); done {
978		return err
979	}
980
981	authz, err := a.srv.ResolveToken(args.Token)
982	if err != nil {
983		return err
984	} else if authz == nil {
985		return acl.ErrPermissionDenied
986	}
987
988	return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
989		func(ws memdb.WatchSet, state *state.Store) error {
990			index, tokens, err := state.ACLTokenBatchGet(ws, args.AccessorIDs)
991			if err != nil {
992				return err
993			}
994
995			// This RPC is used for replication, so don't filter out expired tokens here.
996
997			// Filter the tokens down to just what we have permission to see - also redact
998			// secrets based on allowed permissions. We could just call filterACLWithAuthorizer
999			// on the whole token list but then it would require another pass through the token
1000			// list to determine if any secrets were redacted. Its a small amount of code to
1001			// process the loop so it was duplicated here and we instead call the filter func
1002			// with just a single token.
1003			ret := make(structs.ACLTokens, 0, len(tokens))
1004			for _, token := range tokens {
1005				final := token
1006				a.srv.filterACLWithAuthorizer(authz, &final)
1007				if final != nil {
1008					ret = append(ret, final)
1009					if final.SecretID == redactedToken {
1010						reply.Redacted = true
1011					}
1012				} else {
1013					reply.Removed = true
1014				}
1015			}
1016
1017			reply.Index, reply.Tokens = index, ret
1018			return nil
1019		})
1020}
1021
1022func (a *ACL) PolicyRead(args *structs.ACLPolicyGetRequest, reply *structs.ACLPolicyResponse) error {
1023	if err := a.aclPreCheck(); err != nil {
1024		return err
1025	}
1026
1027	if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, false); err != nil {
1028		return err
1029	}
1030
1031	if done, err := a.srv.ForwardRPC("ACL.PolicyRead", args, reply); done {
1032		return err
1033	}
1034
1035	var authzContext acl.AuthorizerContext
1036	if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
1037		return err
1038	} else if authz == nil || authz.ACLRead(&authzContext) != acl.Allow {
1039		return acl.ErrPermissionDenied
1040	}
1041
1042	return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
1043		func(ws memdb.WatchSet, state *state.Store) error {
1044			var (
1045				index  uint64
1046				policy *structs.ACLPolicy
1047				err    error
1048			)
1049			if args.PolicyID != "" {
1050				index, policy, err = state.ACLPolicyGetByID(ws, args.PolicyID, &args.EnterpriseMeta)
1051			} else {
1052				index, policy, err = state.ACLPolicyGetByName(ws, args.PolicyName, &args.EnterpriseMeta)
1053			}
1054
1055			if err != nil {
1056				return err
1057			}
1058
1059			reply.Index, reply.Policy = index, policy
1060			return nil
1061		})
1062}
1063
1064func (a *ACL) PolicyBatchRead(args *structs.ACLPolicyBatchGetRequest, reply *structs.ACLPolicyBatchResponse) error {
1065	if err := a.aclPreCheck(); err != nil {
1066		return err
1067	}
1068
1069	if done, err := a.srv.ForwardRPC("ACL.PolicyBatchRead", args, reply); done {
1070		return err
1071	}
1072
1073	authz, err := a.srv.ResolveToken(args.Token)
1074	if err != nil {
1075		return err
1076	} else if authz == nil {
1077		return acl.ErrPermissionDenied
1078	}
1079
1080	return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
1081		func(ws memdb.WatchSet, state *state.Store) error {
1082			index, policies, err := state.ACLPolicyBatchGet(ws, args.PolicyIDs)
1083			if err != nil {
1084				return err
1085			}
1086
1087			a.srv.filterACLWithAuthorizer(authz, &policies)
1088
1089			reply.Index, reply.Policies = index, policies
1090			return nil
1091		})
1092}
1093
1094func (a *ACL) PolicySet(args *structs.ACLPolicySetRequest, reply *structs.ACLPolicy) error {
1095	if err := a.aclPreCheck(); err != nil {
1096		return err
1097	}
1098
1099	if err := a.srv.validateEnterpriseRequest(&args.Policy.EnterpriseMeta, true); err != nil {
1100		return err
1101	}
1102
1103	if !a.srv.InACLDatacenter() {
1104		args.Datacenter = a.srv.config.ACLDatacenter
1105	}
1106
1107	if done, err := a.srv.ForwardRPC("ACL.PolicySet", args, reply); done {
1108		return err
1109	}
1110
1111	defer metrics.MeasureSince([]string{"acl", "policy", "upsert"}, time.Now())
1112
1113	// Verify token is permitted to modify ACLs
1114	var authzContext acl.AuthorizerContext
1115
1116	if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.Policy.EnterpriseMeta, &authzContext); err != nil {
1117		return err
1118	} else if authz == nil || authz.ACLWrite(&authzContext) != acl.Allow {
1119		return acl.ErrPermissionDenied
1120	}
1121
1122	policy := &args.Policy
1123	state := a.srv.fsm.State()
1124
1125	// Almost all of the checks here are also done in the state store. However,
1126	// we want to prevent the raft operations when we know they are going to fail
1127	// so we still do them here.
1128
1129	// ensure a name is set
1130	if policy.Name == "" {
1131		return fmt.Errorf("Invalid Policy: no Name is set")
1132	}
1133
1134	if !validPolicyName.MatchString(policy.Name) {
1135		return fmt.Errorf("Invalid Policy: invalid Name. Only alphanumeric characters, '-' and '_' are allowed")
1136	}
1137
1138	var idMatch *structs.ACLPolicy
1139	var nameMatch *structs.ACLPolicy
1140	var err error
1141
1142	if policy.ID != "" {
1143		if _, err := uuid.ParseUUID(policy.ID); err != nil {
1144			return fmt.Errorf("Policy ID invalid UUID")
1145		}
1146
1147		_, idMatch, err = state.ACLPolicyGetByID(nil, policy.ID, nil)
1148		if err != nil {
1149			return fmt.Errorf("acl policy lookup by id failed: %v", err)
1150		}
1151	}
1152	_, nameMatch, err = state.ACLPolicyGetByName(nil, policy.Name, &policy.EnterpriseMeta)
1153	if err != nil {
1154		return fmt.Errorf("acl policy lookup by name failed: %v", err)
1155	}
1156
1157	if policy.ID == "" {
1158		// with no policy ID one will be generated
1159		var err error
1160		policy.ID, err = lib.GenerateUUID(a.srv.checkPolicyUUID)
1161		if err != nil {
1162			return err
1163		}
1164
1165		// validate the name is unique
1166		if nameMatch != nil {
1167			return fmt.Errorf("Invalid Policy: A Policy with Name %q already exists", policy.Name)
1168		}
1169	} else {
1170		// Verify the policy exists
1171		if idMatch == nil {
1172			return fmt.Errorf("cannot find policy %s", policy.ID)
1173		}
1174
1175		// Verify that the name isn't changing or that the name is not already used
1176		if idMatch.Name != policy.Name && nameMatch != nil {
1177			return fmt.Errorf("Invalid Policy: A policy with name %q already exists", policy.Name)
1178		}
1179
1180		if policy.ID == structs.ACLPolicyGlobalManagementID {
1181			if policy.Datacenters != nil || len(policy.Datacenters) > 0 {
1182				return fmt.Errorf("Changing the Datacenters of the builtin global-management policy is not permitted")
1183			}
1184
1185			if policy.Rules != idMatch.Rules {
1186				return fmt.Errorf("Changing the Rules for the builtin global-management policy is not permitted")
1187			}
1188		}
1189	}
1190
1191	// validate the rules
1192	_, err = acl.NewPolicyFromSource("", 0, policy.Rules, policy.Syntax, a.srv.aclConfig, policy.EnterprisePolicyMeta())
1193	if err != nil {
1194		return err
1195	}
1196
1197	// validate the enterprise meta
1198	err = state.ACLPolicyUpsertValidateEnterprise(policy, idMatch)
1199	if err != nil {
1200		return err
1201	}
1202
1203	// calculate the hash for this policy
1204	policy.SetHash(true)
1205
1206	req := &structs.ACLPolicyBatchSetRequest{
1207		Policies: structs.ACLPolicies{policy},
1208	}
1209
1210	_, err = a.srv.raftApply(structs.ACLPolicySetRequestType, req)
1211	if err != nil {
1212		return fmt.Errorf("Failed to apply policy upsert request: %v", err)
1213	}
1214
1215	// Remove from the cache to prevent stale cache usage
1216	a.srv.acls.cache.RemovePolicy(policy.ID)
1217
1218	if _, policy, err := a.srv.fsm.State().ACLPolicyGetByID(nil, policy.ID, &policy.EnterpriseMeta); err == nil && policy != nil {
1219		*reply = *policy
1220	}
1221
1222	return nil
1223}
1224
1225func (a *ACL) PolicyDelete(args *structs.ACLPolicyDeleteRequest, reply *string) error {
1226	if err := a.aclPreCheck(); err != nil {
1227		return err
1228	}
1229
1230	if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, true); err != nil {
1231		return err
1232	}
1233
1234	if !a.srv.InACLDatacenter() {
1235		args.Datacenter = a.srv.config.ACLDatacenter
1236	}
1237
1238	if done, err := a.srv.ForwardRPC("ACL.PolicyDelete", args, reply); done {
1239		return err
1240	}
1241
1242	defer metrics.MeasureSince([]string{"acl", "policy", "delete"}, time.Now())
1243
1244	// Verify token is permitted to modify ACLs
1245	var authzContext acl.AuthorizerContext
1246
1247	if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
1248		return err
1249	} else if authz == nil || authz.ACLWrite(&authzContext) != acl.Allow {
1250		return acl.ErrPermissionDenied
1251	}
1252
1253	_, policy, err := a.srv.fsm.State().ACLPolicyGetByID(nil, args.PolicyID, &args.EnterpriseMeta)
1254	if err != nil {
1255		return err
1256	}
1257
1258	if policy == nil {
1259		return nil
1260	}
1261
1262	if policy.ID == structs.ACLPolicyGlobalManagementID {
1263		return fmt.Errorf("Delete operation not permitted on the builtin global-management policy")
1264	}
1265
1266	req := structs.ACLPolicyBatchDeleteRequest{
1267		PolicyIDs: []string{args.PolicyID},
1268	}
1269
1270	_, err = a.srv.raftApply(structs.ACLPolicyDeleteRequestType, &req)
1271	if err != nil {
1272		return fmt.Errorf("Failed to apply policy delete request: %v", err)
1273	}
1274
1275	a.srv.acls.cache.RemovePolicy(policy.ID)
1276
1277	*reply = policy.Name
1278
1279	return nil
1280}
1281
1282func (a *ACL) PolicyList(args *structs.ACLPolicyListRequest, reply *structs.ACLPolicyListResponse) error {
1283	if err := a.aclPreCheck(); err != nil {
1284		return err
1285	}
1286
1287	if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, false); err != nil {
1288		return err
1289	}
1290
1291	if done, err := a.srv.ForwardRPC("ACL.PolicyList", args, reply); done {
1292		return err
1293	}
1294
1295	var authzContext acl.AuthorizerContext
1296
1297	authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext)
1298	if err != nil {
1299		return err
1300	} else if authz == nil || authz.ACLRead(&authzContext) != acl.Allow {
1301		return acl.ErrPermissionDenied
1302	}
1303
1304	return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
1305		func(ws memdb.WatchSet, state *state.Store) error {
1306			index, policies, err := state.ACLPolicyList(ws, &args.EnterpriseMeta)
1307			if err != nil {
1308				return err
1309			}
1310
1311			// filter down to just what the requester has permissions to see
1312			a.srv.filterACLWithAuthorizer(authz, &policies)
1313
1314			var stubs structs.ACLPolicyListStubs
1315			for _, policy := range policies {
1316				stubs = append(stubs, policy.Stub())
1317			}
1318
1319			reply.Index, reply.Policies = index, stubs
1320			return nil
1321		})
1322}
1323
1324// PolicyResolve is used to retrieve a subset of the policies associated with a given token
1325// The policy ids in the args simply act as a filter on the policy set assigned to the token
1326func (a *ACL) PolicyResolve(args *structs.ACLPolicyBatchGetRequest, reply *structs.ACLPolicyBatchResponse) error {
1327	if err := a.aclPreCheck(); err != nil {
1328		return err
1329	}
1330
1331	if done, err := a.srv.ForwardRPC("ACL.PolicyResolve", args, reply); done {
1332		return err
1333	}
1334
1335	// get full list of policies for this token
1336	identity, policies, err := a.srv.acls.resolveTokenToIdentityAndPolicies(args.Token)
1337	if err != nil {
1338		return err
1339	}
1340
1341	entIdentity, entPolicies, err := a.srv.acls.resolveEnterpriseIdentityAndPolicies(identity)
1342	if err != nil {
1343		return err
1344	}
1345
1346	idMap := make(map[string]*structs.ACLPolicy)
1347	for _, policyID := range identity.PolicyIDs() {
1348		idMap[policyID] = nil
1349	}
1350	if entIdentity != nil {
1351		for _, policyID := range entIdentity.PolicyIDs() {
1352			idMap[policyID] = nil
1353		}
1354	}
1355
1356	for _, policy := range policies {
1357		idMap[policy.ID] = policy
1358	}
1359	for _, policy := range entPolicies {
1360		idMap[policy.ID] = policy
1361	}
1362
1363	for _, policyID := range args.PolicyIDs {
1364		if policy, ok := idMap[policyID]; ok {
1365			// only add non-deleted policies
1366			if policy != nil {
1367				reply.Policies = append(reply.Policies, policy)
1368			}
1369		} else {
1370			// send a permission denied to indicate that the request included
1371			// policy ids not associated with this token
1372			return acl.ErrPermissionDenied
1373		}
1374	}
1375
1376	a.srv.setQueryMeta(&reply.QueryMeta)
1377
1378	return nil
1379}
1380
1381// makeACLETag returns an ETag for the given parent and policy.
1382func makeACLETag(parent string, policy *acl.Policy) string {
1383	return fmt.Sprintf("%s:%s", parent, policy.ID)
1384}
1385
1386// GetPolicy is used to retrieve a compiled policy object with a TTL. Does not
1387// support a blocking query.
1388func (a *ACL) GetPolicy(args *structs.ACLPolicyResolveLegacyRequest, reply *structs.ACLPolicyResolveLegacyResponse) error {
1389	if done, err := a.srv.ForwardRPC("ACL.GetPolicy", args, reply); done {
1390		return err
1391	}
1392
1393	// Verify we are allowed to serve this request
1394	if a.srv.config.ACLDatacenter != a.srv.config.Datacenter {
1395		return acl.ErrDisabled
1396	}
1397
1398	// Get the policy via the cache
1399	parent := a.srv.config.ACLDefaultPolicy
1400
1401	ident, policy, err := a.srv.acls.GetMergedPolicyForToken(args.ACL)
1402	if err != nil {
1403		return err
1404	}
1405
1406	if token, ok := ident.(*structs.ACLToken); ok && token.Type == structs.ACLTokenTypeManagement {
1407		parent = "manage"
1408	}
1409
1410	// translates the structures internals to most closely match what could be expressed in the original rule language
1411	policy = policy.ConvertToLegacy()
1412
1413	// Generate an ETag
1414	etag := makeACLETag(parent, policy)
1415
1416	// Setup the response
1417	reply.ETag = etag
1418	reply.TTL = a.srv.config.ACLTokenTTL
1419	a.srv.setQueryMeta(&reply.QueryMeta)
1420
1421	// Only send the policy on an Etag mis-match
1422	if args.ETag != etag {
1423		reply.Parent = parent
1424		reply.Policy = policy
1425	}
1426	return nil
1427}
1428
1429// ReplicationStatus is used to retrieve the current ACL replication status.
1430func (a *ACL) ReplicationStatus(args *structs.DCSpecificRequest,
1431	reply *structs.ACLReplicationStatus) error {
1432	// This must be sent to the leader, so we fix the args since we are
1433	// re-using a structure where we don't support all the options.
1434	args.RequireConsistent = true
1435	args.AllowStale = false
1436	if done, err := a.srv.ForwardRPC("ACL.ReplicationStatus", args, reply); done {
1437		return err
1438	}
1439
1440	// There's no ACL token required here since this doesn't leak any
1441	// sensitive information, and we don't want people to have to use
1442	// management tokens if they are querying this via a health check.
1443
1444	// Poll the latest status.
1445	a.srv.aclReplicationStatusLock.RLock()
1446	*reply = a.srv.aclReplicationStatus
1447	a.srv.aclReplicationStatusLock.RUnlock()
1448	return nil
1449}
1450
1451func timePointer(t time.Time) *time.Time {
1452	return &t
1453}
1454
1455func (a *ACL) RoleRead(args *structs.ACLRoleGetRequest, reply *structs.ACLRoleResponse) error {
1456	if err := a.aclPreCheck(); err != nil {
1457		return err
1458	}
1459
1460	if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, false); err != nil {
1461		return err
1462	}
1463
1464	if done, err := a.srv.ForwardRPC("ACL.RoleRead", args, reply); done {
1465		return err
1466	}
1467
1468	var authzContext acl.AuthorizerContext
1469
1470	if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
1471		return err
1472	} else if authz == nil || authz.ACLRead(&authzContext) != acl.Allow {
1473		return acl.ErrPermissionDenied
1474	}
1475
1476	return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
1477		func(ws memdb.WatchSet, state *state.Store) error {
1478			var (
1479				index uint64
1480				role  *structs.ACLRole
1481				err   error
1482			)
1483			if args.RoleID != "" {
1484				index, role, err = state.ACLRoleGetByID(ws, args.RoleID, &args.EnterpriseMeta)
1485			} else {
1486				index, role, err = state.ACLRoleGetByName(ws, args.RoleName, &args.EnterpriseMeta)
1487			}
1488
1489			if err != nil {
1490				return err
1491			}
1492
1493			reply.Index, reply.Role = index, role
1494			return nil
1495		})
1496}
1497
1498func (a *ACL) RoleBatchRead(args *structs.ACLRoleBatchGetRequest, reply *structs.ACLRoleBatchResponse) error {
1499	if err := a.aclPreCheck(); err != nil {
1500		return err
1501	}
1502
1503	if done, err := a.srv.ForwardRPC("ACL.RoleBatchRead", args, reply); done {
1504		return err
1505	}
1506
1507	authz, err := a.srv.ResolveToken(args.Token)
1508	if err != nil {
1509		return err
1510	} else if authz == nil {
1511		return acl.ErrPermissionDenied
1512	}
1513
1514	return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
1515		func(ws memdb.WatchSet, state *state.Store) error {
1516			index, roles, err := state.ACLRoleBatchGet(ws, args.RoleIDs)
1517			if err != nil {
1518				return err
1519			}
1520
1521			a.srv.filterACLWithAuthorizer(authz, &roles)
1522
1523			reply.Index, reply.Roles = index, roles
1524			return nil
1525		})
1526}
1527
1528func (a *ACL) RoleSet(args *structs.ACLRoleSetRequest, reply *structs.ACLRole) error {
1529	if err := a.aclPreCheck(); err != nil {
1530		return err
1531	}
1532
1533	if err := a.srv.validateEnterpriseRequest(&args.Role.EnterpriseMeta, true); err != nil {
1534		return err
1535	}
1536
1537	if !a.srv.InACLDatacenter() {
1538		args.Datacenter = a.srv.config.ACLDatacenter
1539	}
1540
1541	if done, err := a.srv.ForwardRPC("ACL.RoleSet", args, reply); done {
1542		return err
1543	}
1544
1545	defer metrics.MeasureSince([]string{"acl", "role", "upsert"}, time.Now())
1546
1547	// Verify token is permitted to modify ACLs
1548	var authzContext acl.AuthorizerContext
1549
1550	if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.Role.EnterpriseMeta, &authzContext); err != nil {
1551		return err
1552	} else if authz == nil || authz.ACLWrite(&authzContext) != acl.Allow {
1553		return acl.ErrPermissionDenied
1554	}
1555
1556	role := &args.Role
1557	state := a.srv.fsm.State()
1558
1559	// Almost all of the checks here are also done in the state store. However,
1560	// we want to prevent the raft operations when we know they are going to fail
1561	// so we still do them here.
1562
1563	// ensure a name is set
1564	if role.Name == "" {
1565		return fmt.Errorf("Invalid Role: no Name is set")
1566	}
1567
1568	if !validRoleName.MatchString(role.Name) {
1569		return fmt.Errorf("Invalid Role: invalid Name. Only alphanumeric characters, '-' and '_' are allowed")
1570	}
1571
1572	var existing *structs.ACLRole
1573	var err error
1574	if role.ID == "" {
1575		// with no role ID one will be generated
1576		role.ID, err = lib.GenerateUUID(a.srv.checkRoleUUID)
1577		if err != nil {
1578			return err
1579		}
1580
1581		// validate the name is unique
1582		if _, existing, err = state.ACLRoleGetByName(nil, role.Name, &role.EnterpriseMeta); err != nil {
1583			return fmt.Errorf("acl role lookup by name failed: %v", err)
1584		} else if existing != nil {
1585			return fmt.Errorf("Invalid Role: A Role with Name %q already exists", role.Name)
1586		}
1587	} else {
1588		if _, err := uuid.ParseUUID(role.ID); err != nil {
1589			return fmt.Errorf("Role ID invalid UUID")
1590		}
1591
1592		// Verify the role exists
1593		_, existing, err = state.ACLRoleGetByID(nil, role.ID, nil)
1594		if err != nil {
1595			return fmt.Errorf("acl role lookup failed: %v", err)
1596		} else if existing == nil {
1597			return fmt.Errorf("cannot find role %s", role.ID)
1598		}
1599
1600		if existing.Name != role.Name {
1601			if _, nameMatch, err := state.ACLRoleGetByName(nil, role.Name, &role.EnterpriseMeta); err != nil {
1602				return fmt.Errorf("acl role lookup by name failed: %v", err)
1603			} else if nameMatch != nil {
1604				return fmt.Errorf("Invalid Role: A role with name %q already exists", role.Name)
1605			}
1606		}
1607	}
1608
1609	// validate the enterprise meta
1610	if err := state.ACLRoleUpsertValidateEnterprise(role, existing); err != nil {
1611		return err
1612	}
1613
1614	policyIDs := make(map[string]struct{})
1615	var policies []structs.ACLRolePolicyLink
1616
1617	// Validate all the policy names and convert them to policy IDs
1618	for _, link := range role.Policies {
1619		if link.ID == "" {
1620			_, policy, err := state.ACLPolicyGetByName(nil, link.Name, &role.EnterpriseMeta)
1621			if err != nil {
1622				return fmt.Errorf("Error looking up policy for name %q: %v", link.Name, err)
1623			}
1624			if policy == nil {
1625				return fmt.Errorf("No such ACL policy with name %q", link.Name)
1626			}
1627			link.ID = policy.ID
1628		}
1629
1630		// Do not store the policy name within raft/memdb as the policy could be renamed in the future.
1631		link.Name = ""
1632
1633		// dedup policy links by id
1634		if _, ok := policyIDs[link.ID]; !ok {
1635			policies = append(policies, link)
1636			policyIDs[link.ID] = struct{}{}
1637		}
1638	}
1639	role.Policies = policies
1640
1641	for _, svcid := range role.ServiceIdentities {
1642		if svcid.ServiceName == "" {
1643			return fmt.Errorf("Service identity is missing the service name field on this role")
1644		}
1645		if !isValidServiceIdentityName(svcid.ServiceName) {
1646			return fmt.Errorf("Service identity %q has an invalid name. Only alphanumeric characters, '-' and '_' are allowed", svcid.ServiceName)
1647		}
1648	}
1649	role.ServiceIdentities = dedupeServiceIdentities(role.ServiceIdentities)
1650
1651	for _, nodeid := range role.NodeIdentities {
1652		if nodeid.NodeName == "" {
1653			return fmt.Errorf("Node identity is missing the node name field on this role")
1654		}
1655		if nodeid.Datacenter == "" {
1656			return fmt.Errorf("Node identity is missing the datacenter field on this role")
1657		}
1658		if !isValidNodeIdentityName(nodeid.NodeName) {
1659			return fmt.Errorf("Node identity has an invalid name. Only alphanumeric characters, '-' and '_' are allowed")
1660		}
1661	}
1662	role.NodeIdentities = dedupeNodeIdentities(role.NodeIdentities)
1663
1664	// calculate the hash for this role
1665	role.SetHash(true)
1666
1667	req := &structs.ACLRoleBatchSetRequest{
1668		Roles: structs.ACLRoles{role},
1669	}
1670
1671	_, err = a.srv.raftApply(structs.ACLRoleSetRequestType, req)
1672	if err != nil {
1673		return fmt.Errorf("Failed to apply role upsert request: %v", err)
1674	}
1675
1676	// Remove from the cache to prevent stale cache usage
1677	a.srv.acls.cache.RemoveRole(role.ID)
1678
1679	if _, role, err := a.srv.fsm.State().ACLRoleGetByID(nil, role.ID, &role.EnterpriseMeta); err == nil && role != nil {
1680		*reply = *role
1681	}
1682
1683	return nil
1684}
1685
1686func (a *ACL) RoleDelete(args *structs.ACLRoleDeleteRequest, reply *string) error {
1687	if err := a.aclPreCheck(); err != nil {
1688		return err
1689	}
1690
1691	if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, true); err != nil {
1692		return err
1693	}
1694
1695	if !a.srv.InACLDatacenter() {
1696		args.Datacenter = a.srv.config.ACLDatacenter
1697	}
1698
1699	if done, err := a.srv.ForwardRPC("ACL.RoleDelete", args, reply); done {
1700		return err
1701	}
1702
1703	defer metrics.MeasureSince([]string{"acl", "role", "delete"}, time.Now())
1704
1705	// Verify token is permitted to modify ACLs
1706	var authzContext acl.AuthorizerContext
1707
1708	if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
1709		return err
1710	} else if authz == nil || authz.ACLWrite(&authzContext) != acl.Allow {
1711		return acl.ErrPermissionDenied
1712	}
1713
1714	_, role, err := a.srv.fsm.State().ACLRoleGetByID(nil, args.RoleID, &args.EnterpriseMeta)
1715	if err != nil {
1716		return err
1717	}
1718
1719	if role == nil {
1720		return nil
1721	}
1722
1723	req := structs.ACLRoleBatchDeleteRequest{
1724		RoleIDs: []string{args.RoleID},
1725	}
1726
1727	_, err = a.srv.raftApply(structs.ACLRoleDeleteRequestType, &req)
1728	if err != nil {
1729		return fmt.Errorf("Failed to apply role delete request: %v", err)
1730	}
1731
1732	a.srv.acls.cache.RemoveRole(role.ID)
1733
1734	*reply = role.Name
1735
1736	return nil
1737}
1738
1739func (a *ACL) RoleList(args *structs.ACLRoleListRequest, reply *structs.ACLRoleListResponse) error {
1740	if err := a.aclPreCheck(); err != nil {
1741		return err
1742	}
1743
1744	if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, false); err != nil {
1745		return err
1746	}
1747
1748	if done, err := a.srv.ForwardRPC("ACL.RoleList", args, reply); done {
1749		return err
1750	}
1751
1752	var authzContext acl.AuthorizerContext
1753
1754	authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext)
1755	if err != nil {
1756		return err
1757	} else if authz == nil || authz.ACLRead(&authzContext) != acl.Allow {
1758		return acl.ErrPermissionDenied
1759	}
1760
1761	return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
1762		func(ws memdb.WatchSet, state *state.Store) error {
1763			index, roles, err := state.ACLRoleList(ws, args.Policy, &args.EnterpriseMeta)
1764			if err != nil {
1765				return err
1766			}
1767
1768			a.srv.filterACLWithAuthorizer(authz, &roles)
1769
1770			reply.Index, reply.Roles = index, roles
1771			return nil
1772		})
1773}
1774
1775// RoleResolve is used to retrieve a subset of the roles associated with a given token
1776// The role ids in the args simply act as a filter on the role set assigned to the token
1777func (a *ACL) RoleResolve(args *structs.ACLRoleBatchGetRequest, reply *structs.ACLRoleBatchResponse) error {
1778	if err := a.aclPreCheck(); err != nil {
1779		return err
1780	}
1781
1782	if done, err := a.srv.ForwardRPC("ACL.RoleResolve", args, reply); done {
1783		return err
1784	}
1785
1786	// get full list of roles for this token
1787	identity, roles, err := a.srv.acls.resolveTokenToIdentityAndRoles(args.Token)
1788	if err != nil {
1789		return err
1790	}
1791
1792	entIdentity, entRoles, err := a.srv.acls.resolveEnterpriseIdentityAndRoles(identity)
1793	if err != nil {
1794		return err
1795	}
1796
1797	idMap := make(map[string]*structs.ACLRole)
1798	for _, roleID := range identity.RoleIDs() {
1799		idMap[roleID] = nil
1800	}
1801	if entIdentity != nil {
1802		for _, roleID := range entIdentity.RoleIDs() {
1803			idMap[roleID] = nil
1804		}
1805	}
1806
1807	for _, role := range roles {
1808		idMap[role.ID] = role
1809	}
1810	for _, role := range entRoles {
1811		idMap[role.ID] = role
1812	}
1813
1814	for _, roleID := range args.RoleIDs {
1815		if role, ok := idMap[roleID]; ok {
1816			// only add non-deleted roles
1817			if role != nil {
1818				reply.Roles = append(reply.Roles, role)
1819			}
1820		} else {
1821			// send a permission denied to indicate that the request included
1822			// role ids not associated with this token
1823			return acl.ErrPermissionDenied
1824		}
1825	}
1826
1827	a.srv.setQueryMeta(&reply.QueryMeta)
1828
1829	return nil
1830}
1831
1832var errAuthMethodsRequireTokenReplication = errors.New("Token replication is required for auth methods to function")
1833
1834func (a *ACL) BindingRuleRead(args *structs.ACLBindingRuleGetRequest, reply *structs.ACLBindingRuleResponse) error {
1835	if err := a.aclPreCheck(); err != nil {
1836		return err
1837	}
1838
1839	if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, false); err != nil {
1840		return err
1841	}
1842
1843	if !a.srv.LocalTokensEnabled() {
1844		return errAuthMethodsRequireTokenReplication
1845	}
1846
1847	if done, err := a.srv.ForwardRPC("ACL.BindingRuleRead", args, reply); done {
1848		return err
1849	}
1850
1851	var authzContext acl.AuthorizerContext
1852
1853	authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext)
1854	if err != nil {
1855		return err
1856	} else if authz == nil || authz.ACLRead(&authzContext) != acl.Allow {
1857		return acl.ErrPermissionDenied
1858	}
1859
1860	return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
1861		func(ws memdb.WatchSet, state *state.Store) error {
1862			index, rule, err := state.ACLBindingRuleGetByID(ws, args.BindingRuleID, &args.EnterpriseMeta)
1863
1864			if err != nil {
1865				return err
1866			}
1867
1868			reply.Index, reply.BindingRule = index, rule
1869			return nil
1870		})
1871}
1872
1873func (a *ACL) BindingRuleSet(args *structs.ACLBindingRuleSetRequest, reply *structs.ACLBindingRule) error {
1874	if err := a.aclPreCheck(); err != nil {
1875		return err
1876	}
1877
1878	if err := a.srv.validateEnterpriseRequest(&args.BindingRule.EnterpriseMeta, true); err != nil {
1879		return err
1880	}
1881
1882	if !a.srv.LocalTokensEnabled() {
1883		return errAuthMethodsRequireTokenReplication
1884	}
1885
1886	if done, err := a.srv.ForwardRPC("ACL.BindingRuleSet", args, reply); done {
1887		return err
1888	}
1889
1890	defer metrics.MeasureSince([]string{"acl", "bindingrule", "upsert"}, time.Now())
1891
1892	var authzContext acl.AuthorizerContext
1893
1894	// Verify token is permitted to modify ACLs
1895	if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.BindingRule.EnterpriseMeta, &authzContext); err != nil {
1896		return err
1897	} else if authz == nil || authz.ACLWrite(&authzContext) != acl.Allow {
1898		return acl.ErrPermissionDenied
1899	}
1900
1901	var existing *structs.ACLBindingRule
1902	rule := &args.BindingRule
1903	state := a.srv.fsm.State()
1904
1905	if rule.ID == "" {
1906		// with no binding rule ID one will be generated
1907		var err error
1908
1909		rule.ID, err = lib.GenerateUUID(a.srv.checkBindingRuleUUID)
1910		if err != nil {
1911			return err
1912		}
1913	} else {
1914		if _, err := uuid.ParseUUID(rule.ID); err != nil {
1915			return fmt.Errorf("Binding Rule ID invalid UUID")
1916		}
1917
1918		// Verify the role exists
1919		var err error
1920		// specifically disregarding the enterprise meta here
1921		_, existing, err = state.ACLBindingRuleGetByID(nil, rule.ID, nil)
1922		if err != nil {
1923			return fmt.Errorf("acl binding rule lookup failed: %v", err)
1924		} else if existing == nil {
1925			return fmt.Errorf("cannot find binding rule %s", rule.ID)
1926		}
1927
1928		if rule.AuthMethod == "" {
1929			rule.AuthMethod = existing.AuthMethod
1930		} else if existing.AuthMethod != rule.AuthMethod {
1931			return fmt.Errorf("the AuthMethod field of an Binding Rule is immutable")
1932		}
1933	}
1934
1935	if rule.AuthMethod == "" {
1936		return fmt.Errorf("Invalid Binding Rule: no AuthMethod is set")
1937	}
1938
1939	// this is done early here to produce better errors
1940	if err := state.ACLBindingRuleUpsertValidateEnterprise(rule, existing); err != nil {
1941		return err
1942	}
1943
1944	methodIdx, method, err := state.ACLAuthMethodGetByName(nil, rule.AuthMethod, &args.BindingRule.EnterpriseMeta)
1945	if err != nil {
1946		return fmt.Errorf("acl auth method lookup failed: %v", err)
1947	} else if method == nil {
1948		return fmt.Errorf("cannot find auth method with name %q", rule.AuthMethod)
1949	}
1950	validator, err := a.srv.loadAuthMethodValidator(methodIdx, method)
1951	if err != nil {
1952		return err
1953	}
1954
1955	// Create a blank placeholder identity for use in validation below.
1956	blankID := validator.NewIdentity()
1957
1958	if rule.Selector != "" {
1959		if _, err := bexpr.CreateEvaluatorForType(rule.Selector, nil, blankID.SelectableFields); err != nil {
1960			return fmt.Errorf("invalid Binding Rule: Selector is invalid: %v", err)
1961		}
1962	}
1963
1964	if rule.BindType == "" {
1965		return fmt.Errorf("Invalid Binding Rule: no BindType is set")
1966	}
1967
1968	if rule.BindName == "" {
1969		return fmt.Errorf("Invalid Binding Rule: no BindName is set")
1970	}
1971
1972	switch rule.BindType {
1973	case structs.BindingRuleBindTypeService:
1974	case structs.BindingRuleBindTypeNode:
1975	case structs.BindingRuleBindTypeRole:
1976	default:
1977		return fmt.Errorf("Invalid Binding Rule: unknown BindType %q", rule.BindType)
1978	}
1979
1980	if valid, err := validateBindingRuleBindName(rule.BindType, rule.BindName, blankID.ProjectedVarNames()); err != nil {
1981		return fmt.Errorf("Invalid Binding Rule: invalid BindName: %v", err)
1982	} else if !valid {
1983		return fmt.Errorf("Invalid Binding Rule: invalid BindName")
1984	}
1985
1986	req := &structs.ACLBindingRuleBatchSetRequest{
1987		BindingRules: structs.ACLBindingRules{rule},
1988	}
1989
1990	_, err = a.srv.raftApply(structs.ACLBindingRuleSetRequestType, req)
1991	if err != nil {
1992		return fmt.Errorf("Failed to apply binding rule upsert request: %v", err)
1993	}
1994
1995	if _, rule, err := a.srv.fsm.State().ACLBindingRuleGetByID(nil, rule.ID, &rule.EnterpriseMeta); err == nil && rule != nil {
1996		*reply = *rule
1997	}
1998
1999	return nil
2000}
2001
2002func (a *ACL) BindingRuleDelete(args *structs.ACLBindingRuleDeleteRequest, reply *bool) error {
2003	if err := a.aclPreCheck(); err != nil {
2004		return err
2005	}
2006
2007	if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, true); err != nil {
2008		return err
2009	}
2010
2011	if !a.srv.LocalTokensEnabled() {
2012		return errAuthMethodsRequireTokenReplication
2013	}
2014
2015	if done, err := a.srv.ForwardRPC("ACL.BindingRuleDelete", args, reply); done {
2016		return err
2017	}
2018
2019	defer metrics.MeasureSince([]string{"acl", "bindingrule", "delete"}, time.Now())
2020
2021	var authzContext acl.AuthorizerContext
2022
2023	// Verify token is permitted to modify ACLs
2024	if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
2025		return err
2026	} else if authz == nil || authz.ACLWrite(&authzContext) != acl.Allow {
2027		return acl.ErrPermissionDenied
2028	}
2029
2030	_, rule, err := a.srv.fsm.State().ACLBindingRuleGetByID(nil, args.BindingRuleID, &args.EnterpriseMeta)
2031	if err != nil {
2032		return err
2033	}
2034
2035	if rule == nil {
2036		return nil
2037	}
2038
2039	req := structs.ACLBindingRuleBatchDeleteRequest{
2040		BindingRuleIDs: []string{args.BindingRuleID},
2041	}
2042
2043	_, err = a.srv.raftApply(structs.ACLBindingRuleDeleteRequestType, &req)
2044	if err != nil {
2045		return fmt.Errorf("Failed to apply binding rule delete request: %v", err)
2046	}
2047
2048	*reply = true
2049
2050	return nil
2051}
2052
2053func (a *ACL) BindingRuleList(args *structs.ACLBindingRuleListRequest, reply *structs.ACLBindingRuleListResponse) error {
2054	if err := a.aclPreCheck(); err != nil {
2055		return err
2056	}
2057
2058	if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, false); err != nil {
2059		return err
2060	}
2061
2062	if !a.srv.LocalTokensEnabled() {
2063		return errAuthMethodsRequireTokenReplication
2064	}
2065
2066	if done, err := a.srv.ForwardRPC("ACL.BindingRuleList", args, reply); done {
2067		return err
2068	}
2069
2070	var authzContext acl.AuthorizerContext
2071
2072	authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext)
2073	if err != nil {
2074		return err
2075	} else if authz == nil || authz.ACLRead(&authzContext) != acl.Allow {
2076		return acl.ErrPermissionDenied
2077	}
2078
2079	return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
2080		func(ws memdb.WatchSet, state *state.Store) error {
2081			index, rules, err := state.ACLBindingRuleList(ws, args.AuthMethod, &args.EnterpriseMeta)
2082			if err != nil {
2083				return err
2084			}
2085
2086			a.srv.filterACLWithAuthorizer(authz, &rules)
2087
2088			reply.Index, reply.BindingRules = index, rules
2089			return nil
2090		})
2091}
2092
2093func (a *ACL) AuthMethodRead(args *structs.ACLAuthMethodGetRequest, reply *structs.ACLAuthMethodResponse) error {
2094	if err := a.aclPreCheck(); err != nil {
2095		return err
2096	}
2097
2098	if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, false); err != nil {
2099		return err
2100	}
2101
2102	if !a.srv.LocalTokensEnabled() {
2103		return errAuthMethodsRequireTokenReplication
2104	}
2105
2106	if done, err := a.srv.ForwardRPC("ACL.AuthMethodRead", args, reply); done {
2107		return err
2108	}
2109
2110	var authzContext acl.AuthorizerContext
2111
2112	if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
2113		return err
2114	} else if authz == nil || authz.ACLRead(&authzContext) != acl.Allow {
2115		return acl.ErrPermissionDenied
2116	}
2117
2118	return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
2119		func(ws memdb.WatchSet, state *state.Store) error {
2120			index, method, err := state.ACLAuthMethodGetByName(ws, args.AuthMethodName, &args.EnterpriseMeta)
2121
2122			if err != nil {
2123				return err
2124			}
2125
2126			if method != nil {
2127				_ = a.enterpriseAuthMethodTypeValidation(method.Type)
2128			}
2129
2130			reply.Index, reply.AuthMethod = index, method
2131			return nil
2132		})
2133}
2134
2135func (a *ACL) AuthMethodSet(args *structs.ACLAuthMethodSetRequest, reply *structs.ACLAuthMethod) error {
2136	if err := a.aclPreCheck(); err != nil {
2137		return err
2138	}
2139
2140	if err := a.srv.validateEnterpriseRequest(&args.AuthMethod.EnterpriseMeta, true); err != nil {
2141		return err
2142	}
2143
2144	if !a.srv.LocalTokensEnabled() {
2145		return errAuthMethodsRequireTokenReplication
2146	}
2147
2148	if done, err := a.srv.ForwardRPC("ACL.AuthMethodSet", args, reply); done {
2149		return err
2150	}
2151
2152	defer metrics.MeasureSince([]string{"acl", "authmethod", "upsert"}, time.Now())
2153
2154	// Verify token is permitted to modify ACLs
2155	var authzContext acl.AuthorizerContext
2156
2157	if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.AuthMethod.EnterpriseMeta, &authzContext); err != nil {
2158		return err
2159	} else if authz == nil || authz.ACLWrite(&authzContext) != acl.Allow {
2160		return acl.ErrPermissionDenied
2161	}
2162
2163	method := &args.AuthMethod
2164	state := a.srv.fsm.State()
2165
2166	// ensure a name is set
2167	if method.Name == "" {
2168		return fmt.Errorf("Invalid Auth Method: no Name is set")
2169	}
2170	if !validAuthMethod.MatchString(method.Name) {
2171		return fmt.Errorf("Invalid Auth Method: invalid Name. Only alphanumeric characters, '-' and '_' are allowed")
2172	}
2173
2174	if err := a.enterpriseAuthMethodTypeValidation(method.Type); err != nil {
2175		return err
2176	}
2177
2178	// Check to see if the method exists first.
2179	_, existing, err := state.ACLAuthMethodGetByName(nil, method.Name, &method.EnterpriseMeta)
2180	if err != nil {
2181		return fmt.Errorf("acl auth method lookup failed: %v", err)
2182	}
2183
2184	if existing != nil {
2185		if method.Type == "" {
2186			method.Type = existing.Type
2187		} else if existing.Type != method.Type {
2188			return fmt.Errorf("the Type field of an Auth Method is immutable")
2189		}
2190	}
2191
2192	if !authmethod.IsRegisteredType(method.Type) {
2193		return fmt.Errorf("Invalid Auth Method: Type should be one of: %v", authmethod.Types())
2194	}
2195
2196	if method.MaxTokenTTL != 0 {
2197		if method.MaxTokenTTL > a.srv.config.ACLTokenMaxExpirationTTL {
2198			return fmt.Errorf("MaxTokenTTL %s cannot be more than %s",
2199				method.MaxTokenTTL, a.srv.config.ACLTokenMaxExpirationTTL)
2200		} else if method.MaxTokenTTL < a.srv.config.ACLTokenMinExpirationTTL {
2201			return fmt.Errorf("MaxTokenTTL %s cannot be less than %s",
2202				method.MaxTokenTTL, a.srv.config.ACLTokenMinExpirationTTL)
2203		}
2204	}
2205
2206	switch method.TokenLocality {
2207	case "local", "":
2208	case "global":
2209		if !a.srv.InACLDatacenter() {
2210			return fmt.Errorf("Invalid Auth Method: TokenLocality 'global' can only be used in the primary datacenter")
2211		}
2212	default:
2213		return fmt.Errorf("Invalid Auth Method: TokenLocality should be one of 'local' or 'global'")
2214	}
2215
2216	// Instantiate a validator but do not cache it yet. This will validate the
2217	// configuration.
2218	validator, err := authmethod.NewValidator(a.srv.logger, method)
2219	if err != nil {
2220		return fmt.Errorf("Invalid Auth Method: %v", err)
2221	}
2222
2223	if err := enterpriseAuthMethodValidation(method, validator); err != nil {
2224		return err
2225	}
2226
2227	if err := a.srv.fsm.State().ACLAuthMethodUpsertValidateEnterprise(method, existing); err != nil {
2228		return err
2229	}
2230
2231	req := &structs.ACLAuthMethodBatchSetRequest{
2232		AuthMethods: structs.ACLAuthMethods{method},
2233	}
2234
2235	_, err = a.srv.raftApply(structs.ACLAuthMethodSetRequestType, req)
2236	if err != nil {
2237		return fmt.Errorf("Failed to apply auth method upsert request: %v", err)
2238	}
2239
2240	if _, method, err := a.srv.fsm.State().ACLAuthMethodGetByName(nil, method.Name, &method.EnterpriseMeta); err == nil && method != nil {
2241		*reply = *method
2242	}
2243
2244	return nil
2245}
2246
2247func (a *ACL) AuthMethodDelete(args *structs.ACLAuthMethodDeleteRequest, reply *bool) error {
2248	if err := a.aclPreCheck(); err != nil {
2249		return err
2250	}
2251
2252	if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, true); err != nil {
2253		return err
2254	}
2255
2256	if !a.srv.LocalTokensEnabled() {
2257		return errAuthMethodsRequireTokenReplication
2258	}
2259
2260	if done, err := a.srv.ForwardRPC("ACL.AuthMethodDelete", args, reply); done {
2261		return err
2262	}
2263
2264	defer metrics.MeasureSince([]string{"acl", "authmethod", "delete"}, time.Now())
2265
2266	// Verify token is permitted to modify ACLs
2267	var authzContext acl.AuthorizerContext
2268
2269	if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
2270		return err
2271	} else if authz == nil || authz.ACLWrite(&authzContext) != acl.Allow {
2272		return acl.ErrPermissionDenied
2273	}
2274
2275	_, method, err := a.srv.fsm.State().ACLAuthMethodGetByName(nil, args.AuthMethodName, &args.EnterpriseMeta)
2276	if err != nil {
2277		return err
2278	}
2279
2280	if method == nil {
2281		return nil
2282	}
2283
2284	if err := a.enterpriseAuthMethodTypeValidation(method.Type); err != nil {
2285		return err
2286	}
2287
2288	req := structs.ACLAuthMethodBatchDeleteRequest{
2289		AuthMethodNames: []string{args.AuthMethodName},
2290		EnterpriseMeta:  args.EnterpriseMeta,
2291	}
2292
2293	_, err = a.srv.raftApply(structs.ACLAuthMethodDeleteRequestType, &req)
2294	if err != nil {
2295		return fmt.Errorf("Failed to apply auth method delete request: %v", err)
2296	}
2297
2298	*reply = true
2299
2300	return nil
2301}
2302
2303func (a *ACL) AuthMethodList(args *structs.ACLAuthMethodListRequest, reply *structs.ACLAuthMethodListResponse) error {
2304	if err := a.aclPreCheck(); err != nil {
2305		return err
2306	}
2307
2308	if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, false); err != nil {
2309		return err
2310	}
2311
2312	if !a.srv.LocalTokensEnabled() {
2313		return errAuthMethodsRequireTokenReplication
2314	}
2315
2316	if done, err := a.srv.ForwardRPC("ACL.AuthMethodList", args, reply); done {
2317		return err
2318	}
2319
2320	var authzContext acl.AuthorizerContext
2321
2322	authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext)
2323	if err != nil {
2324		return err
2325	} else if authz == nil || authz.ACLRead(&authzContext) != acl.Allow {
2326		return acl.ErrPermissionDenied
2327	}
2328
2329	return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
2330		func(ws memdb.WatchSet, state *state.Store) error {
2331			index, methods, err := state.ACLAuthMethodList(ws, &args.EnterpriseMeta)
2332			if err != nil {
2333				return err
2334			}
2335
2336			a.srv.filterACLWithAuthorizer(authz, &methods)
2337
2338			var stubs structs.ACLAuthMethodListStubs
2339			for _, method := range methods {
2340				_ = a.enterpriseAuthMethodTypeValidation(method.Type)
2341				stubs = append(stubs, method.Stub())
2342			}
2343
2344			reply.Index, reply.AuthMethods = index, stubs
2345			return nil
2346		})
2347}
2348
2349func (a *ACL) Login(args *structs.ACLLoginRequest, reply *structs.ACLToken) error {
2350	if err := a.aclPreCheck(); err != nil {
2351		return err
2352	}
2353
2354	if !a.srv.LocalTokensEnabled() {
2355		return errAuthMethodsRequireTokenReplication
2356	}
2357
2358	if args.Auth == nil {
2359		return fmt.Errorf("Invalid Login request: Missing auth parameters")
2360	}
2361
2362	if err := a.srv.validateEnterpriseRequest(&args.Auth.EnterpriseMeta, true); err != nil {
2363		return err
2364	}
2365
2366	if args.Token != "" { // This shouldn't happen.
2367		return errors.New("do not provide a token when logging in")
2368	}
2369
2370	if done, err := a.srv.ForwardRPC("ACL.Login", args, reply); done {
2371		return err
2372	}
2373
2374	defer metrics.MeasureSince([]string{"acl", "login"}, time.Now())
2375
2376	auth := args.Auth
2377
2378	// 1. take args.Data.AuthMethod to get an AuthMethod Validator
2379	idx, method, err := a.srv.fsm.State().ACLAuthMethodGetByName(nil, auth.AuthMethod, &auth.EnterpriseMeta)
2380	if err != nil {
2381		return err
2382	} else if method == nil {
2383		return fmt.Errorf("%w: auth method %q not found", acl.ErrNotFound, auth.AuthMethod)
2384	}
2385
2386	if err := a.enterpriseAuthMethodTypeValidation(method.Type); err != nil {
2387		return err
2388	}
2389
2390	validator, err := a.srv.loadAuthMethodValidator(idx, method)
2391	if err != nil {
2392		return err
2393	}
2394
2395	// 2. Send args.Data.BearerToken to method validator and get back a fields map
2396	verifiedIdentity, err := validator.ValidateLogin(context.Background(), auth.BearerToken)
2397	if err != nil {
2398		return err
2399	}
2400
2401	return a.tokenSetFromAuthMethod(
2402		method,
2403		&auth.EnterpriseMeta,
2404		"token created via login",
2405		auth.Meta,
2406		validator,
2407		verifiedIdentity,
2408		&structs.ACLTokenSetRequest{
2409			Datacenter:   args.Datacenter,
2410			WriteRequest: args.WriteRequest,
2411		},
2412		reply,
2413	)
2414}
2415
2416func (a *ACL) tokenSetFromAuthMethod(
2417	method *structs.ACLAuthMethod,
2418	entMeta *structs.EnterpriseMeta,
2419	tokenDescriptionPrefix string,
2420	tokenMetadata map[string]string,
2421	validator authmethod.Validator,
2422	verifiedIdentity *authmethod.Identity,
2423	createReq *structs.ACLTokenSetRequest, // this should be prepopulated with datacenter+writerequest
2424	reply *structs.ACLToken,
2425) error {
2426	// This always will return a valid pointer
2427	targetMeta, err := computeTargetEnterpriseMeta(method, verifiedIdentity)
2428	if err != nil {
2429		return err
2430	}
2431
2432	// 3. send map through role bindings
2433	bindings, err := a.srv.evaluateRoleBindings(validator, verifiedIdentity, entMeta, targetMeta)
2434	if err != nil {
2435		return err
2436	}
2437
2438	// We try to prevent the creation of a useless token without taking a trip
2439	// through the state store if we can.
2440	if bindings == nil || (len(bindings.serviceIdentities) == 0 && len(bindings.nodeIdentities) == 0 && len(bindings.roles) == 0) {
2441		return acl.ErrPermissionDenied
2442	}
2443
2444	// TODO(sso): add a CapturedField to ACLAuthMethod that would pluck fields from the returned identity and stuff into `auth.Meta`.
2445
2446	description := tokenDescriptionPrefix
2447	loginMeta, err := encodeLoginMeta(tokenMetadata)
2448	if err != nil {
2449		return err
2450	}
2451	if loginMeta != "" {
2452		description += ": " + loginMeta
2453	}
2454
2455	// 4. create token
2456	createReq.ACLToken = structs.ACLToken{
2457		Description:       description,
2458		Local:             true,
2459		AuthMethod:        method.Name,
2460		ServiceIdentities: bindings.serviceIdentities,
2461		NodeIdentities:    bindings.nodeIdentities,
2462		Roles:             bindings.roles,
2463		ExpirationTTL:     method.MaxTokenTTL,
2464		EnterpriseMeta:    *targetMeta,
2465	}
2466
2467	if method.TokenLocality == "global" {
2468		if !a.srv.InACLDatacenter() {
2469			return errors.New("creating global tokens via auth methods is only permitted in the primary datacenter")
2470		}
2471		createReq.ACLToken.Local = false
2472	}
2473
2474	createReq.ACLToken.ACLAuthMethodEnterpriseMeta.FillWithEnterpriseMeta(entMeta)
2475
2476	// 5. return token information like a TokenCreate would
2477	err = a.tokenSetInternal(createReq, reply, true)
2478
2479	// If we were in a slight race with a role delete operation then we may
2480	// still end up failing to insert an unprivileged token in the state
2481	// machine instead.  Return the same error as earlier so it doesn't
2482	// actually matter which one prevents the insertion.
2483	if err != nil && err.Error() == state.ErrTokenHasNoPrivileges.Error() {
2484		return acl.ErrPermissionDenied
2485	}
2486
2487	return err
2488}
2489
2490func encodeLoginMeta(meta map[string]string) (string, error) {
2491	if len(meta) == 0 {
2492		return "", nil
2493	}
2494
2495	d, err := json.Marshal(meta)
2496	if err != nil {
2497		return "", err
2498	}
2499	return string(d), nil
2500}
2501
2502func (a *ACL) Logout(args *structs.ACLLogoutRequest, reply *bool) error {
2503	if err := a.aclPreCheck(); err != nil {
2504		return err
2505	}
2506
2507	if !a.srv.LocalTokensEnabled() {
2508		return errAuthMethodsRequireTokenReplication
2509	}
2510
2511	if args.Token == "" {
2512		return acl.ErrNotFound
2513	}
2514
2515	if done, err := a.srv.ForwardRPC("ACL.Logout", args, reply); done {
2516		return err
2517	}
2518
2519	defer metrics.MeasureSince([]string{"acl", "logout"}, time.Now())
2520
2521	_, token, err := a.srv.fsm.State().ACLTokenGetBySecret(nil, args.Token, nil)
2522	if err != nil {
2523		return err
2524
2525	} else if token == nil {
2526		return acl.ErrNotFound
2527
2528	} else if token.AuthMethod == "" {
2529		// Can't "logout" of a token that wasn't a result of login.
2530		return acl.ErrPermissionDenied
2531
2532	} else if !a.srv.InACLDatacenter() && !token.Local {
2533		// global token writes must be forwarded to the primary DC
2534		args.Datacenter = a.srv.config.ACLDatacenter
2535		return a.srv.forwardDC("ACL.Logout", a.srv.config.ACLDatacenter, args, reply)
2536	}
2537
2538	// No need to check expiration time because it's being deleted.
2539
2540	req := &structs.ACLTokenBatchDeleteRequest{
2541		TokenIDs: []string{token.AccessorID},
2542	}
2543
2544	_, err = a.srv.raftApply(structs.ACLTokenDeleteRequestType, req)
2545	if err != nil {
2546		return fmt.Errorf("Failed to apply token delete request: %v", err)
2547	}
2548
2549	// Purge the identity from the cache to prevent using the previous definition of the identity
2550	a.srv.acls.cache.RemoveIdentity(tokenSecretCacheID(token.SecretID))
2551
2552	*reply = true
2553
2554	return nil
2555}
2556
2557func (a *ACL) Authorize(args *structs.RemoteACLAuthorizationRequest, reply *[]structs.ACLAuthorizationResponse) error {
2558	if err := a.aclPreCheck(); err != nil {
2559		return err
2560	}
2561
2562	if done, err := a.srv.ForwardRPC("ACL.Authorize", args, reply); done {
2563		return err
2564	}
2565
2566	authz, err := a.srv.ResolveToken(args.Token)
2567	if err != nil {
2568		return err
2569	} else if authz == nil {
2570		return fmt.Errorf("Failed to initialize authorizer")
2571	}
2572
2573	responses, err := structs.CreateACLAuthorizationResponses(authz, args.Requests)
2574	if err != nil {
2575		return err
2576	}
2577
2578	*reply = responses
2579	return nil
2580}
2581