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 }