github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/nomad/mock/acl.go (about)

     1  package mock
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  	"time"
     8  
     9  	"github.com/hashicorp/nomad/helper/uuid"
    10  	testing "github.com/mitchellh/go-testing-interface"
    11  
    12  	"github.com/hashicorp/nomad/nomad/structs"
    13  	"github.com/stretchr/testify/assert"
    14  )
    15  
    16  // StateStore defines the methods required from state.StateStore but avoids a
    17  // circular dependency.
    18  type StateStore interface {
    19  	UpsertACLPolicies(msgType structs.MessageType, index uint64, policies []*structs.ACLPolicy) error
    20  	UpsertACLTokens(msgType structs.MessageType, index uint64, tokens []*structs.ACLToken) error
    21  }
    22  
    23  // NamespacePolicy is a helper for generating the policy hcl for a given
    24  // namespace. Either policy or capabilities may be nil but not both.
    25  func NamespacePolicy(namespace string, policy string, capabilities []string) string {
    26  	policyHCL := fmt.Sprintf("namespace %q {", namespace)
    27  	if policy != "" {
    28  		policyHCL += fmt.Sprintf("\n\tpolicy = %q", policy)
    29  	}
    30  	if len(capabilities) != 0 {
    31  		for i, s := range capabilities {
    32  			if !strings.HasPrefix(s, "\"") {
    33  				capabilities[i] = strconv.Quote(s)
    34  			}
    35  		}
    36  
    37  		policyHCL += fmt.Sprintf("\n\tcapabilities = [%v]", strings.Join(capabilities, ","))
    38  	}
    39  	policyHCL += "\n}"
    40  	return policyHCL
    41  }
    42  
    43  // NamespacePolicyWithVariables is a helper for generating the policy hcl for a given
    44  // namespace. Either policy or capabilities may be nil but not both.
    45  func NamespacePolicyWithVariables(namespace string, policy string, capabilities []string, svars map[string][]string) string {
    46  	policyHCL := fmt.Sprintf("namespace %q {", namespace)
    47  	if policy != "" {
    48  		policyHCL += fmt.Sprintf("\n\tpolicy = %q", policy)
    49  	}
    50  	if len(capabilities) != 0 {
    51  		for i, s := range capabilities {
    52  			if !strings.HasPrefix(s, "\"") {
    53  				capabilities[i] = strconv.Quote(s)
    54  			}
    55  		}
    56  		policyHCL += fmt.Sprintf("\n\tcapabilities = [%v]", strings.Join(capabilities, ","))
    57  	}
    58  
    59  	policyHCL += VariablePolicy(svars)
    60  	policyHCL += "\n}"
    61  	return policyHCL
    62  }
    63  
    64  // VariablePolicy is a helper for generating the policy hcl for a given
    65  // variable block inside of a namespace.
    66  func VariablePolicy(svars map[string][]string) string {
    67  	policyHCL := ""
    68  	if len(svars) > 0 {
    69  		policyHCL = "\n\n\tvariables {"
    70  		for p, c := range svars {
    71  			for i, s := range c {
    72  				if !strings.HasPrefix(s, "\"") {
    73  					c[i] = strconv.Quote(s)
    74  				}
    75  			}
    76  			policyHCL += fmt.Sprintf("\n\t\tpath %q { capabilities = [%v]}", p, strings.Join(c, ","))
    77  		}
    78  		policyHCL += "\n\t}"
    79  	}
    80  	return policyHCL
    81  }
    82  
    83  // HostVolumePolicy is a helper for generating the policy hcl for a given
    84  // host-volume. Either policy or capabilities may be nil but not both.
    85  func HostVolumePolicy(vol string, policy string, capabilities []string) string {
    86  	policyHCL := fmt.Sprintf("host_volume %q {", vol)
    87  	if policy != "" {
    88  		policyHCL += fmt.Sprintf("\n\tpolicy = %q", policy)
    89  	}
    90  	if len(capabilities) != 0 {
    91  		for i, s := range capabilities {
    92  			if !strings.HasPrefix(s, "\"") {
    93  				capabilities[i] = strconv.Quote(s)
    94  			}
    95  		}
    96  
    97  		policyHCL += fmt.Sprintf("\n\tcapabilities = [%v]", strings.Join(capabilities, ","))
    98  	}
    99  	policyHCL += "\n}"
   100  	return policyHCL
   101  }
   102  
   103  // AgentPolicy is a helper for generating the hcl for a given agent policy.
   104  func AgentPolicy(policy string) string {
   105  	return fmt.Sprintf("agent {\n\tpolicy = %q\n}\n", policy)
   106  }
   107  
   108  // NodePolicy is a helper for generating the hcl for a given node policy.
   109  func NodePolicy(policy string) string {
   110  	return fmt.Sprintf("node {\n\tpolicy = %q\n}\n", policy)
   111  }
   112  
   113  // QuotaPolicy is a helper for generating the hcl for a given quota policy.
   114  func QuotaPolicy(policy string) string {
   115  	return fmt.Sprintf("quota {\n\tpolicy = %q\n}\n", policy)
   116  }
   117  
   118  // PluginPolicy is a helper for generating the hcl for a given plugin policy.
   119  func PluginPolicy(policy string) string {
   120  	return fmt.Sprintf("plugin {\n\tpolicy = %q\n}\n", policy)
   121  }
   122  
   123  // CreatePolicy creates a policy with the given name and rule.
   124  func CreatePolicy(t testing.T, state StateStore, index uint64, name, rule string) {
   125  	t.Helper()
   126  
   127  	// Create the ACLPolicy
   128  	policy := &structs.ACLPolicy{
   129  		Name:  name,
   130  		Rules: rule,
   131  	}
   132  	policy.SetHash()
   133  	assert.Nil(t, state.UpsertACLPolicies(structs.MsgTypeTestSetup, index, []*structs.ACLPolicy{policy}))
   134  }
   135  
   136  // CreateToken creates a local, client token for the given policies
   137  func CreateToken(t testing.T, state StateStore, index uint64, policies []string) *structs.ACLToken {
   138  	t.Helper()
   139  
   140  	// Create the ACLToken
   141  	token := ACLToken()
   142  	token.Policies = policies
   143  	token.SetHash()
   144  	assert.Nil(t, state.UpsertACLTokens(structs.MsgTypeTestSetup, index, []*structs.ACLToken{token}))
   145  	return token
   146  }
   147  
   148  // CreatePolicyAndToken creates a policy and then returns a token configured for
   149  // just that policy. CreatePolicyAndToken uses the given index and index+1.
   150  func CreatePolicyAndToken(t testing.T, state StateStore, index uint64, name, rule string) *structs.ACLToken {
   151  	CreatePolicy(t, state, index, name, rule)
   152  	return CreateToken(t, state, index+1, []string{name})
   153  }
   154  
   155  func ACLRole() *structs.ACLRole {
   156  	role := structs.ACLRole{
   157  		ID:          uuid.Generate(),
   158  		Name:        fmt.Sprintf("acl-role-%s", uuid.Short()),
   159  		Description: "mocked-test-acl-role",
   160  		Policies: []*structs.ACLRolePolicyLink{
   161  			{Name: "mocked-test-policy-1"},
   162  			{Name: "mocked-test-policy-2"},
   163  		},
   164  		CreateIndex: 10,
   165  		ModifyIndex: 10,
   166  	}
   167  	role.SetHash()
   168  	return &role
   169  }
   170  
   171  func ACLPolicy() *structs.ACLPolicy {
   172  	ap := &structs.ACLPolicy{
   173  		Name:        fmt.Sprintf("policy-%s", uuid.Generate()),
   174  		Description: "Super cool policy!",
   175  		Rules: `
   176  		namespace "default" {
   177  			policy = "write"
   178  		}
   179  		node {
   180  			policy = "read"
   181  		}
   182  		agent {
   183  			policy = "read"
   184  		}
   185  		`,
   186  		CreateIndex: 10,
   187  		ModifyIndex: 20,
   188  	}
   189  	ap.SetHash()
   190  	return ap
   191  }
   192  
   193  func ACLToken() *structs.ACLToken {
   194  	tk := &structs.ACLToken{
   195  		AccessorID:  uuid.Generate(),
   196  		SecretID:    uuid.Generate(),
   197  		Name:        "my cool token " + uuid.Generate(),
   198  		Type:        "client",
   199  		Policies:    []string{"foo", "bar"},
   200  		Global:      false,
   201  		CreateTime:  time.Now().UTC(),
   202  		CreateIndex: 10,
   203  		ModifyIndex: 20,
   204  	}
   205  	tk.SetHash()
   206  	return tk
   207  }
   208  
   209  func ACLManagementToken() *structs.ACLToken {
   210  	return &structs.ACLToken{
   211  		AccessorID:  uuid.Generate(),
   212  		SecretID:    uuid.Generate(),
   213  		Name:        "management " + uuid.Generate(),
   214  		Type:        "management",
   215  		Global:      true,
   216  		CreateTime:  time.Now().UTC(),
   217  		CreateIndex: 10,
   218  		ModifyIndex: 20,
   219  	}
   220  }
   221  
   222  func ACLAuthMethod() *structs.ACLAuthMethod {
   223  	maxTokenTTL, _ := time.ParseDuration("3600s")
   224  	method := structs.ACLAuthMethod{
   225  		Name:          fmt.Sprintf("acl-auth-method-%s", uuid.Short()),
   226  		Type:          "OIDC",
   227  		TokenLocality: "local",
   228  		MaxTokenTTL:   maxTokenTTL,
   229  		Default:       false,
   230  		Config: &structs.ACLAuthMethodConfig{
   231  			OIDCDiscoveryURL:    "http://example.com",
   232  			OIDCClientID:        "mock",
   233  			OIDCClientSecret:    "very secret secret",
   234  			BoundAudiences:      []string{"audience1", "audience2"},
   235  			AllowedRedirectURIs: []string{"foo", "bar"},
   236  			DiscoveryCaPem:      []string{"foo"},
   237  			SigningAlgs:         []string{"bar"},
   238  			ClaimMappings:       map[string]string{"foo": "bar"},
   239  			ListClaimMappings:   map[string]string{"foo": "bar"},
   240  		},
   241  		CreateTime:  time.Now().UTC(),
   242  		CreateIndex: 10,
   243  		ModifyIndex: 10,
   244  	}
   245  	method.SetHash()
   246  	method.Canonicalize()
   247  	return &method
   248  }
   249  
   250  func ACLBindingRule() *structs.ACLBindingRule {
   251  	return &structs.ACLBindingRule{
   252  		ID:          uuid.Short(),
   253  		Description: "mocked-acl-binding-rule",
   254  		AuthMethod:  "auth0",
   255  		Selector:    "engineering in list.roles",
   256  		BindType:    "role",
   257  		BindName:    "eng-ro",
   258  		CreateTime:  time.Now().UTC(),
   259  		ModifyTime:  time.Now().UTC(),
   260  		CreateIndex: 10,
   261  		ModifyIndex: 10,
   262  	}
   263  }