github.com/hashicorp/nomad/api@v0.0.0-20240306165712-3193ac204f65/acl.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package api
     5  
     6  import (
     7  	"encoding/json"
     8  	"errors"
     9  	"fmt"
    10  	"time"
    11  )
    12  
    13  // ACLPolicies is used to query the ACL Policy endpoints.
    14  type ACLPolicies struct {
    15  	client *Client
    16  }
    17  
    18  // ACLPolicies returns a new handle on the ACL policies.
    19  func (c *Client) ACLPolicies() *ACLPolicies {
    20  	return &ACLPolicies{client: c}
    21  }
    22  
    23  // List is used to dump all of the policies.
    24  func (a *ACLPolicies) List(q *QueryOptions) ([]*ACLPolicyListStub, *QueryMeta, error) {
    25  	var resp []*ACLPolicyListStub
    26  	qm, err := a.client.query("/v1/acl/policies", &resp, q)
    27  	if err != nil {
    28  		return nil, nil, err
    29  	}
    30  	return resp, qm, nil
    31  }
    32  
    33  // Upsert is used to create or update a policy
    34  func (a *ACLPolicies) Upsert(policy *ACLPolicy, q *WriteOptions) (*WriteMeta, error) {
    35  	if policy == nil || policy.Name == "" {
    36  		return nil, errors.New("missing policy name")
    37  	}
    38  	wm, err := a.client.put("/v1/acl/policy/"+policy.Name, policy, nil, q)
    39  	if err != nil {
    40  		return nil, err
    41  	}
    42  	return wm, nil
    43  }
    44  
    45  // Delete is used to delete a policy
    46  func (a *ACLPolicies) Delete(policyName string, q *WriteOptions) (*WriteMeta, error) {
    47  	if policyName == "" {
    48  		return nil, errors.New("missing policy name")
    49  	}
    50  	wm, err := a.client.delete("/v1/acl/policy/"+policyName, nil, nil, q)
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  	return wm, nil
    55  }
    56  
    57  // Info is used to query a specific policy
    58  func (a *ACLPolicies) Info(policyName string, q *QueryOptions) (*ACLPolicy, *QueryMeta, error) {
    59  	if policyName == "" {
    60  		return nil, nil, errors.New("missing policy name")
    61  	}
    62  	var resp ACLPolicy
    63  	wm, err := a.client.query("/v1/acl/policy/"+policyName, &resp, q)
    64  	if err != nil {
    65  		return nil, nil, err
    66  	}
    67  	return &resp, wm, nil
    68  }
    69  
    70  // ACLTokens is used to query the ACL token endpoints.
    71  type ACLTokens struct {
    72  	client *Client
    73  }
    74  
    75  // ACLTokens returns a new handle on the ACL tokens.
    76  func (c *Client) ACLTokens() *ACLTokens {
    77  	return &ACLTokens{client: c}
    78  }
    79  
    80  // Bootstrap is used to get the initial bootstrap token
    81  //
    82  // See BootstrapOpts to set ACL bootstrapping options.
    83  func (a *ACLTokens) Bootstrap(q *WriteOptions) (*ACLToken, *WriteMeta, error) {
    84  	var resp ACLToken
    85  	wm, err := a.client.put("/v1/acl/bootstrap", nil, &resp, q)
    86  	if err != nil {
    87  		return nil, nil, err
    88  	}
    89  	return &resp, wm, nil
    90  }
    91  
    92  // BootstrapOpts is used to get the initial bootstrap token or pass in the one that was provided in the API
    93  func (a *ACLTokens) BootstrapOpts(btoken string, q *WriteOptions) (*ACLToken, *WriteMeta, error) {
    94  	if q == nil {
    95  		q = &WriteOptions{}
    96  	}
    97  	req := &BootstrapRequest{
    98  		BootstrapSecret: btoken,
    99  	}
   100  
   101  	var resp ACLToken
   102  	wm, err := a.client.put("/v1/acl/bootstrap", req, &resp, q)
   103  	if err != nil {
   104  		return nil, nil, err
   105  	}
   106  	return &resp, wm, nil
   107  }
   108  
   109  // List is used to dump all of the tokens.
   110  func (a *ACLTokens) List(q *QueryOptions) ([]*ACLTokenListStub, *QueryMeta, error) {
   111  	var resp []*ACLTokenListStub
   112  	qm, err := a.client.query("/v1/acl/tokens", &resp, q)
   113  	if err != nil {
   114  		return nil, nil, err
   115  	}
   116  	return resp, qm, nil
   117  }
   118  
   119  // Create is used to create a token
   120  func (a *ACLTokens) Create(token *ACLToken, q *WriteOptions) (*ACLToken, *WriteMeta, error) {
   121  	if token.AccessorID != "" {
   122  		return nil, nil, errors.New("cannot specify Accessor ID")
   123  	}
   124  	var resp ACLToken
   125  	wm, err := a.client.put("/v1/acl/token", token, &resp, q)
   126  	if err != nil {
   127  		return nil, nil, err
   128  	}
   129  	return &resp, wm, nil
   130  }
   131  
   132  // Update is used to update an existing token
   133  func (a *ACLTokens) Update(token *ACLToken, q *WriteOptions) (*ACLToken, *WriteMeta, error) {
   134  	if token.AccessorID == "" {
   135  		return nil, nil, errors.New("missing accessor ID")
   136  	}
   137  	var resp ACLToken
   138  	wm, err := a.client.put("/v1/acl/token/"+token.AccessorID,
   139  		token, &resp, q)
   140  	if err != nil {
   141  		return nil, nil, err
   142  	}
   143  	return &resp, wm, nil
   144  }
   145  
   146  // Delete is used to delete a token
   147  func (a *ACLTokens) Delete(accessorID string, q *WriteOptions) (*WriteMeta, error) {
   148  	if accessorID == "" {
   149  		return nil, errors.New("missing accessor ID")
   150  	}
   151  	wm, err := a.client.delete("/v1/acl/token/"+accessorID, nil, nil, q)
   152  	if err != nil {
   153  		return nil, err
   154  	}
   155  	return wm, nil
   156  }
   157  
   158  // Info is used to query a token
   159  func (a *ACLTokens) Info(accessorID string, q *QueryOptions) (*ACLToken, *QueryMeta, error) {
   160  	if accessorID == "" {
   161  		return nil, nil, errors.New("missing accessor ID")
   162  	}
   163  	var resp ACLToken
   164  	wm, err := a.client.query("/v1/acl/token/"+accessorID, &resp, q)
   165  	if err != nil {
   166  		return nil, nil, err
   167  	}
   168  	return &resp, wm, nil
   169  }
   170  
   171  // Self is used to query our own token
   172  func (a *ACLTokens) Self(q *QueryOptions) (*ACLToken, *QueryMeta, error) {
   173  	var resp ACLToken
   174  	wm, err := a.client.query("/v1/acl/token/self", &resp, q)
   175  	if err != nil {
   176  		return nil, nil, err
   177  	}
   178  	return &resp, wm, nil
   179  }
   180  
   181  // UpsertOneTimeToken is used to create a one-time token
   182  func (a *ACLTokens) UpsertOneTimeToken(q *WriteOptions) (*OneTimeToken, *WriteMeta, error) {
   183  	var resp *OneTimeTokenUpsertResponse
   184  	wm, err := a.client.put("/v1/acl/token/onetime", nil, &resp, q)
   185  	if err != nil {
   186  		return nil, nil, err
   187  	}
   188  	if resp == nil {
   189  		return nil, nil, errors.New("no one-time token returned")
   190  	}
   191  	return resp.OneTimeToken, wm, nil
   192  }
   193  
   194  // ExchangeOneTimeToken is used to create a one-time token
   195  func (a *ACLTokens) ExchangeOneTimeToken(secret string, q *WriteOptions) (*ACLToken, *WriteMeta, error) {
   196  	if secret == "" {
   197  		return nil, nil, errors.New("missing secret ID")
   198  	}
   199  	req := &OneTimeTokenExchangeRequest{OneTimeSecretID: secret}
   200  	var resp *OneTimeTokenExchangeResponse
   201  	wm, err := a.client.put("/v1/acl/token/onetime/exchange", req, &resp, q)
   202  	if err != nil {
   203  		return nil, nil, err
   204  	}
   205  	if resp == nil {
   206  		return nil, nil, errors.New("no ACL token returned")
   207  	}
   208  	return resp.Token, wm, nil
   209  }
   210  
   211  var (
   212  	// errMissingACLRoleID is the generic errors to use when a call is missing
   213  	// the required ACL Role ID parameter.
   214  	errMissingACLRoleID = errors.New("missing ACL role ID")
   215  
   216  	// errMissingACLAuthMethodName is the generic error to use when a call is
   217  	// missing the required ACL auth-method name parameter.
   218  	errMissingACLAuthMethodName = errors.New("missing ACL auth-method name")
   219  
   220  	// errMissingACLBindingRuleID is the generic error to use when a call is
   221  	// missing the required ACL binding rule ID parameter.
   222  	errMissingACLBindingRuleID = errors.New("missing ACL binding rule ID")
   223  )
   224  
   225  // ACLRoles is used to query the ACL Role endpoints.
   226  type ACLRoles struct {
   227  	client *Client
   228  }
   229  
   230  // ACLRoles returns a new handle on the ACL roles API client.
   231  func (c *Client) ACLRoles() *ACLRoles {
   232  	return &ACLRoles{client: c}
   233  }
   234  
   235  // List is used to detail all the ACL roles currently stored within state.
   236  func (a *ACLRoles) List(q *QueryOptions) ([]*ACLRoleListStub, *QueryMeta, error) {
   237  	var resp []*ACLRoleListStub
   238  	qm, err := a.client.query("/v1/acl/roles", &resp, q)
   239  	if err != nil {
   240  		return nil, nil, err
   241  	}
   242  	return resp, qm, nil
   243  }
   244  
   245  // Create is used to create an ACL role.
   246  func (a *ACLRoles) Create(role *ACLRole, w *WriteOptions) (*ACLRole, *WriteMeta, error) {
   247  	if role.ID != "" {
   248  		return nil, nil, errors.New("cannot specify ACL role ID")
   249  	}
   250  	var resp ACLRole
   251  	wm, err := a.client.put("/v1/acl/role", role, &resp, w)
   252  	if err != nil {
   253  		return nil, nil, err
   254  	}
   255  	return &resp, wm, nil
   256  }
   257  
   258  // Update is used to update an existing ACL role.
   259  func (a *ACLRoles) Update(role *ACLRole, w *WriteOptions) (*ACLRole, *WriteMeta, error) {
   260  	if role.ID == "" {
   261  		return nil, nil, errMissingACLRoleID
   262  	}
   263  	var resp ACLRole
   264  	wm, err := a.client.put("/v1/acl/role/"+role.ID, role, &resp, w)
   265  	if err != nil {
   266  		return nil, nil, err
   267  	}
   268  	return &resp, wm, nil
   269  }
   270  
   271  // Delete is used to delete an ACL role.
   272  func (a *ACLRoles) Delete(roleID string, w *WriteOptions) (*WriteMeta, error) {
   273  	if roleID == "" {
   274  		return nil, errMissingACLRoleID
   275  	}
   276  	wm, err := a.client.delete("/v1/acl/role/"+roleID, nil, nil, w)
   277  	if err != nil {
   278  		return nil, err
   279  	}
   280  	return wm, nil
   281  }
   282  
   283  // Get is used to look up an ACL role.
   284  func (a *ACLRoles) Get(roleID string, q *QueryOptions) (*ACLRole, *QueryMeta, error) {
   285  	if roleID == "" {
   286  		return nil, nil, errMissingACLRoleID
   287  	}
   288  	var resp ACLRole
   289  	qm, err := a.client.query("/v1/acl/role/"+roleID, &resp, q)
   290  	if err != nil {
   291  		return nil, nil, err
   292  	}
   293  	return &resp, qm, nil
   294  }
   295  
   296  // GetByName is used to look up an ACL role using its name.
   297  func (a *ACLRoles) GetByName(roleName string, q *QueryOptions) (*ACLRole, *QueryMeta, error) {
   298  	if roleName == "" {
   299  		return nil, nil, errors.New("missing ACL role name")
   300  	}
   301  	var resp ACLRole
   302  	qm, err := a.client.query("/v1/acl/role/name/"+roleName, &resp, q)
   303  	if err != nil {
   304  		return nil, nil, err
   305  	}
   306  	return &resp, qm, nil
   307  }
   308  
   309  // ACLAuthMethods is used to query the ACL auth-methods endpoints.
   310  type ACLAuthMethods struct {
   311  	client *Client
   312  }
   313  
   314  // ACLAuthMethods returns a new handle on the ACL auth-methods API client.
   315  func (c *Client) ACLAuthMethods() *ACLAuthMethods {
   316  	return &ACLAuthMethods{client: c}
   317  }
   318  
   319  // List is used to detail all the ACL auth-methods currently stored within
   320  // state.
   321  func (a *ACLAuthMethods) List(q *QueryOptions) ([]*ACLAuthMethodListStub, *QueryMeta, error) {
   322  	var resp []*ACLAuthMethodListStub
   323  	qm, err := a.client.query("/v1/acl/auth-methods", &resp, q)
   324  	if err != nil {
   325  		return nil, nil, err
   326  	}
   327  	return resp, qm, nil
   328  }
   329  
   330  // Create is used to create an ACL auth-method.
   331  func (a *ACLAuthMethods) Create(authMethod *ACLAuthMethod, w *WriteOptions) (*ACLAuthMethod, *WriteMeta, error) {
   332  	if authMethod.Name == "" {
   333  		return nil, nil, errMissingACLAuthMethodName
   334  	}
   335  	var resp ACLAuthMethod
   336  	wm, err := a.client.put("/v1/acl/auth-method", authMethod, &resp, w)
   337  	if err != nil {
   338  		return nil, nil, err
   339  	}
   340  	return &resp, wm, nil
   341  }
   342  
   343  // Update is used to update an existing ACL auth-method.
   344  func (a *ACLAuthMethods) Update(authMethod *ACLAuthMethod, w *WriteOptions) (*ACLAuthMethod, *WriteMeta, error) {
   345  	if authMethod.Name == "" {
   346  		return nil, nil, errMissingACLAuthMethodName
   347  	}
   348  	var resp ACLAuthMethod
   349  	wm, err := a.client.put("/v1/acl/auth-method/"+authMethod.Name, authMethod, &resp, w)
   350  	if err != nil {
   351  		return nil, nil, err
   352  	}
   353  	return &resp, wm, nil
   354  }
   355  
   356  // Delete is used to delete an ACL auth-method.
   357  func (a *ACLAuthMethods) Delete(authMethodName string, w *WriteOptions) (*WriteMeta, error) {
   358  	if authMethodName == "" {
   359  		return nil, errMissingACLAuthMethodName
   360  	}
   361  	wm, err := a.client.delete("/v1/acl/auth-method/"+authMethodName, nil, nil, w)
   362  	if err != nil {
   363  		return nil, err
   364  	}
   365  	return wm, nil
   366  }
   367  
   368  // Get is used to look up an ACL auth-method.
   369  func (a *ACLAuthMethods) Get(authMethodName string, q *QueryOptions) (*ACLAuthMethod, *QueryMeta, error) {
   370  	if authMethodName == "" {
   371  		return nil, nil, errMissingACLAuthMethodName
   372  	}
   373  	var resp ACLAuthMethod
   374  	qm, err := a.client.query("/v1/acl/auth-method/"+authMethodName, &resp, q)
   375  	if err != nil {
   376  		return nil, nil, err
   377  	}
   378  	return &resp, qm, nil
   379  }
   380  
   381  // ACLBindingRules is used to query the ACL auth-methods endpoints.
   382  type ACLBindingRules struct {
   383  	client *Client
   384  }
   385  
   386  // ACLBindingRules returns a new handle on the ACL auth-methods API client.
   387  func (c *Client) ACLBindingRules() *ACLBindingRules {
   388  	return &ACLBindingRules{client: c}
   389  }
   390  
   391  // List is used to detail all the ACL binding rules currently stored within
   392  // state.
   393  func (a *ACLBindingRules) List(q *QueryOptions) ([]*ACLBindingRuleListStub, *QueryMeta, error) {
   394  	var resp []*ACLBindingRuleListStub
   395  	qm, err := a.client.query("/v1/acl/binding-rules", &resp, q)
   396  	if err != nil {
   397  		return nil, nil, err
   398  	}
   399  	return resp, qm, nil
   400  }
   401  
   402  // Create is used to create an ACL binding rule.
   403  func (a *ACLBindingRules) Create(bindingRule *ACLBindingRule, w *WriteOptions) (*ACLBindingRule, *WriteMeta, error) {
   404  	var resp ACLBindingRule
   405  	wm, err := a.client.put("/v1/acl/binding-rule", bindingRule, &resp, w)
   406  	if err != nil {
   407  		return nil, nil, err
   408  	}
   409  	return &resp, wm, nil
   410  }
   411  
   412  // Update is used to update an existing ACL binding rule.
   413  func (a *ACLBindingRules) Update(bindingRule *ACLBindingRule, w *WriteOptions) (*ACLBindingRule, *WriteMeta, error) {
   414  	if bindingRule.ID == "" {
   415  		return nil, nil, errMissingACLBindingRuleID
   416  	}
   417  	var resp ACLBindingRule
   418  	wm, err := a.client.put("/v1/acl/binding-rule/"+bindingRule.ID, bindingRule, &resp, w)
   419  	if err != nil {
   420  		return nil, nil, err
   421  	}
   422  	return &resp, wm, nil
   423  }
   424  
   425  // Delete is used to delete an ACL binding rule.
   426  func (a *ACLBindingRules) Delete(bindingRuleID string, w *WriteOptions) (*WriteMeta, error) {
   427  	if bindingRuleID == "" {
   428  		return nil, errMissingACLBindingRuleID
   429  	}
   430  	wm, err := a.client.delete("/v1/acl/binding-rule/"+bindingRuleID, nil, nil, w)
   431  	if err != nil {
   432  		return nil, err
   433  	}
   434  	return wm, nil
   435  }
   436  
   437  // Get is used to look up an ACL binding rule.
   438  func (a *ACLBindingRules) Get(bindingRuleID string, q *QueryOptions) (*ACLBindingRule, *QueryMeta, error) {
   439  	if bindingRuleID == "" {
   440  		return nil, nil, errMissingACLBindingRuleID
   441  	}
   442  	var resp ACLBindingRule
   443  	qm, err := a.client.query("/v1/acl/binding-rule/"+bindingRuleID, &resp, q)
   444  	if err != nil {
   445  		return nil, nil, err
   446  	}
   447  	return &resp, qm, nil
   448  }
   449  
   450  // ACLOIDC is used to query the ACL OIDC endpoints.
   451  //
   452  // Deprecated: ACLOIDC is deprecated, use ACLAuth instead.
   453  type ACLOIDC struct {
   454  	client *Client
   455  	ACLAuth
   456  }
   457  
   458  // ACLOIDC returns a new handle on the ACL auth-methods API client.
   459  //
   460  // Deprecated: c.ACLOIDC() is deprecated, use c.ACLAuth() instead.
   461  func (c *Client) ACLOIDC() *ACLOIDC {
   462  	return &ACLOIDC{client: c}
   463  }
   464  
   465  // ACLAuth is used to query the ACL auth endpoints.
   466  type ACLAuth struct {
   467  	client *Client
   468  }
   469  
   470  // ACLAuth returns a new handle on the ACL auth-methods API client.
   471  func (c *Client) ACLAuth() *ACLAuth {
   472  	return &ACLAuth{client: c}
   473  }
   474  
   475  // GetAuthURL generates the OIDC provider authentication URL. This URL should
   476  // be visited in order to sign in to the provider.
   477  func (a *ACLAuth) GetAuthURL(req *ACLOIDCAuthURLRequest, q *WriteOptions) (*ACLOIDCAuthURLResponse, *WriteMeta, error) {
   478  	var resp ACLOIDCAuthURLResponse
   479  	wm, err := a.client.put("/v1/acl/oidc/auth-url", req, &resp, q)
   480  	if err != nil {
   481  		return nil, nil, err
   482  	}
   483  	return &resp, wm, nil
   484  }
   485  
   486  // CompleteAuth exchanges the OIDC provider token for a Nomad token with the
   487  // appropriate claims attached.
   488  func (a *ACLAuth) CompleteAuth(req *ACLOIDCCompleteAuthRequest, q *WriteOptions) (*ACLToken, *WriteMeta, error) {
   489  	var resp ACLToken
   490  	wm, err := a.client.put("/v1/acl/oidc/complete-auth", req, &resp, q)
   491  	if err != nil {
   492  		return nil, nil, err
   493  	}
   494  	return &resp, wm, nil
   495  }
   496  
   497  // Login exchanges the third party token for a Nomad token with the appropriate
   498  // claims attached.
   499  func (a *ACLAuth) Login(req *ACLLoginRequest, q *WriteOptions) (*ACLToken, *WriteMeta, error) {
   500  	var resp ACLToken
   501  	wm, err := a.client.put("/v1/acl/login", req, &resp, q)
   502  	if err != nil {
   503  		return nil, nil, err
   504  	}
   505  	return &resp, wm, nil
   506  }
   507  
   508  // ACLPolicyListStub is used to for listing ACL policies
   509  type ACLPolicyListStub struct {
   510  	Name        string
   511  	Description string
   512  	CreateIndex uint64
   513  	ModifyIndex uint64
   514  }
   515  
   516  // ACLPolicy is used to represent an ACL policy
   517  type ACLPolicy struct {
   518  	Name        string
   519  	Description string
   520  	Rules       string
   521  	JobACL      *JobACL
   522  
   523  	CreateIndex uint64
   524  	ModifyIndex uint64
   525  }
   526  
   527  // JobACL represents an ACL policy's attachment to a job, group, or task.
   528  type JobACL struct {
   529  	Namespace string
   530  	JobID     string
   531  	Group     string
   532  	Task      string
   533  }
   534  
   535  // ACLToken represents a client token which is used to Authenticate
   536  type ACLToken struct {
   537  	AccessorID string
   538  	SecretID   string
   539  	Name       string
   540  	Type       string
   541  	Policies   []string
   542  
   543  	// Roles represents the ACL roles that this token is tied to. The token
   544  	// will inherit the permissions of all policies detailed within the role.
   545  	Roles []*ACLTokenRoleLink
   546  
   547  	Global     bool
   548  	CreateTime time.Time
   549  
   550  	// ExpirationTime represents the point after which a token should be
   551  	// considered revoked and is eligible for destruction. The zero value of
   552  	// time.Time does not respect json omitempty directives, so we must use a
   553  	// pointer.
   554  	ExpirationTime *time.Time `json:",omitempty"`
   555  
   556  	// ExpirationTTL is a convenience field for helping set ExpirationTime to a
   557  	// value of CreateTime+ExpirationTTL. This can only be set during token
   558  	// creation. This is a string version of a time.Duration like "2m".
   559  	ExpirationTTL time.Duration `json:",omitempty"`
   560  
   561  	CreateIndex uint64
   562  	ModifyIndex uint64
   563  }
   564  
   565  // ACLTokenRoleLink is used to link an ACL token to an ACL role. The ACL token
   566  // can therefore inherit all the ACL policy permissions that the ACL role
   567  // contains.
   568  type ACLTokenRoleLink struct {
   569  
   570  	// ID is the ACLRole.ID UUID. This field is immutable and represents the
   571  	// absolute truth for the link.
   572  	ID string
   573  
   574  	// Name is the human friendly identifier for the ACL role and is a
   575  	// convenience field for operators.
   576  	Name string
   577  }
   578  
   579  // MarshalJSON implements the json.Marshaler interface and allows
   580  // ACLToken.ExpirationTTL to be marshaled correctly.
   581  func (a *ACLToken) MarshalJSON() ([]byte, error) {
   582  	type Alias ACLToken
   583  	exported := &struct {
   584  		ExpirationTTL string
   585  		*Alias
   586  	}{
   587  		ExpirationTTL: a.ExpirationTTL.String(),
   588  		Alias:         (*Alias)(a),
   589  	}
   590  	if a.ExpirationTTL == 0 {
   591  		exported.ExpirationTTL = ""
   592  	}
   593  	return json.Marshal(exported)
   594  }
   595  
   596  // UnmarshalJSON implements the json.Unmarshaler interface and allows
   597  // ACLToken.ExpirationTTL to be unmarshalled correctly.
   598  func (a *ACLToken) UnmarshalJSON(data []byte) (err error) {
   599  	type Alias ACLToken
   600  	aux := &struct {
   601  		ExpirationTTL any
   602  		*Alias
   603  	}{
   604  		Alias: (*Alias)(a),
   605  	}
   606  
   607  	if err = json.Unmarshal(data, &aux); err != nil {
   608  		return err
   609  	}
   610  	if aux.ExpirationTTL != nil {
   611  		switch v := aux.ExpirationTTL.(type) {
   612  		case string:
   613  			if v != "" {
   614  				if a.ExpirationTTL, err = time.ParseDuration(v); err != nil {
   615  					return err
   616  				}
   617  			}
   618  		case float64:
   619  			a.ExpirationTTL = time.Duration(v)
   620  		}
   621  
   622  	}
   623  	return nil
   624  }
   625  
   626  type ACLTokenListStub struct {
   627  	AccessorID string
   628  	Name       string
   629  	Type       string
   630  	Policies   []string
   631  	Roles      []*ACLTokenRoleLink
   632  	Global     bool
   633  	CreateTime time.Time
   634  
   635  	// ExpirationTime represents the point after which a token should be
   636  	// considered revoked and is eligible for destruction. A nil value
   637  	// indicates no expiration has been set on the token.
   638  	ExpirationTime *time.Time `json:",omitempty"`
   639  
   640  	CreateIndex uint64
   641  	ModifyIndex uint64
   642  }
   643  
   644  type OneTimeToken struct {
   645  	OneTimeSecretID string
   646  	AccessorID      string
   647  	ExpiresAt       time.Time
   648  	CreateIndex     uint64
   649  	ModifyIndex     uint64
   650  }
   651  
   652  type OneTimeTokenUpsertResponse struct {
   653  	OneTimeToken *OneTimeToken
   654  }
   655  
   656  type OneTimeTokenExchangeRequest struct {
   657  	OneTimeSecretID string
   658  }
   659  
   660  type OneTimeTokenExchangeResponse struct {
   661  	Token *ACLToken
   662  }
   663  
   664  // BootstrapRequest is used for when operators provide an ACL Bootstrap Token
   665  type BootstrapRequest struct {
   666  	BootstrapSecret string
   667  }
   668  
   669  // ACLRole is an abstraction for the ACL system which allows the grouping of
   670  // ACL policies into a single object. ACL tokens can be created and linked to
   671  // a role; the token then inherits all the permissions granted by the policies.
   672  type ACLRole struct {
   673  
   674  	// ID is an internally generated UUID for this role and is controlled by
   675  	// Nomad. It can be used after role creation to update the existing role.
   676  	ID string
   677  
   678  	// Name is unique across the entire set of federated clusters and is
   679  	// supplied by the operator on role creation. The name can be modified by
   680  	// updating the role and including the Nomad generated ID. This update will
   681  	// not affect tokens created and linked to this role. This is a required
   682  	// field.
   683  	Name string
   684  
   685  	// Description is a human-readable, operator set description that can
   686  	// provide additional context about the role. This is an optional field.
   687  	Description string
   688  
   689  	// Policies is an array of ACL policy links. Although currently policies
   690  	// can only be linked using their name, in the future we will want to add
   691  	// IDs also and thus allow operators to specify either a name, an ID, or
   692  	// both. At least one entry is required.
   693  	Policies []*ACLRolePolicyLink
   694  
   695  	CreateIndex uint64
   696  	ModifyIndex uint64
   697  }
   698  
   699  // ACLRolePolicyLink is used to link a policy to an ACL role. We use a struct
   700  // rather than a list of strings as in the future we will want to add IDs to
   701  // policies and then link via these.
   702  type ACLRolePolicyLink struct {
   703  
   704  	// Name is the ACLPolicy.Name value which will be linked to the ACL role.
   705  	Name string
   706  }
   707  
   708  // ACLRoleListStub is the stub object returned when performing a listing of ACL
   709  // roles. While it might not currently be different to the full response
   710  // object, it allows us to future-proof the RPC in the event the ACLRole object
   711  // grows over time.
   712  type ACLRoleListStub struct {
   713  
   714  	// ID is an internally generated UUID for this role and is controlled by
   715  	// Nomad.
   716  	ID string
   717  
   718  	// Name is unique across the entire set of federated clusters and is
   719  	// supplied by the operator on role creation. The name can be modified by
   720  	// updating the role and including the Nomad generated ID. This update will
   721  	// not affect tokens created and linked to this role. This is a required
   722  	// field.
   723  	Name string
   724  
   725  	// Description is a human-readable, operator set description that can
   726  	// provide additional context about the role. This is an operational field.
   727  	Description string
   728  
   729  	// Policies is an array of ACL policy links. Although currently policies
   730  	// can only be linked using their name, in the future we will want to add
   731  	// IDs also and thus allow operators to specify either a name, an ID, or
   732  	// both.
   733  	Policies []*ACLRolePolicyLink
   734  
   735  	CreateIndex uint64
   736  	ModifyIndex uint64
   737  }
   738  
   739  // ACLAuthMethod is used to capture the properties of an authentication method
   740  // used for single sing-on.
   741  type ACLAuthMethod struct {
   742  
   743  	// Name is the identifier for this auth-method and is a required parameter.
   744  	Name string
   745  
   746  	// Type is the SSO identifier this auth-method is. Nomad currently only
   747  	// supports "oidc" and the API contains ACLAuthMethodTypeOIDC for
   748  	// convenience.
   749  	Type string
   750  
   751  	// Defines whether the auth-method creates a local or global token when
   752  	// performing SSO login. This should be set to either "local" or "global"
   753  	// and the API contains ACLAuthMethodTokenLocalityLocal and
   754  	// ACLAuthMethodTokenLocalityGlobal for convenience.
   755  	TokenLocality string
   756  
   757  	// TokenNameFormat defines the HIL template to use when building the token name
   758  	TokenNameFormat string
   759  
   760  	// MaxTokenTTL is the maximum life of a token created by this method.
   761  	MaxTokenTTL time.Duration
   762  
   763  	// Default identifies whether this is the default auth-method to use when
   764  	// attempting to login without specifying an auth-method name to use.
   765  	Default bool
   766  
   767  	// Config contains the detailed configuration which is specific to the
   768  	// auth-method.
   769  	Config *ACLAuthMethodConfig
   770  
   771  	CreateTime  time.Time
   772  	ModifyTime  time.Time
   773  	CreateIndex uint64
   774  	ModifyIndex uint64
   775  }
   776  
   777  // MarshalJSON implements the json.Marshaler interface and allows
   778  // ACLAuthMethod.MaxTokenTTL to be marshaled correctly.
   779  func (m *ACLAuthMethod) MarshalJSON() ([]byte, error) {
   780  	type Alias ACLAuthMethod
   781  	exported := &struct {
   782  		MaxTokenTTL string
   783  		*Alias
   784  	}{
   785  		MaxTokenTTL: m.MaxTokenTTL.String(),
   786  		Alias:       (*Alias)(m),
   787  	}
   788  	if m.MaxTokenTTL == 0 {
   789  		exported.MaxTokenTTL = ""
   790  	}
   791  	return json.Marshal(exported)
   792  }
   793  
   794  // UnmarshalJSON implements the json.Unmarshaler interface and allows
   795  // ACLAuthMethod.MaxTokenTTL to be unmarshalled correctly.
   796  func (m *ACLAuthMethod) UnmarshalJSON(data []byte) error {
   797  	type Alias ACLAuthMethod
   798  	aux := &struct {
   799  		MaxTokenTTL string
   800  		*Alias
   801  	}{
   802  		Alias: (*Alias)(m),
   803  	}
   804  	if err := json.Unmarshal(data, &aux); err != nil {
   805  		return err
   806  	}
   807  	var err error
   808  	if aux.MaxTokenTTL != "" {
   809  		if m.MaxTokenTTL, err = time.ParseDuration(aux.MaxTokenTTL); err != nil {
   810  			return err
   811  		}
   812  	}
   813  	return nil
   814  }
   815  
   816  // ACLAuthMethodConfig is used to store configuration of an auth method.
   817  type ACLAuthMethodConfig struct {
   818  	// A list of PEM-encoded public keys to use to authenticate signatures
   819  	// locally
   820  	JWTValidationPubKeys []string
   821  	// JSON Web Key Sets url for authenticating signatures
   822  	JWKSURL string
   823  	// The OIDC Discovery URL, without any .well-known component (base path)
   824  	OIDCDiscoveryURL string
   825  	// The OAuth Client ID configured with the OIDC provider
   826  	OIDCClientID string
   827  	// The OAuth Client Secret configured with the OIDC provider
   828  	OIDCClientSecret string
   829  	// Disable claims from the OIDC UserInfo endpoint
   830  	OIDCDisableUserInfo bool
   831  	// List of OIDC scopes
   832  	OIDCScopes []string
   833  	// List of auth claims that are valid for login
   834  	BoundAudiences []string
   835  	// The value against which to match the iss claim in a JWT
   836  	BoundIssuer []string
   837  	// A list of allowed values for redirect_uri
   838  	AllowedRedirectURIs []string
   839  	// PEM encoded CA certs for use by the TLS client used to talk with the
   840  	// OIDC Discovery URL.
   841  	DiscoveryCaPem []string
   842  	// PEM encoded CA cert for use by the TLS client used to talk with the JWKS
   843  	// URL
   844  	JWKSCACert string
   845  	// A list of supported signing algorithms
   846  	SigningAlgs []string
   847  	// Duration in seconds of leeway when validating expiration of a token to
   848  	// account for clock skew
   849  	ExpirationLeeway time.Duration
   850  	// Duration in seconds of leeway when validating not before values of a
   851  	// token to account for clock skew.
   852  	NotBeforeLeeway time.Duration
   853  	// Duration in seconds of leeway when validating all claims to account for
   854  	// clock skew.
   855  	ClockSkewLeeway time.Duration
   856  	// Mappings of claims (key) that will be copied to a metadata field
   857  	// (value).
   858  	ClaimMappings     map[string]string
   859  	ListClaimMappings map[string]string
   860  }
   861  
   862  // MarshalJSON implements the json.Marshaler interface and allows
   863  // time.Duration fields to be marshaled correctly.
   864  func (c *ACLAuthMethodConfig) MarshalJSON() ([]byte, error) {
   865  	type Alias ACLAuthMethodConfig
   866  	exported := &struct {
   867  		ExpirationLeeway string
   868  		NotBeforeLeeway  string
   869  		ClockSkewLeeway  string
   870  		*Alias
   871  	}{
   872  		ExpirationLeeway: c.ExpirationLeeway.String(),
   873  		NotBeforeLeeway:  c.NotBeforeLeeway.String(),
   874  		ClockSkewLeeway:  c.ClockSkewLeeway.String(),
   875  		Alias:            (*Alias)(c),
   876  	}
   877  	if c.ExpirationLeeway == 0 {
   878  		exported.ExpirationLeeway = ""
   879  	}
   880  	if c.NotBeforeLeeway == 0 {
   881  		exported.NotBeforeLeeway = ""
   882  	}
   883  	if c.ClockSkewLeeway == 0 {
   884  		exported.ClockSkewLeeway = ""
   885  	}
   886  	return json.Marshal(exported)
   887  }
   888  
   889  // UnmarshalJSON implements the json.Unmarshaler interface and allows
   890  // time.Duration fields to be unmarshalled correctly.
   891  func (c *ACLAuthMethodConfig) UnmarshalJSON(data []byte) error {
   892  	type Alias ACLAuthMethodConfig
   893  	aux := &struct {
   894  		ExpirationLeeway any
   895  		NotBeforeLeeway  any
   896  		ClockSkewLeeway  any
   897  		*Alias
   898  	}{
   899  		Alias: (*Alias)(c),
   900  	}
   901  	if err := json.Unmarshal(data, &aux); err != nil {
   902  		return err
   903  	}
   904  	var err error
   905  	if aux.ExpirationLeeway != nil {
   906  		switch v := aux.ExpirationLeeway.(type) {
   907  		case string:
   908  			if v != "" {
   909  				if c.ExpirationLeeway, err = time.ParseDuration(v); err != nil {
   910  					return err
   911  				}
   912  			}
   913  		case float64:
   914  			c.ExpirationLeeway = time.Duration(v)
   915  		default:
   916  			return fmt.Errorf("unexpected ExpirationLeeway type: %v", v)
   917  		}
   918  	}
   919  	if aux.NotBeforeLeeway != nil {
   920  		switch v := aux.NotBeforeLeeway.(type) {
   921  		case string:
   922  			if v != "" {
   923  				if c.NotBeforeLeeway, err = time.ParseDuration(v); err != nil {
   924  					return err
   925  				}
   926  			}
   927  		case float64:
   928  			c.NotBeforeLeeway = time.Duration(v)
   929  		default:
   930  			return fmt.Errorf("unexpected NotBeforeLeeway type: %v", v)
   931  		}
   932  	}
   933  	if aux.ClockSkewLeeway != nil {
   934  		switch v := aux.ClockSkewLeeway.(type) {
   935  		case string:
   936  			if v != "" {
   937  				if c.ClockSkewLeeway, err = time.ParseDuration(v); err != nil {
   938  					return err
   939  				}
   940  			}
   941  		case float64:
   942  			c.ClockSkewLeeway = time.Duration(v)
   943  		default:
   944  			return fmt.Errorf("unexpected ClockSkewLeeway type: %v", v)
   945  		}
   946  	}
   947  	return nil
   948  }
   949  
   950  // ACLAuthMethodListStub is the stub object returned when performing a listing
   951  // of ACL auth-methods. It is intentionally minimal due to the unauthenticated
   952  // nature of the list endpoint.
   953  type ACLAuthMethodListStub struct {
   954  	Name    string
   955  	Type    string
   956  	Default bool
   957  
   958  	CreateIndex uint64
   959  	ModifyIndex uint64
   960  }
   961  
   962  const (
   963  	// ACLAuthMethodTokenLocalityLocal is the ACLAuthMethod.TokenLocality that
   964  	// will generate ACL tokens which can only be used on the local cluster the
   965  	// request was made.
   966  	ACLAuthMethodTokenLocalityLocal = "local"
   967  
   968  	// ACLAuthMethodTokenLocalityGlobal is the ACLAuthMethod.TokenLocality that
   969  	// will generate ACL tokens which can be used on all federated clusters.
   970  	ACLAuthMethodTokenLocalityGlobal = "global"
   971  
   972  	// ACLAuthMethodTypeOIDC the ACLAuthMethod.Type and represents an
   973  	// auth-method which uses the OIDC protocol.
   974  	ACLAuthMethodTypeOIDC = "OIDC"
   975  
   976  	// ACLAuthMethodTypeJWT the ACLAuthMethod.Type and represents an auth-method
   977  	// which uses the JWT type.
   978  	ACLAuthMethodTypeJWT = "JWT"
   979  )
   980  
   981  // ACLBindingRule contains a direct relation to an ACLAuthMethod and represents
   982  // a rule to apply when logging in via the named AuthMethod. This allows the
   983  // transformation of OIDC provider claims, to Nomad based ACL concepts such as
   984  // ACL Roles and Policies.
   985  type ACLBindingRule struct {
   986  
   987  	// ID is an internally generated UUID for this rule and is controlled by
   988  	// Nomad.
   989  	ID string
   990  
   991  	// Description is a human-readable, operator set description that can
   992  	// provide additional context about the binding rule. This is an
   993  	// operational field.
   994  	Description string
   995  
   996  	// AuthMethod is the name of the auth method for which this rule applies
   997  	// to. This is required and the method must exist within state before the
   998  	// cluster administrator can create the rule.
   999  	AuthMethod string
  1000  
  1001  	// Selector is an expression that matches against verified identity
  1002  	// attributes returned from the auth method during login. This is optional
  1003  	// and when not set, provides a catch-all rule.
  1004  	Selector string
  1005  
  1006  	// BindType adjusts how this binding rule is applied at login time. The
  1007  	// valid values are ACLBindingRuleBindTypeRole,
  1008  	// ACLBindingRuleBindTypePolicy, and ACLBindingRuleBindTypeManagement.
  1009  	BindType string
  1010  
  1011  	// BindName is the target of the binding. Can be lightly templated using
  1012  	// HIL ${foo} syntax from available field names. How it is used depends
  1013  	// upon the BindType.
  1014  	BindName string
  1015  
  1016  	CreateTime  time.Time
  1017  	ModifyTime  time.Time
  1018  	CreateIndex uint64
  1019  	ModifyIndex uint64
  1020  }
  1021  
  1022  const (
  1023  	// ACLBindingRuleBindTypeRole is the ACL binding rule bind type that only
  1024  	// allows the binding rule to function if a role exists at login-time. The
  1025  	// role will be specified within the ACLBindingRule.BindName parameter, and
  1026  	// will identify whether this is an ID or Name.
  1027  	ACLBindingRuleBindTypeRole = "role"
  1028  
  1029  	// ACLBindingRuleBindTypePolicy is the ACL binding rule bind type that
  1030  	// assigns a policy to the generate ACL token. The role will be specified
  1031  	// within the ACLBindingRule.BindName parameter, and will be the policy
  1032  	// name.
  1033  	ACLBindingRuleBindTypePolicy = "policy"
  1034  
  1035  	// ACLBindingRuleBindTypeManagement is the ACL binding rule bind type that
  1036  	// will generate management ACL tokens when matched.
  1037  	ACLBindingRuleBindTypeManagement = "management"
  1038  )
  1039  
  1040  // ACLBindingRuleListStub is the stub object returned when performing a listing
  1041  // of ACL binding rules.
  1042  type ACLBindingRuleListStub struct {
  1043  
  1044  	// ID is an internally generated UUID for this role and is controlled by
  1045  	// Nomad.
  1046  	ID string
  1047  
  1048  	// Description is a human-readable, operator set description that can
  1049  	// provide additional context about the binding role. This is an
  1050  	// operational field.
  1051  	Description string
  1052  
  1053  	// AuthMethod is the name of the auth method for which this rule applies
  1054  	// to. This is required and the method must exist within state before the
  1055  	// cluster administrator can create the rule.
  1056  	AuthMethod string
  1057  
  1058  	CreateIndex uint64
  1059  	ModifyIndex uint64
  1060  }
  1061  
  1062  // ACLOIDCAuthURLRequest is the request to make when starting the OIDC
  1063  // authentication login flow.
  1064  type ACLOIDCAuthURLRequest struct {
  1065  
  1066  	// AuthMethodName is the OIDC auth-method to use. This is a required
  1067  	// parameter.
  1068  	AuthMethodName string
  1069  
  1070  	// RedirectURI is the URL that authorization should redirect to. This is a
  1071  	// required parameter.
  1072  	RedirectURI string
  1073  
  1074  	// ClientNonce is a randomly generated string to prevent replay attacks. It
  1075  	// is up to the client to generate this and Go integrations should use the
  1076  	// oidc.NewID function within the hashicorp/cap library.
  1077  	ClientNonce string
  1078  }
  1079  
  1080  // ACLOIDCAuthURLResponse is the response when starting the OIDC authentication
  1081  // login flow.
  1082  type ACLOIDCAuthURLResponse struct {
  1083  
  1084  	// AuthURL is URL to begin authorization and is where the user logging in
  1085  	// should go.
  1086  	AuthURL string
  1087  }
  1088  
  1089  // ACLOIDCCompleteAuthRequest is the request object to begin completing the
  1090  // OIDC auth cycle after receiving the callback from the OIDC provider.
  1091  type ACLOIDCCompleteAuthRequest struct {
  1092  
  1093  	// AuthMethodName is the name of the auth method being used to login via
  1094  	// OIDC. This will match AuthUrlArgs.AuthMethodName. This is a required
  1095  	// parameter.
  1096  	AuthMethodName string
  1097  
  1098  	// ClientNonce, State, and Code are provided from the parameters given to
  1099  	// the redirect URL. These are all required parameters.
  1100  	ClientNonce string
  1101  	State       string
  1102  	Code        string
  1103  
  1104  	// RedirectURI is the URL that authorization should redirect to. This is a
  1105  	// required parameter.
  1106  	RedirectURI string
  1107  }
  1108  
  1109  // ACLLoginRequest is the request object to begin auth with an external bearer
  1110  // token provider.
  1111  type ACLLoginRequest struct {
  1112  	// AuthMethodName is the name of the auth method being used to login. This
  1113  	// is a required parameter.
  1114  	AuthMethodName string
  1115  	// LoginToken is the token used to login. This is a required parameter.
  1116  	LoginToken string
  1117  }