github.com/clly/consul@v1.4.5/agent/consul/acl_endpoint.go (about)

     1  package consul
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"regexp"
     9  	"time"
    10  
    11  	"github.com/armon/go-metrics"
    12  	"github.com/hashicorp/consul/acl"
    13  	"github.com/hashicorp/consul/agent/consul/state"
    14  	"github.com/hashicorp/consul/agent/structs"
    15  	"github.com/hashicorp/consul/lib"
    16  	"github.com/hashicorp/go-memdb"
    17  	"github.com/hashicorp/go-uuid"
    18  )
    19  
    20  const (
    21  	// aclBootstrapReset is the file name to create in the data dir. It's only contents
    22  	// should be the reset index
    23  	aclBootstrapReset = "acl-bootstrap-reset"
    24  )
    25  
    26  // Regex for matching
    27  var validPolicyName = regexp.MustCompile(`^[A-Za-z0-9\-_]{1,128}$`)
    28  
    29  // ACL endpoint is used to manipulate ACLs
    30  type ACL struct {
    31  	srv *Server
    32  }
    33  
    34  // fileBootstrapResetIndex retrieves the reset index specified by the administrator from
    35  // the file on disk.
    36  //
    37  // Q: What is the bootstrap reset index?
    38  // A: If you happen to lose acess to all tokens capable of ACL management you need a way
    39  //    to get back into your system. This allows an admin to write the current
    40  //    bootstrap "index" into a special file on disk to override the mechanism preventing
    41  //    a second token bootstrap. The index will be retrieved by a API call to /v1/acl/bootstrap
    42  //    When already bootstrapped this API will return the reset index necessary within
    43  //    the error response. Once set in the file, the bootstrap API can be used again to
    44  //    get a new token.
    45  //
    46  // Q: Why is the reset index not in the config?
    47  // A: We want to be able to remove the reset index once we have used it. This prevents
    48  //    accidentally allowing bootstrapping yet again after a snapshot restore.
    49  //
    50  func (a *ACL) fileBootstrapResetIndex() uint64 {
    51  	// Determine the file path to check
    52  	path := filepath.Join(a.srv.config.DataDir, aclBootstrapReset)
    53  
    54  	// Read the file
    55  	raw, err := ioutil.ReadFile(path)
    56  	if err != nil {
    57  		if !os.IsNotExist(err) {
    58  			a.srv.logger.Printf("[ERR] acl.bootstrap: failed to read %q: %v", path, err)
    59  		}
    60  		return 0
    61  	}
    62  
    63  	// Attempt to parse the file
    64  	var resetIdx uint64
    65  	if _, err := fmt.Sscanf(string(raw), "%d", &resetIdx); err != nil {
    66  		a.srv.logger.Printf("[ERR] acl.bootstrap: failed to parse %q: %v", path, err)
    67  		return 0
    68  	}
    69  
    70  	// Return the reset index
    71  	a.srv.logger.Printf("[DEBUG] acl.bootstrap: parsed %q: reset index %d", path, resetIdx)
    72  	return resetIdx
    73  }
    74  
    75  func (a *ACL) removeBootstrapResetFile() {
    76  	if err := os.Remove(filepath.Join(a.srv.config.DataDir, aclBootstrapReset)); err != nil {
    77  		a.srv.logger.Printf("[WARN] acl.bootstrap: failed to remove bootstrap file: %v", err)
    78  	}
    79  }
    80  
    81  func (a *ACL) aclPreCheck() error {
    82  	if !a.srv.ACLsEnabled() {
    83  		return acl.ErrDisabled
    84  	}
    85  
    86  	if a.srv.UseLegacyACLs() {
    87  		return fmt.Errorf("The ACL system is currently in legacy mode.")
    88  	}
    89  
    90  	return nil
    91  }
    92  
    93  // Bootstrap is used to perform a one-time ACL bootstrap operation on
    94  // a cluster to get the first management token.
    95  func (a *ACL) BootstrapTokens(args *structs.DCSpecificRequest, reply *structs.ACLToken) error {
    96  	if err := a.aclPreCheck(); err != nil {
    97  		return err
    98  	}
    99  	if done, err := a.srv.forward("ACL.BootstrapTokens", args, args, reply); done {
   100  		return err
   101  	}
   102  
   103  	// Verify we are allowed to serve this request
   104  	if !a.srv.InACLDatacenter() {
   105  		return acl.ErrDisabled
   106  	}
   107  
   108  	// By doing some pre-checks we can head off later bootstrap attempts
   109  	// without having to run them through Raft, which should curb abuse.
   110  	state := a.srv.fsm.State()
   111  	allowed, resetIdx, err := state.CanBootstrapACLToken()
   112  	if err != nil {
   113  		return err
   114  	}
   115  	var specifiedIndex uint64 = 0
   116  	if !allowed {
   117  		// Check if there is a reset index specified
   118  		specifiedIndex = a.fileBootstrapResetIndex()
   119  		if specifiedIndex == 0 {
   120  			return fmt.Errorf("ACL bootstrap no longer allowed (reset index: %d)", resetIdx)
   121  		} else if specifiedIndex != resetIdx {
   122  			return fmt.Errorf("Invalid bootstrap reset index (specified %d, reset index: %d)", specifiedIndex, resetIdx)
   123  		}
   124  	}
   125  
   126  	// remove the bootstrap override file now that we have the index from it and it was valid.
   127  	// whether bootstrapping works or not is irrelevant as we really don't want this file hanging around
   128  	// in case a snapshot restore is done. In that case we don't want to accidentally allow re-bootstrapping
   129  	// just because the file was unchanged.
   130  	a.removeBootstrapResetFile()
   131  
   132  	accessor, err := lib.GenerateUUID(a.srv.checkTokenUUID)
   133  	if err != nil {
   134  		return err
   135  	}
   136  	secret, err := lib.GenerateUUID(a.srv.checkTokenUUID)
   137  	if err != nil {
   138  		return err
   139  	}
   140  
   141  	req := structs.ACLTokenBootstrapRequest{
   142  		Token: structs.ACLToken{
   143  			AccessorID:  accessor,
   144  			SecretID:    secret,
   145  			Description: "Bootstrap Token (Global Management)",
   146  			Policies: []structs.ACLTokenPolicyLink{
   147  				{
   148  					ID: structs.ACLPolicyGlobalManagementID,
   149  				},
   150  			},
   151  			CreateTime: time.Now(),
   152  			Local:      false,
   153  			// DEPRECATED (ACL-Legacy-Compat) - This is used so that the bootstrap token is still visible via the v1 acl APIs
   154  			Type: structs.ACLTokenTypeManagement,
   155  		},
   156  		ResetIndex: specifiedIndex,
   157  	}
   158  
   159  	req.Token.SetHash(true)
   160  
   161  	resp, err := a.srv.raftApply(structs.ACLBootstrapRequestType, &req)
   162  	if err != nil {
   163  		return err
   164  	}
   165  
   166  	if err, ok := resp.(error); ok {
   167  		return err
   168  	}
   169  
   170  	if _, token, err := state.ACLTokenGetByAccessor(nil, accessor); err == nil {
   171  		*reply = *token
   172  	}
   173  
   174  	a.srv.logger.Printf("[INFO] consul.acl: ACL bootstrap completed")
   175  	return nil
   176  }
   177  
   178  func (a *ACL) TokenRead(args *structs.ACLTokenGetRequest, reply *structs.ACLTokenResponse) error {
   179  	if err := a.aclPreCheck(); err != nil {
   180  		return err
   181  	}
   182  
   183  	// clients will not know whether the server has local token store. In the case
   184  	// where it doesn't we will transparently forward requests.
   185  	if !a.srv.LocalTokensEnabled() {
   186  		args.Datacenter = a.srv.config.ACLDatacenter
   187  	}
   188  
   189  	if done, err := a.srv.forward("ACL.TokenRead", args, args, reply); done {
   190  		return err
   191  	}
   192  
   193  	var rule acl.Authorizer
   194  	if args.TokenIDType == structs.ACLTokenAccessor {
   195  		var err error
   196  		// Only ACLRead privileges are required to list tokens
   197  		// However if you do not have ACLWrite as well the token
   198  		// secrets will be redacted
   199  		if rule, err = a.srv.ResolveToken(args.Token); err != nil {
   200  			return err
   201  		} else if rule == nil || !rule.ACLRead() {
   202  			return acl.ErrPermissionDenied
   203  		}
   204  	}
   205  
   206  	return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
   207  		func(ws memdb.WatchSet, state *state.Store) error {
   208  			var index uint64
   209  			var token *structs.ACLToken
   210  			var err error
   211  
   212  			if args.TokenIDType == structs.ACLTokenAccessor {
   213  				index, token, err = state.ACLTokenGetByAccessor(ws, args.TokenID)
   214  				if token != nil {
   215  					a.srv.filterACLWithAuthorizer(rule, &token)
   216  					if !rule.ACLWrite() {
   217  						reply.Redacted = true
   218  					}
   219  				}
   220  			} else {
   221  				index, token, err = state.ACLTokenGetBySecret(ws, args.TokenID)
   222  			}
   223  
   224  			if err != nil {
   225  				return err
   226  			}
   227  
   228  			reply.Index, reply.Token = index, token
   229  			return nil
   230  		})
   231  }
   232  
   233  func (a *ACL) TokenClone(args *structs.ACLTokenSetRequest, reply *structs.ACLToken) error {
   234  	if err := a.aclPreCheck(); err != nil {
   235  		return err
   236  	}
   237  
   238  	// clients will not know whether the server has local token store. In the case
   239  	// where it doesn't we will transparently forward requests.
   240  	if !a.srv.LocalTokensEnabled() {
   241  		args.Datacenter = a.srv.config.ACLDatacenter
   242  	}
   243  
   244  	if done, err := a.srv.forward("ACL.TokenClone", args, args, reply); done {
   245  		return err
   246  	}
   247  
   248  	defer metrics.MeasureSince([]string{"acl", "token", "clone"}, time.Now())
   249  
   250  	if rule, err := a.srv.ResolveToken(args.Token); err != nil {
   251  		return err
   252  	} else if rule == nil || !rule.ACLWrite() {
   253  		return acl.ErrPermissionDenied
   254  	}
   255  
   256  	_, token, err := a.srv.fsm.State().ACLTokenGetByAccessor(nil, args.ACLToken.AccessorID)
   257  	if err != nil {
   258  		return err
   259  	} else if token == nil {
   260  		return acl.ErrNotFound
   261  	} else if !a.srv.InACLDatacenter() && !token.Local {
   262  		// global token writes must be forwarded to the primary DC
   263  		args.Datacenter = a.srv.config.ACLDatacenter
   264  		return a.srv.forwardDC("ACL.TokenClone", a.srv.config.ACLDatacenter, args, reply)
   265  	}
   266  
   267  	if token.Rules != "" {
   268  		return fmt.Errorf("Cannot clone a legacy ACL with this endpoint")
   269  	}
   270  
   271  	cloneReq := structs.ACLTokenSetRequest{
   272  		Datacenter: args.Datacenter,
   273  		ACLToken: structs.ACLToken{
   274  			Policies:    token.Policies,
   275  			Local:       token.Local,
   276  			Description: token.Description,
   277  		},
   278  		WriteRequest: args.WriteRequest,
   279  	}
   280  
   281  	if args.ACLToken.Description != "" {
   282  		cloneReq.ACLToken.Description = args.ACLToken.Description
   283  	}
   284  
   285  	return a.tokenSetInternal(&cloneReq, reply, false)
   286  }
   287  
   288  func (a *ACL) TokenSet(args *structs.ACLTokenSetRequest, reply *structs.ACLToken) error {
   289  	if err := a.aclPreCheck(); err != nil {
   290  		return err
   291  	}
   292  
   293  	// Global token creation/modification always goes to the ACL DC
   294  	if !args.ACLToken.Local {
   295  		args.Datacenter = a.srv.config.ACLDatacenter
   296  	} else if !a.srv.LocalTokensEnabled() {
   297  		return fmt.Errorf("Local tokens are disabled")
   298  	}
   299  
   300  	if done, err := a.srv.forward("ACL.TokenSet", args, args, reply); done {
   301  		return err
   302  	}
   303  
   304  	defer metrics.MeasureSince([]string{"acl", "token", "upsert"}, time.Now())
   305  
   306  	// Verify token is permitted to modify ACLs
   307  	if rule, err := a.srv.ResolveToken(args.Token); err != nil {
   308  		return err
   309  	} else if rule == nil || !rule.ACLWrite() {
   310  		return acl.ErrPermissionDenied
   311  	}
   312  
   313  	return a.tokenSetInternal(args, reply, false)
   314  }
   315  
   316  func (a *ACL) tokenSetInternal(args *structs.ACLTokenSetRequest, reply *structs.ACLToken, upgrade bool) error {
   317  	token := &args.ACLToken
   318  
   319  	if !a.srv.LocalTokensEnabled() {
   320  		// local token operations
   321  		return fmt.Errorf("Cannot upsert tokens within this datacenter")
   322  	} else if !a.srv.InACLDatacenter() && !token.Local {
   323  		return fmt.Errorf("Cannot upsert global tokens within this datacenter")
   324  	}
   325  
   326  	state := a.srv.fsm.State()
   327  
   328  	if token.AccessorID == "" {
   329  		// Token Create
   330  		var err error
   331  
   332  		// Generate the AccessorID
   333  		token.AccessorID, err = lib.GenerateUUID(a.srv.checkTokenUUID)
   334  		if err != nil {
   335  			return err
   336  		}
   337  
   338  		// Generate the SecretID - not supporting non-UUID secrets
   339  		token.SecretID, err = lib.GenerateUUID(a.srv.checkTokenUUID)
   340  		if err != nil {
   341  			return err
   342  		}
   343  
   344  		token.CreateTime = time.Now()
   345  	} else {
   346  		// Token Update
   347  		if _, err := uuid.ParseUUID(token.AccessorID); err != nil {
   348  			return fmt.Errorf("AccessorID is not a valid UUID")
   349  		}
   350  
   351  		// DEPRECATED (ACL-Legacy-Compat) - maybe get rid of this in the future
   352  		//   and instead do a ParseUUID check. New tokens will not have
   353  		//   secrets generated by users but rather they will always be UUIDs.
   354  		//   However if users just continue the upgrade cycle they may still
   355  		//   have tokens using secrets that are not UUIDS
   356  		// The RootAuthorizer checks that the SecretID is not "allow", "deny"
   357  		// or "manage" as a precaution against something accidentally using
   358  		// one of these root policies by setting the secret to it.
   359  		if acl.RootAuthorizer(token.SecretID) != nil {
   360  			return acl.PermissionDeniedError{Cause: "Cannot modify root ACL"}
   361  		}
   362  
   363  		// Verify the token exists
   364  		_, existing, err := state.ACLTokenGetByAccessor(nil, token.AccessorID)
   365  		if err != nil {
   366  			return fmt.Errorf("Failed to lookup the acl token %q: %v", token.AccessorID, err)
   367  		}
   368  		if existing == nil {
   369  			return fmt.Errorf("Cannot find token %q", token.AccessorID)
   370  		}
   371  		if token.SecretID == "" {
   372  			token.SecretID = existing.SecretID
   373  		} else if existing.SecretID != token.SecretID {
   374  			return fmt.Errorf("Changing a tokens SecretID is not permitted")
   375  		}
   376  
   377  		// Cannot toggle the "Global" mode
   378  		if token.Local != existing.Local {
   379  			return fmt.Errorf("cannot toggle local mode of %s", token.AccessorID)
   380  		}
   381  
   382  		if upgrade {
   383  			token.CreateTime = time.Now()
   384  		} else {
   385  			token.CreateTime = existing.CreateTime
   386  		}
   387  	}
   388  
   389  	policyIDs := make(map[string]struct{})
   390  	var policies []structs.ACLTokenPolicyLink
   391  
   392  	// Validate all the policy names and convert them to policy IDs
   393  	for _, link := range token.Policies {
   394  		if link.ID == "" {
   395  			_, policy, err := state.ACLPolicyGetByName(nil, link.Name)
   396  			if err != nil {
   397  				return fmt.Errorf("Error looking up policy for name %q: %v", link.Name, err)
   398  			}
   399  			if policy == nil {
   400  				return fmt.Errorf("No such ACL policy with name %q", link.Name)
   401  			}
   402  			link.ID = policy.ID
   403  		}
   404  
   405  		// Do not store the policy name within raft/memdb as the policy could be renamed in the future.
   406  		link.Name = ""
   407  
   408  		// dedup policy links by id
   409  		if _, ok := policyIDs[link.ID]; !ok {
   410  			policies = append(policies, link)
   411  			policyIDs[link.ID] = struct{}{}
   412  		}
   413  	}
   414  	token.Policies = policies
   415  
   416  	if token.Rules != "" {
   417  		return fmt.Errorf("Rules cannot be specified for this token")
   418  	}
   419  
   420  	if token.Type != "" {
   421  		return fmt.Errorf("Type cannot be specified for this token")
   422  	}
   423  
   424  	token.SetHash(true)
   425  
   426  	req := &structs.ACLTokenBatchSetRequest{
   427  		Tokens: structs.ACLTokens{token},
   428  		CAS:    false,
   429  	}
   430  
   431  	resp, err := a.srv.raftApply(structs.ACLTokenSetRequestType, req)
   432  	if err != nil {
   433  		return fmt.Errorf("Failed to apply token write request: %v", err)
   434  	}
   435  
   436  	// Purge the identity from the cache to prevent using the previous definition of the identity
   437  	a.srv.acls.cache.RemoveIdentity(token.SecretID)
   438  
   439  	if respErr, ok := resp.(error); ok {
   440  		return respErr
   441  	}
   442  
   443  	if _, updatedToken, err := a.srv.fsm.State().ACLTokenGetByAccessor(nil, token.AccessorID); err == nil && token != nil {
   444  		*reply = *updatedToken
   445  	} else {
   446  		return fmt.Errorf("Failed to retrieve the token after insertion")
   447  	}
   448  
   449  	return nil
   450  }
   451  
   452  func (a *ACL) TokenDelete(args *structs.ACLTokenDeleteRequest, reply *string) error {
   453  	if err := a.aclPreCheck(); err != nil {
   454  		return err
   455  	}
   456  
   457  	if !a.srv.LocalTokensEnabled() {
   458  		args.Datacenter = a.srv.config.ACLDatacenter
   459  	}
   460  
   461  	if done, err := a.srv.forward("ACL.TokenDelete", args, args, reply); done {
   462  		return err
   463  	}
   464  
   465  	defer metrics.MeasureSince([]string{"acl", "token", "delete"}, time.Now())
   466  
   467  	// Verify token is permitted to modify ACLs
   468  	if rule, err := a.srv.ResolveToken(args.Token); err != nil {
   469  		return err
   470  	} else if rule == nil || !rule.ACLWrite() {
   471  		return acl.ErrPermissionDenied
   472  	}
   473  
   474  	if _, err := uuid.ParseUUID(args.TokenID); err != nil {
   475  		return fmt.Errorf("Accessor ID is missing or an invalid UUID")
   476  	}
   477  
   478  	if args.TokenID == structs.ACLTokenAnonymousID {
   479  		return fmt.Errorf("Delete operation not permitted on the anonymous token")
   480  	}
   481  
   482  	// grab the token here so we can invalidate our cache later on
   483  	_, token, err := a.srv.fsm.State().ACLTokenGetByAccessor(nil, args.TokenID)
   484  	if err != nil {
   485  		return err
   486  	}
   487  
   488  	if token != nil {
   489  		if args.Token == token.SecretID {
   490  			return fmt.Errorf("Deletion of the request's authorization token is not permitted")
   491  		}
   492  
   493  		if !a.srv.InACLDatacenter() && !token.Local {
   494  			args.Datacenter = a.srv.config.ACLDatacenter
   495  			return a.srv.forwardDC("ACL.TokenDelete", a.srv.config.ACLDatacenter, args, reply)
   496  		}
   497  	}
   498  
   499  	req := &structs.ACLTokenBatchDeleteRequest{
   500  		TokenIDs: []string{args.TokenID},
   501  	}
   502  
   503  	resp, err := a.srv.raftApply(structs.ACLTokenDeleteRequestType, req)
   504  	if err != nil {
   505  		return fmt.Errorf("Failed to apply token delete request: %v", err)
   506  	}
   507  
   508  	// Purge the identity from the cache to prevent using the previous definition of the identity
   509  	if token != nil {
   510  		a.srv.acls.cache.RemoveIdentity(token.SecretID)
   511  	}
   512  
   513  	if respErr, ok := resp.(error); ok {
   514  		return respErr
   515  	}
   516  
   517  	if reply != nil && token != nil {
   518  		*reply = token.AccessorID
   519  	}
   520  
   521  	return nil
   522  }
   523  
   524  func (a *ACL) TokenList(args *structs.ACLTokenListRequest, reply *structs.ACLTokenListResponse) error {
   525  	if err := a.aclPreCheck(); err != nil {
   526  		return err
   527  	}
   528  
   529  	if !a.srv.LocalTokensEnabled() {
   530  		if args.Datacenter != a.srv.config.ACLDatacenter {
   531  			args.Datacenter = a.srv.config.ACLDatacenter
   532  			args.IncludeLocal = false
   533  			args.IncludeGlobal = true
   534  		}
   535  		args.Datacenter = a.srv.config.ACLDatacenter
   536  	}
   537  
   538  	if done, err := a.srv.forward("ACL.TokenList", args, args, reply); done {
   539  		return err
   540  	}
   541  
   542  	rule, err := a.srv.ResolveToken(args.Token)
   543  	if err != nil {
   544  		return err
   545  	} else if rule == nil || !rule.ACLRead() {
   546  		return acl.ErrPermissionDenied
   547  	}
   548  
   549  	return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
   550  		func(ws memdb.WatchSet, state *state.Store) error {
   551  			index, tokens, err := state.ACLTokenList(ws, args.IncludeLocal, args.IncludeGlobal, args.Policy)
   552  			if err != nil {
   553  				return err
   554  			}
   555  
   556  			stubs := make([]*structs.ACLTokenListStub, 0, len(tokens))
   557  			for _, token := range tokens {
   558  				stubs = append(stubs, token.Stub())
   559  			}
   560  			reply.Index, reply.Tokens = index, stubs
   561  			return nil
   562  		})
   563  }
   564  
   565  func (a *ACL) TokenBatchRead(args *structs.ACLTokenBatchGetRequest, reply *structs.ACLTokenBatchResponse) error {
   566  	if err := a.aclPreCheck(); err != nil {
   567  		return err
   568  	}
   569  
   570  	if !a.srv.LocalTokensEnabled() {
   571  		args.Datacenter = a.srv.config.ACLDatacenter
   572  	}
   573  
   574  	if done, err := a.srv.forward("ACL.TokenBatchRead", args, args, reply); done {
   575  		return err
   576  	}
   577  
   578  	rule, err := a.srv.ResolveToken(args.Token)
   579  	if err != nil {
   580  		return err
   581  	} else if rule == nil || !rule.ACLRead() {
   582  		return acl.ErrPermissionDenied
   583  	}
   584  
   585  	return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
   586  		func(ws memdb.WatchSet, state *state.Store) error {
   587  			index, tokens, err := state.ACLTokenBatchGet(ws, args.AccessorIDs)
   588  			if err != nil {
   589  				return err
   590  			}
   591  
   592  			a.srv.filterACLWithAuthorizer(rule, &tokens)
   593  
   594  			reply.Index, reply.Tokens = index, tokens
   595  			reply.Redacted = !rule.ACLWrite()
   596  			return nil
   597  		})
   598  }
   599  
   600  func (a *ACL) PolicyRead(args *structs.ACLPolicyGetRequest, reply *structs.ACLPolicyResponse) error {
   601  	if err := a.aclPreCheck(); err != nil {
   602  		return err
   603  	}
   604  
   605  	if done, err := a.srv.forward("ACL.PolicyRead", args, args, reply); done {
   606  		return err
   607  	}
   608  
   609  	if rule, err := a.srv.ResolveToken(args.Token); err != nil {
   610  		return err
   611  	} else if rule == nil || !rule.ACLRead() {
   612  		return acl.ErrPermissionDenied
   613  	}
   614  
   615  	return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
   616  		func(ws memdb.WatchSet, state *state.Store) error {
   617  			index, policy, err := state.ACLPolicyGetByID(ws, args.PolicyID)
   618  
   619  			if err != nil {
   620  				return err
   621  			}
   622  
   623  			reply.Index, reply.Policy = index, policy
   624  			return nil
   625  		})
   626  }
   627  
   628  func (a *ACL) PolicyBatchRead(args *structs.ACLPolicyBatchGetRequest, reply *structs.ACLPolicyBatchResponse) error {
   629  	if err := a.aclPreCheck(); err != nil {
   630  		return err
   631  	}
   632  
   633  	if done, err := a.srv.forward("ACL.PolicyBatchRead", args, args, reply); done {
   634  		return err
   635  	}
   636  
   637  	if rule, err := a.srv.ResolveToken(args.Token); err != nil {
   638  		return err
   639  	} else if rule == nil || !rule.ACLRead() {
   640  		return acl.ErrPermissionDenied
   641  	}
   642  
   643  	return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
   644  		func(ws memdb.WatchSet, state *state.Store) error {
   645  			index, policies, err := state.ACLPolicyBatchGet(ws, args.PolicyIDs)
   646  			if err != nil {
   647  				return err
   648  			}
   649  
   650  			reply.Index, reply.Policies = index, policies
   651  			return nil
   652  		})
   653  }
   654  
   655  func (a *ACL) PolicySet(args *structs.ACLPolicySetRequest, reply *structs.ACLPolicy) error {
   656  	if err := a.aclPreCheck(); err != nil {
   657  		return err
   658  	}
   659  
   660  	if !a.srv.InACLDatacenter() {
   661  		args.Datacenter = a.srv.config.ACLDatacenter
   662  	}
   663  
   664  	if done, err := a.srv.forward("ACL.PolicySet", args, args, reply); done {
   665  		return err
   666  	}
   667  
   668  	defer metrics.MeasureSince([]string{"acl", "policy", "upsert"}, time.Now())
   669  
   670  	// Verify token is permitted to modify ACLs
   671  	if rule, err := a.srv.ResolveToken(args.Token); err != nil {
   672  		return err
   673  	} else if rule == nil || !rule.ACLWrite() {
   674  		return acl.ErrPermissionDenied
   675  	}
   676  
   677  	policy := &args.Policy
   678  	state := a.srv.fsm.State()
   679  
   680  	// Almost all of the checks here are also done in the state store. However,
   681  	// we want to prevent the raft operations when we know they are going to fail
   682  	// so we still do them here.
   683  
   684  	// ensure a name is set
   685  	if policy.Name == "" {
   686  		return fmt.Errorf("Invalid Policy: no Name is set")
   687  	}
   688  
   689  	if !validPolicyName.MatchString(policy.Name) {
   690  		return fmt.Errorf("Invalid Policy: invalid Name. Only alphanumeric characters, '-' and '_' are allowed")
   691  	}
   692  
   693  	if policy.ID == "" {
   694  		// with no policy ID one will be generated
   695  		var err error
   696  
   697  		policy.ID, err = lib.GenerateUUID(a.srv.checkPolicyUUID)
   698  		if err != nil {
   699  			return err
   700  		}
   701  
   702  		// validate the name is unique
   703  		if _, existing, err := state.ACLPolicyGetByName(nil, policy.Name); err != nil {
   704  			return fmt.Errorf("acl policy lookup by name failed: %v", err)
   705  		} else if existing != nil {
   706  			return fmt.Errorf("Invalid Policy: A Policy with Name %q already exists", policy.Name)
   707  		}
   708  	} else {
   709  		if _, err := uuid.ParseUUID(policy.ID); err != nil {
   710  			return fmt.Errorf("Policy ID invalid UUID")
   711  		}
   712  
   713  		// Verify the policy exists
   714  		_, existing, err := state.ACLPolicyGetByID(nil, policy.ID)
   715  		if err != nil {
   716  			return fmt.Errorf("acl policy lookup failed: %v", err)
   717  		} else if existing == nil {
   718  			return fmt.Errorf("cannot find policy %s", policy.ID)
   719  		}
   720  
   721  		if existing.Name != policy.Name {
   722  			if _, nameMatch, err := state.ACLPolicyGetByName(nil, policy.Name); err != nil {
   723  				return fmt.Errorf("acl policy lookup by name failed: %v", err)
   724  			} else if nameMatch != nil {
   725  				return fmt.Errorf("Invalid Policy: A policy with name %q already exists", policy.Name)
   726  			}
   727  		}
   728  
   729  		if policy.ID == structs.ACLPolicyGlobalManagementID {
   730  			if policy.Datacenters != nil || len(policy.Datacenters) > 0 {
   731  				return fmt.Errorf("Changing the Datacenters of the builtin global-management policy is not permitted")
   732  			}
   733  
   734  			if policy.Rules != existing.Rules {
   735  				return fmt.Errorf("Changing the Rules for the builtin global-management policy is not permitted")
   736  			}
   737  		}
   738  	}
   739  
   740  	// validate the rules
   741  	_, err := acl.NewPolicyFromSource("", 0, policy.Rules, policy.Syntax, a.srv.sentinel)
   742  	if err != nil {
   743  		return err
   744  	}
   745  
   746  	// calculate the hash for this policy
   747  	policy.SetHash(true)
   748  
   749  	req := &structs.ACLPolicyBatchSetRequest{
   750  		Policies: structs.ACLPolicies{policy},
   751  	}
   752  
   753  	resp, err := a.srv.raftApply(structs.ACLPolicySetRequestType, req)
   754  	if err != nil {
   755  		return fmt.Errorf("Failed to apply policy upsert request: %v", err)
   756  	}
   757  
   758  	// Remove from the cache to prevent stale cache usage
   759  	a.srv.acls.cache.RemovePolicy(policy.ID)
   760  
   761  	if respErr, ok := resp.(error); ok {
   762  		return respErr
   763  	}
   764  
   765  	if _, policy, err := a.srv.fsm.State().ACLPolicyGetByID(nil, policy.ID); err == nil && policy != nil {
   766  		*reply = *policy
   767  	}
   768  
   769  	return nil
   770  }
   771  
   772  func (a *ACL) PolicyDelete(args *structs.ACLPolicyDeleteRequest, reply *string) error {
   773  	if err := a.aclPreCheck(); err != nil {
   774  		return err
   775  	}
   776  
   777  	if !a.srv.InACLDatacenter() {
   778  		args.Datacenter = a.srv.config.ACLDatacenter
   779  	}
   780  
   781  	if done, err := a.srv.forward("ACL.PolicyDelete", args, args, reply); done {
   782  		return err
   783  	}
   784  
   785  	defer metrics.MeasureSince([]string{"acl", "policy", "delete"}, time.Now())
   786  
   787  	// Verify token is permitted to modify ACLs
   788  	if rule, err := a.srv.ResolveToken(args.Token); err != nil {
   789  		return err
   790  	} else if rule == nil || !rule.ACLWrite() {
   791  		return acl.ErrPermissionDenied
   792  	}
   793  
   794  	_, policy, err := a.srv.fsm.State().ACLPolicyGetByID(nil, args.PolicyID)
   795  	if err != nil {
   796  		return err
   797  	}
   798  
   799  	if policy == nil {
   800  		return nil
   801  	}
   802  
   803  	if policy.ID == structs.ACLPolicyGlobalManagementID {
   804  		return fmt.Errorf("Delete operation not permitted on the builtin global-management policy")
   805  	}
   806  
   807  	req := structs.ACLPolicyBatchDeleteRequest{
   808  		PolicyIDs: []string{args.PolicyID},
   809  	}
   810  
   811  	resp, err := a.srv.raftApply(structs.ACLPolicyDeleteRequestType, &req)
   812  	if err != nil {
   813  		return fmt.Errorf("Failed to apply policy delete request: %v", err)
   814  	}
   815  
   816  	a.srv.acls.cache.RemovePolicy(policy.ID)
   817  
   818  	if respErr, ok := resp.(error); ok {
   819  		return respErr
   820  	}
   821  
   822  	if policy != nil {
   823  		*reply = policy.Name
   824  	}
   825  
   826  	return nil
   827  }
   828  
   829  func (a *ACL) PolicyList(args *structs.ACLPolicyListRequest, reply *structs.ACLPolicyListResponse) error {
   830  	if err := a.aclPreCheck(); err != nil {
   831  		return err
   832  	}
   833  
   834  	if done, err := a.srv.forward("ACL.PolicyList", args, args, reply); done {
   835  		return err
   836  	}
   837  
   838  	if rule, err := a.srv.ResolveToken(args.Token); err != nil {
   839  		return err
   840  	} else if rule == nil || !rule.ACLRead() {
   841  		return acl.ErrPermissionDenied
   842  	}
   843  
   844  	return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
   845  		func(ws memdb.WatchSet, state *state.Store) error {
   846  			index, policies, err := state.ACLPolicyList(ws)
   847  			if err != nil {
   848  				return err
   849  			}
   850  
   851  			var stubs structs.ACLPolicyListStubs
   852  			for _, policy := range policies {
   853  				stubs = append(stubs, policy.Stub())
   854  			}
   855  
   856  			reply.Index, reply.Policies = index, stubs
   857  			return nil
   858  		})
   859  }
   860  
   861  // PolicyResolve is used to retrieve a subset of the policies associated with a given token
   862  // The policy ids in the args simply act as a filter on the policy set assigned to the token
   863  func (a *ACL) PolicyResolve(args *structs.ACLPolicyBatchGetRequest, reply *structs.ACLPolicyBatchResponse) error {
   864  	if err := a.aclPreCheck(); err != nil {
   865  		return err
   866  	}
   867  
   868  	if done, err := a.srv.forward("ACL.PolicyResolve", args, args, reply); done {
   869  		return err
   870  	}
   871  
   872  	// get full list of policies for this token
   873  	identity, policies, err := a.srv.acls.resolveTokenToIdentityAndPolicies(args.Token)
   874  	if err != nil {
   875  		return err
   876  	}
   877  
   878  	idMap := make(map[string]*structs.ACLPolicy)
   879  	for _, policyID := range identity.PolicyIDs() {
   880  		idMap[policyID] = nil
   881  	}
   882  	for _, policy := range policies {
   883  		idMap[policy.ID] = policy
   884  	}
   885  
   886  	for _, policyID := range args.PolicyIDs {
   887  		if policy, ok := idMap[policyID]; ok {
   888  			// only add non-deleted policies
   889  			if policy != nil {
   890  				reply.Policies = append(reply.Policies, policy)
   891  			}
   892  		} else {
   893  			// send a permission denied to indicate that the request included
   894  			// policy ids not associated with this token
   895  			return acl.ErrPermissionDenied
   896  		}
   897  	}
   898  
   899  	a.srv.setQueryMeta(&reply.QueryMeta)
   900  
   901  	return nil
   902  }
   903  
   904  // makeACLETag returns an ETag for the given parent and policy.
   905  func makeACLETag(parent string, policy *acl.Policy) string {
   906  	return fmt.Sprintf("%s:%s", parent, policy.ID)
   907  }
   908  
   909  // GetPolicy is used to retrieve a compiled policy object with a TTL. Does not
   910  // support a blocking query.
   911  func (a *ACL) GetPolicy(args *structs.ACLPolicyResolveLegacyRequest, reply *structs.ACLPolicyResolveLegacyResponse) error {
   912  	if done, err := a.srv.forward("ACL.GetPolicy", args, args, reply); done {
   913  		return err
   914  	}
   915  
   916  	// Verify we are allowed to serve this request
   917  	if a.srv.config.ACLDatacenter != a.srv.config.Datacenter {
   918  		return acl.ErrDisabled
   919  	}
   920  
   921  	// Get the policy via the cache
   922  	parent := a.srv.config.ACLDefaultPolicy
   923  
   924  	policy, err := a.srv.acls.GetMergedPolicyForToken(args.ACL)
   925  	if err != nil {
   926  		return err
   927  	}
   928  
   929  	// translates the structures internals to most closely match what could be expressed in the original rule language
   930  	policy = policy.ConvertToLegacy()
   931  
   932  	// Generate an ETag
   933  	etag := makeACLETag(parent, policy)
   934  
   935  	// Setup the response
   936  	reply.ETag = etag
   937  	reply.TTL = a.srv.config.ACLTokenTTL
   938  	a.srv.setQueryMeta(&reply.QueryMeta)
   939  
   940  	// Only send the policy on an Etag mis-match
   941  	if args.ETag != etag {
   942  		reply.Parent = parent
   943  		reply.Policy = policy
   944  	}
   945  	return nil
   946  }
   947  
   948  // ReplicationStatus is used to retrieve the current ACL replication status.
   949  func (a *ACL) ReplicationStatus(args *structs.DCSpecificRequest,
   950  	reply *structs.ACLReplicationStatus) error {
   951  	// This must be sent to the leader, so we fix the args since we are
   952  	// re-using a structure where we don't support all the options.
   953  	args.RequireConsistent = true
   954  	args.AllowStale = false
   955  	if done, err := a.srv.forward("ACL.ReplicationStatus", args, args, reply); done {
   956  		return err
   957  	}
   958  
   959  	// There's no ACL token required here since this doesn't leak any
   960  	// sensitive information, and we don't want people to have to use
   961  	// management tokens if they are querying this via a health check.
   962  
   963  	// Poll the latest status.
   964  	a.srv.aclReplicationStatusLock.RLock()
   965  	*reply = a.srv.aclReplicationStatus
   966  	a.srv.aclReplicationStatusLock.RUnlock()
   967  	return nil
   968  }