From d1faead3715ca7a2bab7bd99c0a6a2c112afbfe8 Mon Sep 17 00:00:00 2001 From: Tim Gross Date: Fri, 26 Aug 2022 14:03:56 -0400 Subject: [PATCH] rename SecureVariables to Variables throughout --- acl/acl.go | 37 ++- acl/acl_test.go | 46 ++-- acl/policy.go | 56 ++-- acl/policy_test.go | 22 +- api/contexts/contexts.go | 2 +- api/quota.go | 9 +- api/variables.go | 150 +++++------ api/variables_test.go | 34 +-- command/agent/http.go | 4 +- command/agent/search_endpoint_test.go | 60 ++--- command/agent/variable_endpoint.go | 72 ++--- command/agent/variable_endpoint_test.go | 158 +++++------ command/commands.go | 20 +- command/operator_root_keyring.go | 42 +-- command/operator_root_keyring_install.go | 28 +- command/operator_root_keyring_list.go | 28 +- command/operator_root_keyring_remove.go | 26 +- command/operator_root_keyring_rotate.go | 28 +- command/quota_apply.go | 2 +- command/quota_init.go | 4 +- command/quota_status.go | 6 +- command/var.go | 28 +- command/var_init.go | 16 +- command/var_list.go | 28 +- command/var_list_test.go | 12 +- helper/raftutil/msgtypes.go | 2 +- nomad/config.go | 6 +- nomad/core_sched.go | 30 +-- nomad/core_sched_test.go | 36 +-- nomad/encrypter.go | 3 +- nomad/fsm.go | 64 ++--- nomad/fsm_test.go | 26 +- nomad/keyring_endpoint.go | 4 +- nomad/leader.go | 8 +- nomad/mock/acl.go | 12 +- nomad/mock/mock.go | 60 ++--- nomad/search_endpoint.go | 26 +- nomad/search_endpoint_oss.go | 4 +- nomad/server.go | 13 +- nomad/state/schema.go | 50 ++-- nomad/state/state_store.go | 8 +- nomad/state/state_store_restore.go | 24 +- nomad/state/state_store_restore_test.go | 8 +- nomad/state/state_store_test.go | 10 +- nomad/state/state_store_variables.go | 211 ++++++++------- nomad/state/state_store_variables_oss.go | 2 +- nomad/state/state_store_variables_test.go | 222 ++++++++-------- nomad/structs/search.go | 2 +- nomad/structs/structs.go | 10 +- nomad/structs/variables.go | 304 +++++++++++----------- nomad/structs/variables_test.go | 18 +- nomad/variables_endpoint.go | 174 ++++++------- nomad/variables_endpoint_test.go | 154 +++++------ 53 files changed, 1201 insertions(+), 1208 deletions(-) diff --git a/acl/acl.go b/acl/acl.go index 8af395e4f..5c1c33222 100644 --- a/acl/acl.go +++ b/acl/acl.go @@ -61,8 +61,8 @@ type ACL struct { // We use an iradix for the purposes of ordered iteration. wildcardHostVolumes *iradix.Tree - secureVariables *iradix.Tree - wildcardSecureVariables *iradix.Tree + variables *iradix.Tree + wildcardVariables *iradix.Tree agent string node string @@ -131,8 +131,8 @@ func NewACL(management bool, policies []*Policy) (*ACL, error) { } } - if ns.SecureVariables != nil { - for _, pathPolicy := range ns.SecureVariables.Paths { + if ns.Variables != nil { + for _, pathPolicy := range ns.Variables.Paths { key := []byte(ns.Name + "\x00" + pathPolicy.PathSpec) var svCapabilities capabilitySet if globDefinition || strings.Contains(pathPolicy.PathSpec, "*") { @@ -241,8 +241,8 @@ func NewACL(management bool, policies []*Policy) (*ACL, error) { acl.wildcardNamespaces = wnsTxn.Commit() acl.hostVolumes = hvTxn.Commit() acl.wildcardHostVolumes = whvTxn.Commit() - acl.secureVariables = svTxn.Commit() - acl.wildcardSecureVariables = wsvTxn.Commit() + acl.variables = svTxn.Commit() + acl.wildcardVariables = wsvTxn.Commit() return acl, nil } @@ -358,13 +358,13 @@ func (a *ACL) AllowHostVolume(ns string) bool { return !capabilities.Check(PolicyDeny) } -func (a *ACL) AllowSecureVariableOperation(ns, path, op string) bool { +func (a *ACL) AllowVariableOperation(ns, path, op string) bool { if a.management { return true } // Check for a matching capability set - capabilities, ok := a.matchingSecureVariablesCapabilitySet(ns, path) + capabilities, ok := a.matchingVariablesCapabilitySet(ns, path) if !ok { return false } @@ -372,22 +372,21 @@ func (a *ACL) AllowSecureVariableOperation(ns, path, op string) bool { return capabilities.Check(op) } -// AllowSecureVariableSearch is a very loose check that the token has -// *any* access to a secure variables path for the namespace, with an -// expectation that the actual search result will be filtered by -// specific paths -func (a *ACL) AllowSecureVariableSearch(ns string) bool { +// AllowVariableSearch is a very loose check that the token has *any* access to +// a variables path for the namespace, with an expectation that the actual +// search result will be filtered by specific paths +func (a *ACL) AllowVariableSearch(ns string) bool { if a.management { return true } - iter := a.secureVariables.Root().Iterator() + iter := a.variables.Root().Iterator() iter.SeekPrefix([]byte(ns)) _, _, ok := iter.Next() if ok { return true } - iter = a.wildcardSecureVariables.Root().Iterator() + iter = a.wildcardVariables.Root().Iterator() iter.SeekPrefix([]byte(ns)) _, _, ok = iter.Next() return ok @@ -461,20 +460,20 @@ func (a *ACL) matchingHostVolumeCapabilitySet(name string) (capabilitySet, bool) return a.findClosestMatchingGlob(a.wildcardHostVolumes, name) } -// matchingSecureVariablesCapabilitySet looks for a capabilitySet that matches the namespace and path, +// matchingVariablesCapabilitySet looks for a capabilitySet that matches the namespace and path, // if no concrete definitions are found, then we return the closest matching // glob. // The closest matching glob is the one that has the smallest character // difference between the namespace and the glob. -func (a *ACL) matchingSecureVariablesCapabilitySet(ns, path string) (capabilitySet, bool) { +func (a *ACL) matchingVariablesCapabilitySet(ns, path string) (capabilitySet, bool) { // Check for a concrete matching capability set - raw, ok := a.secureVariables.Get([]byte(ns + "\x00" + path)) + raw, ok := a.variables.Get([]byte(ns + "\x00" + path)) if ok { return raw.(capabilitySet), true } // We didn't find a concrete match, so lets try and evaluate globs. - return a.findClosestMatchingGlob(a.wildcardSecureVariables, ns+"\x00"+path) + return a.findClosestMatchingGlob(a.wildcardVariables, ns+"\x00"+path) } type matchingGlob struct { diff --git a/acl/acl_test.go b/acl/acl_test.go index 51c1a6189..3b74431db 100644 --- a/acl/acl_test.go +++ b/acl/acl_test.go @@ -448,7 +448,7 @@ func TestWildcardHostVolumeMatching(t *testing.T) { } } -func TestSecureVariablesMatching(t *testing.T) { +func TestVariablesMatching(t *testing.T) { ci.Parallel(t) tests := []struct { @@ -462,7 +462,7 @@ func TestSecureVariablesMatching(t *testing.T) { { name: "concrete namespace with concrete path matches", policy: `namespace "ns" { - secure_variables { path "foo/bar" { capabilities = ["read"] }}}`, + variables { path "foo/bar" { capabilities = ["read"] }}}`, ns: "ns", path: "foo/bar", op: "read", @@ -471,7 +471,7 @@ func TestSecureVariablesMatching(t *testing.T) { { name: "concrete namespace with concrete path matches for expanded caps", policy: `namespace "ns" { - secure_variables { path "foo/bar" { capabilities = ["read"] }}}`, + variables { path "foo/bar" { capabilities = ["read"] }}}`, ns: "ns", path: "foo/bar", op: "list", @@ -480,7 +480,7 @@ func TestSecureVariablesMatching(t *testing.T) { { name: "concrete namespace with wildcard path matches", policy: `namespace "ns" { - secure_variables { path "foo/*" { capabilities = ["read"] }}}`, + variables { path "foo/*" { capabilities = ["read"] }}}`, ns: "ns", path: "foo/bar", op: "read", @@ -489,7 +489,7 @@ func TestSecureVariablesMatching(t *testing.T) { { name: "concrete namespace with non-prefix wildcard path matches", policy: `namespace "ns" { - secure_variables { path "*/bar" { capabilities = ["read"] }}}`, + variables { path "*/bar" { capabilities = ["read"] }}}`, ns: "ns", path: "foo/bar", op: "read", @@ -498,7 +498,7 @@ func TestSecureVariablesMatching(t *testing.T) { { name: "concrete namespace with overlapping wildcard path prefix over suffix matches", policy: `namespace "ns" { - secure_variables { + variables { path "*/bar" { capabilities = ["list"] } path "foo/*" { capabilities = ["write"] } }}`, @@ -510,7 +510,7 @@ func TestSecureVariablesMatching(t *testing.T) { { name: "concrete namespace with overlapping wildcard path prefix over suffix denied", policy: `namespace "ns" { - secure_variables { + variables { path "*/bar" { capabilities = ["list"] } path "foo/*" { capabilities = ["write"] } }}`, @@ -522,7 +522,7 @@ func TestSecureVariablesMatching(t *testing.T) { { name: "concrete namespace with wildcard path matches most specific only", policy: `namespace "ns" { - secure_variables { + variables { path "*" { capabilities = ["read"] } path "foo/*" { capabilities = ["read"] } path "foo/bar" { capabilities = ["list"] } @@ -535,7 +535,7 @@ func TestSecureVariablesMatching(t *testing.T) { { name: "concrete namespace with invalid concrete path fails", policy: `namespace "ns" { - secure_variables { path "bar" { capabilities = ["read"] }}}`, + variables { path "bar" { capabilities = ["read"] }}}`, ns: "ns", path: "foo/bar", op: "read", @@ -544,7 +544,7 @@ func TestSecureVariablesMatching(t *testing.T) { { name: "concrete namespace with invalid wildcard path fails", policy: `namespace "ns" { - secure_variables { path "*/foo" { capabilities = ["read"] }}}`, + variables { path "*/foo" { capabilities = ["read"] }}}`, ns: "ns", path: "foo/bar", op: "read", @@ -553,7 +553,7 @@ func TestSecureVariablesMatching(t *testing.T) { { name: "wildcard namespace with concrete path matches", policy: `namespace "*" { - secure_variables { path "foo/bar" { capabilities = ["read"] }}}`, + variables { path "foo/bar" { capabilities = ["read"] }}}`, ns: "ns", path: "foo/bar", op: "read", @@ -562,7 +562,7 @@ func TestSecureVariablesMatching(t *testing.T) { { name: "wildcard namespace with invalid concrete path fails", policy: `namespace "*" { - secure_variables { path "bar" { capabilities = ["read"] }}}`, + variables { path "bar" { capabilities = ["read"] }}}`, ns: "ns", path: "foo/bar", op: "read", @@ -571,7 +571,7 @@ func TestSecureVariablesMatching(t *testing.T) { { name: "wildcard in user provided path fails", policy: `namespace "ns" { - secure_variables { path "foo/bar" { capabilities = ["read"] }}}`, + variables { path "foo/bar" { capabilities = ["read"] }}}`, ns: "ns", path: "*", op: "read", @@ -580,7 +580,7 @@ func TestSecureVariablesMatching(t *testing.T) { { name: "wildcard attempt to bypass delimiter null byte fails", policy: `namespace "ns" { - secure_variables { path "foo/bar" { capabilities = ["read"] }}}`, + variables { path "foo/bar" { capabilities = ["read"] }}}`, ns: "ns*", path: "bar", op: "read", @@ -589,7 +589,7 @@ func TestSecureVariablesMatching(t *testing.T) { { name: "wildcard with more specific denied path", policy: `namespace "ns" { - secure_variables { + variables { path "*" { capabilities = ["list"] } path "system/*" { capabilities = ["deny"] }}}`, ns: "ns", @@ -600,11 +600,11 @@ func TestSecureVariablesMatching(t *testing.T) { { name: "multiple namespace with overlapping paths", policy: `namespace "ns" { - secure_variables { + variables { path "*" { capabilities = ["list"] } path "system/*" { capabilities = ["deny"] }}} namespace "prod" { - secure_variables { + variables { path "*" { capabilities = ["list"]}}}`, ns: "prod", path: "system/is-allowed", @@ -618,24 +618,24 @@ func TestSecureVariablesMatching(t *testing.T) { t.Run(tc.name, func(t *testing.T) { policy, err := Parse(tc.policy) require.NoError(t, err) - require.NotNil(t, policy.Namespaces[0].SecureVariables) + require.NotNil(t, policy.Namespaces[0].Variables) acl, err := NewACL(false, []*Policy{policy}) require.NoError(t, err) - require.Equal(t, tc.allow, acl.AllowSecureVariableOperation(tc.ns, tc.path, tc.op)) + require.Equal(t, tc.allow, acl.AllowVariableOperation(tc.ns, tc.path, tc.op)) }) } t.Run("search over namespace", func(t *testing.T) { policy, err := Parse(`namespace "ns" { - secure_variables { path "foo/bar" { capabilities = ["read"] }}}`) + variables { path "foo/bar" { capabilities = ["read"] }}}`) require.NoError(t, err) - require.NotNil(t, policy.Namespaces[0].SecureVariables) + require.NotNil(t, policy.Namespaces[0].Variables) acl, err := NewACL(false, []*Policy{policy}) require.NoError(t, err) - require.True(t, acl.AllowSecureVariableSearch("ns")) - require.False(t, acl.AllowSecureVariableSearch("no-access")) + require.True(t, acl.AllowVariableSearch("ns")) + require.False(t, acl.AllowVariableSearch("no-access")) }) } diff --git a/acl/policy.go b/acl/policy.go index 7059f8b17..b0658cb76 100644 --- a/acl/policy.go +++ b/acl/policy.go @@ -69,13 +69,13 @@ var ( const ( // The following are the fine-grained capabilities that can be - // granted for a secure variables path. When capabilities are + // granted for a variables path. When capabilities are // combined we take the union of all capabilities. - SecureVariablesCapabilityList = "list" - SecureVariablesCapabilityRead = "read" - SecureVariablesCapabilityWrite = "write" - SecureVariablesCapabilityDestroy = "destroy" - SecureVariablesCapabilityDeny = "deny" + VariablesCapabilityList = "list" + VariablesCapabilityRead = "read" + VariablesCapabilityWrite = "write" + VariablesCapabilityDestroy = "destroy" + VariablesCapabilityDeny = "deny" ) // Policy represents a parsed HCL or JSON policy. @@ -104,17 +104,17 @@ func (p *Policy) IsEmpty() bool { // NamespacePolicy is the policy for a specific namespace type NamespacePolicy struct { - Name string `hcl:",key"` - Policy string - Capabilities []string - SecureVariables *SecureVariablesPolicy `hcl:"secure_variables"` + Name string `hcl:",key"` + Policy string + Capabilities []string + Variables *VariablesPolicy `hcl:"variables"` } -type SecureVariablesPolicy struct { - Paths []*SecureVariablesPathPolicy `hcl:"path"` +type VariablesPolicy struct { + Paths []*VariablesPathPolicy `hcl:"path"` } -type SecureVariablesPathPolicy struct { +type VariablesPathPolicy struct { PathSpec string `hcl:",key"` Capabilities []string } @@ -184,11 +184,11 @@ func isNamespaceCapabilityValid(cap string) bool { } // isPathCapabilityValid ensures the given capability is valid for a -// secure variables path policy +// variables path policy func isPathCapabilityValid(cap string) bool { switch cap { - case SecureVariablesCapabilityWrite, SecureVariablesCapabilityRead, - SecureVariablesCapabilityList, SecureVariablesCapabilityDestroy, SecureVariablesCapabilityDeny: + case VariablesCapabilityWrite, VariablesCapabilityRead, + VariablesCapabilityList, VariablesCapabilityDestroy, VariablesCapabilityDeny: return true default: return false @@ -266,15 +266,15 @@ func expandHostVolumePolicy(policy string) []string { } } -func expandSecureVariablesCapabilities(caps []string) []string { +func expandVariablesCapabilities(caps []string) []string { var foundRead, foundList bool for _, cap := range caps { switch cap { - case SecureVariablesCapabilityDeny: - return []string{SecureVariablesCapabilityDeny} - case SecureVariablesCapabilityRead: + case VariablesCapabilityDeny: + return []string{VariablesCapabilityDeny} + case VariablesCapabilityRead: foundRead = true - case SecureVariablesCapabilityList: + case VariablesCapabilityList: foundList = true } } @@ -327,21 +327,21 @@ func Parse(rules string) (*Policy, error) { ns.Capabilities = append(ns.Capabilities, extraCap...) } - if ns.SecureVariables != nil { - if len(ns.SecureVariables.Paths) == 0 { - return nil, fmt.Errorf("Invalid secure variable policy: no secure variable paths in namespace %s", ns.Name) + if ns.Variables != nil { + if len(ns.Variables.Paths) == 0 { + return nil, fmt.Errorf("Invalid variable policy: no variable paths in namespace %s", ns.Name) } - for _, pathPolicy := range ns.SecureVariables.Paths { + for _, pathPolicy := range ns.Variables.Paths { if pathPolicy.PathSpec == "" { - return nil, fmt.Errorf("Invalid missing secure variable path in namespace %s", ns.Name) + return nil, fmt.Errorf("Invalid missing variable path in namespace %s", ns.Name) } for _, cap := range pathPolicy.Capabilities { if !isPathCapabilityValid(cap) { return nil, fmt.Errorf( - "Invalid secure variable capability '%s' in namespace %s", cap, ns.Name) + "Invalid variable capability '%s' in namespace %s", cap, ns.Name) } } - pathPolicy.Capabilities = expandSecureVariablesCapabilities(pathPolicy.Capabilities) + pathPolicy.Capabilities = expandVariablesCapabilities(pathPolicy.Capabilities) } diff --git a/acl/policy_test.go b/acl/policy_test.go index bd8f6eba6..fdd9a70e7 100644 --- a/acl/policy_test.go +++ b/acl/policy_test.go @@ -56,7 +56,7 @@ func TestParse(t *testing.T) { capabilities = ["deny", "read-logs"] } namespace "apps" { - secure_variables { + variables { path "jobs/write-does-not-imply-read-or-delete" { capabilities = ["write"] } @@ -137,25 +137,25 @@ func TestParse(t *testing.T) { }, { Name: "apps", - SecureVariables: &SecureVariablesPolicy{ - Paths: []*SecureVariablesPathPolicy{ + Variables: &VariablesPolicy{ + Paths: []*VariablesPathPolicy{ { PathSpec: "jobs/write-does-not-imply-read-or-delete", - Capabilities: []string{SecureVariablesCapabilityWrite}, + Capabilities: []string{VariablesCapabilityWrite}, }, { PathSpec: "project/read-implies-list", Capabilities: []string{ - SecureVariablesCapabilityRead, - SecureVariablesCapabilityList, + VariablesCapabilityRead, + VariablesCapabilityList, }, }, { PathSpec: "project/explicit", Capabilities: []string{ - SecureVariablesCapabilityRead, - SecureVariablesCapabilityList, - SecureVariablesCapabilityDestroy, + VariablesCapabilityRead, + VariablesCapabilityList, + VariablesCapabilityDestroy, }, }, }, @@ -201,12 +201,12 @@ func TestParse(t *testing.T) { { ` namespace "dev" { - secure_variables "*" { + variables "*" { capabilities = ["read", "write"] } } `, - "Invalid secure variable policy: no secure variable paths in namespace dev", + "Invalid variable policy: no variable paths in namespace dev", nil, }, { diff --git a/api/contexts/contexts.go b/api/contexts/contexts.go index a075b249f..f189c0de1 100644 --- a/api/contexts/contexts.go +++ b/api/contexts/contexts.go @@ -17,7 +17,7 @@ const ( Recommendations Context = "recommendations" ScalingPolicies Context = "scaling_policy" Plugins Context = "plugins" - SecureVariables Context = "vars" + Variables Context = "vars" Volumes Context = "volumes" // These Context types are used to associate a search result from a lower diff --git a/api/quota.go b/api/quota.go index ecfb82e8e..acbd52950 100644 --- a/api/quota.go +++ b/api/quota.go @@ -126,11 +126,10 @@ type QuotaLimit struct { // useful for once we support GPUs RegionLimit *Resources - // SecureVariablesLimit is the maximum total size of all secure - // variables SecureVariable.EncryptedData. A value of zero is - // treated as unlimited and a negative value is treated as fully - // disallowed. - SecureVariablesLimit *int `mapstructure:"secure_variables_limit" hcl:"secure_variables_limit,optional"` + // VariablesLimit is the maximum total size of all variables + // Variable.EncryptedData. A value of zero is treated as unlimited and a + // negative value is treated as fully disallowed. + VariablesLimit *int `mapstructure:"variables_limit" hcl:"variables_limit,optional"` // Hash is the hash of the object and is used to make replication efficient. Hash []byte diff --git a/api/variables.go b/api/variables.go index ff32d6761..23fe2dfe3 100644 --- a/api/variables.go +++ b/api/variables.go @@ -12,25 +12,25 @@ import ( ) const ( - ErrVariableNotFound = "secure variable not found" - ErrVariableMissingItems = "secure variable missing Items field" + ErrVariableNotFound = "variable not found" + ErrVariableMissingItems = "variable missing Items field" ) -// SecureVariables is used to access secure variables. -type SecureVariables struct { +// Variables is used to access variables. +type Variables struct { client *Client } -// SecureVariables returns a new handle on the secure variables. -func (c *Client) SecureVariables() *SecureVariables { - return &SecureVariables{client: c} +// Variables returns a new handle on the variables. +func (c *Client) Variables() *Variables { + return &Variables{client: c} } -// Create is used to create a secure variable. -func (sv *SecureVariables) Create(v *SecureVariable, qo *WriteOptions) (*SecureVariable, *WriteMeta, error) { +// Create is used to create a variable. +func (sv *Variables) Create(v *Variable, qo *WriteOptions) (*Variable, *WriteMeta, error) { v.Path = cleanPathString(v.Path) - var out SecureVariable + var out Variable wm, err := sv.client.write("/v1/var/"+v.Path, v, &out, qo) if err != nil { return nil, wm, err @@ -38,13 +38,13 @@ func (sv *SecureVariables) Create(v *SecureVariable, qo *WriteOptions) (*SecureV return &out, wm, nil } -// CheckedCreate is used to create a secure variable if it doesn't exist +// CheckedCreate is used to create a variable if it doesn't exist // already. If it does, it will return a ErrCASConflict that can be unwrapped // for more details. -func (sv *SecureVariables) CheckedCreate(v *SecureVariable, qo *WriteOptions) (*SecureVariable, *WriteMeta, error) { +func (sv *Variables) CheckedCreate(v *Variable, qo *WriteOptions) (*Variable, *WriteMeta, error) { v.Path = cleanPathString(v.Path) - var out SecureVariable + var out Variable wm, err := sv.writeChecked("/v1/var/"+v.Path+"?cas=0", v, &out, qo) if err != nil { return nil, wm, err @@ -53,12 +53,12 @@ func (sv *SecureVariables) CheckedCreate(v *SecureVariable, qo *WriteOptions) (* return &out, wm, nil } -// Read is used to query a single secure variable by path. This will error +// Read is used to query a single variable by path. This will error // if the variable is not found. -func (sv *SecureVariables) Read(path string, qo *QueryOptions) (*SecureVariable, *QueryMeta, error) { +func (sv *Variables) Read(path string, qo *QueryOptions) (*Variable, *QueryMeta, error) { path = cleanPathString(path) - var svar = new(SecureVariable) + var svar = new(Variable) qm, err := sv.readInternal("/v1/var/"+path, &svar, qo) if err != nil { return nil, nil, err @@ -69,12 +69,12 @@ func (sv *SecureVariables) Read(path string, qo *QueryOptions) (*SecureVariable, return svar, qm, nil } -// Peek is used to query a single secure variable by path, but does not error +// Peek is used to query a single variable by path, but does not error // when the variable is not found -func (sv *SecureVariables) Peek(path string, qo *QueryOptions) (*SecureVariable, *QueryMeta, error) { +func (sv *Variables) Peek(path string, qo *QueryOptions) (*Variable, *QueryMeta, error) { path = cleanPathString(path) - var svar = new(SecureVariable) + var svar = new(Variable) qm, err := sv.readInternal("/v1/var/"+path, &svar, qo) if err != nil { return nil, nil, err @@ -82,11 +82,11 @@ func (sv *SecureVariables) Peek(path string, qo *QueryOptions) (*SecureVariable, return svar, qm, nil } -// Update is used to update a secure variable. -func (sv *SecureVariables) Update(v *SecureVariable, qo *WriteOptions) (*SecureVariable, *WriteMeta, error) { +// Update is used to update a variable. +func (sv *Variables) Update(v *Variable, qo *WriteOptions) (*Variable, *WriteMeta, error) { v.Path = cleanPathString(v.Path) - var out SecureVariable + var out Variable wm, err := sv.client.write("/v1/var/"+v.Path, v, &out, qo) if err != nil { @@ -95,13 +95,13 @@ func (sv *SecureVariables) Update(v *SecureVariable, qo *WriteOptions) (*SecureV return &out, wm, nil } -// CheckedUpdate is used to updated a secure variable if the modify index +// CheckedUpdate is used to updated a variable if the modify index // matches the one on the server. If it does not, it will return an // ErrCASConflict that can be unwrapped for more details. -func (sv *SecureVariables) CheckedUpdate(v *SecureVariable, qo *WriteOptions) (*SecureVariable, *WriteMeta, error) { +func (sv *Variables) CheckedUpdate(v *Variable, qo *WriteOptions) (*Variable, *WriteMeta, error) { v.Path = cleanPathString(v.Path) - var out SecureVariable + var out Variable wm, err := sv.writeChecked("/v1/var/"+v.Path+"?cas="+fmt.Sprint(v.ModifyIndex), v, &out, qo) if err != nil { return nil, wm, err @@ -110,8 +110,8 @@ func (sv *SecureVariables) CheckedUpdate(v *SecureVariable, qo *WriteOptions) (* return &out, wm, nil } -// Delete is used to delete a secure variable -func (sv *SecureVariables) Delete(path string, qo *WriteOptions) (*WriteMeta, error) { +// Delete is used to delete a variable +func (sv *Variables) Delete(path string, qo *WriteOptions) (*WriteMeta, error) { path = cleanPathString(path) wm, err := sv.deleteInternal(path, qo) @@ -121,10 +121,10 @@ func (sv *SecureVariables) Delete(path string, qo *WriteOptions) (*WriteMeta, er return wm, nil } -// CheckedDelete is used to conditionally delete a secure variable. If the +// CheckedDelete is used to conditionally delete a variable. If the // existing variable does not match the provided checkIndex, it will return an // ErrCASConflict that can be unwrapped for more details. -func (sv *SecureVariables) CheckedDelete(path string, checkIndex uint64, qo *WriteOptions) (*WriteMeta, error) { +func (sv *Variables) CheckedDelete(path string, checkIndex uint64, qo *WriteOptions) (*WriteMeta, error) { path = cleanPathString(path) wm, err := sv.deleteChecked(path, checkIndex, qo) @@ -135,11 +135,11 @@ func (sv *SecureVariables) CheckedDelete(path string, checkIndex uint64, qo *Wri return wm, nil } -// List is used to dump all of the secure variables, can be used to pass prefix +// List is used to dump all of the variables, can be used to pass prefix // via QueryOptions rather than as a parameter -func (sv *SecureVariables) List(qo *QueryOptions) ([]*SecureVariableMetadata, *QueryMeta, error) { +func (sv *Variables) List(qo *QueryOptions) ([]*VariableMetadata, *QueryMeta, error) { - var resp []*SecureVariableMetadata + var resp []*VariableMetadata qm, err := sv.client.query("/v1/vars", &resp, qo) if err != nil { return nil, nil, err @@ -147,8 +147,8 @@ func (sv *SecureVariables) List(qo *QueryOptions) ([]*SecureVariableMetadata, *Q return resp, qm, nil } -// PrefixList is used to do a prefix List search over secure variables. -func (sv *SecureVariables) PrefixList(prefix string, qo *QueryOptions) ([]*SecureVariableMetadata, *QueryMeta, error) { +// PrefixList is used to do a prefix List search over variables. +func (sv *Variables) PrefixList(prefix string, qo *QueryOptions) ([]*VariableMetadata, *QueryMeta, error) { if qo == nil { qo = &QueryOptions{Prefix: prefix} @@ -159,12 +159,12 @@ func (sv *SecureVariables) PrefixList(prefix string, qo *QueryOptions) ([]*Secur return sv.List(qo) } -// GetItems returns the inner Items collection from a secure variable at a +// GetItems returns the inner Items collection from a variable at a // given path -func (sv *SecureVariables) GetItems(path string, qo *QueryOptions) (*SecureVariableItems, *QueryMeta, error) { +func (sv *Variables) GetItems(path string, qo *QueryOptions) (*VariableItems, *QueryMeta, error) { path = cleanPathString(path) - svar := new(SecureVariable) + svar := new(Variable) qm, err := sv.readInternal("/v1/var/"+path, &svar, qo) if err != nil { @@ -177,7 +177,7 @@ func (sv *SecureVariables) GetItems(path string, qo *QueryOptions) (*SecureVaria // readInternal exists because the API's higher-level read method requires // the status code to be 200 (OK). For Peek(), we do not consider 404 // (Not Found) an error. -func (sv *SecureVariables) readInternal(endpoint string, out **SecureVariable, q *QueryOptions) (*QueryMeta, error) { +func (sv *Variables) readInternal(endpoint string, out **Variable, q *QueryOptions) (*QueryMeta, error) { r, err := sv.client.newRequest("GET", endpoint) if err != nil { @@ -212,7 +212,7 @@ func (sv *SecureVariables) readInternal(endpoint string, out **SecureVariable, q // readInternal exists because the API's higher-level delete method requires // the status code to be 200 (OK). The SV HTTP API returns a 204 (No Content) // on success. -func (sv *SecureVariables) deleteInternal(path string, q *WriteOptions) (*WriteMeta, error) { +func (sv *Variables) deleteInternal(path string, q *WriteOptions) (*WriteMeta, error) { r, err := sv.client.newRequest("DELETE", fmt.Sprintf("/v1/var/%s", path)) if err != nil { @@ -235,7 +235,7 @@ func (sv *SecureVariables) deleteInternal(path string, q *WriteOptions) (*WriteM // deleteChecked exists because the API's higher-level delete method requires // the status code to be OK. The SV HTTP API returns a 204 (No Content) on // success and a 409 (Conflict) on a CAS error. -func (sv *SecureVariables) deleteChecked(path string, checkIndex uint64, q *WriteOptions) (*WriteMeta, error) { +func (sv *Variables) deleteChecked(path string, checkIndex uint64, q *WriteOptions) (*WriteMeta, error) { r, err := sv.client.newRequest("DELETE", fmt.Sprintf("/v1/var/%s?cas=%v", path, checkIndex)) if err != nil { @@ -255,7 +255,7 @@ func (sv *SecureVariables) deleteChecked(path string, checkIndex uint64, q *Writ // it is a conflict response. Otherwise, there won't be one. if resp.StatusCode == http.StatusConflict { - conflict := new(SecureVariable) + conflict := new(Variable) if err := decodeBody(resp, &conflict); err != nil { return nil, err } @@ -270,7 +270,7 @@ func (sv *SecureVariables) deleteChecked(path string, checkIndex uint64, q *Writ // writeChecked exists because the API's higher-level write method requires // the status code to be OK. The SV HTTP API returns a 200 (OK) on // success and a 409 (Conflict) on a CAS error. -func (sv *SecureVariables) writeChecked(endpoint string, in *SecureVariable, out *SecureVariable, q *WriteOptions) (*WriteMeta, error) { +func (sv *Variables) writeChecked(endpoint string, in *Variable, out *Variable, q *WriteOptions) (*WriteMeta, error) { r, err := sv.client.newRequest("PUT", endpoint) if err != nil { @@ -292,7 +292,7 @@ func (sv *SecureVariables) writeChecked(endpoint string, in *SecureVariable, out if resp.StatusCode == http.StatusConflict { - conflict := new(SecureVariable) + conflict := new(Variable) if err := decodeBody(resp, &conflict); err != nil { return nil, err } @@ -309,12 +309,12 @@ func (sv *SecureVariables) writeChecked(endpoint string, in *SecureVariable, out return wm, nil } -// SecureVariable specifies the metadata and contents to be stored in the +// Variable specifies the metadata and contents to be stored in the // encrypted Nomad backend. -type SecureVariable struct { - // Namespace is the Nomad namespace associated with the secure variable +type Variable struct { + // Namespace is the Nomad namespace associated with the variable Namespace string - // Path is the path to the secure variable + // Path is the path to the variable Path string // Raft indexes to track creation and modification @@ -325,15 +325,15 @@ type SecureVariable struct { CreateTime int64 ModifyTime int64 - Items SecureVariableItems + Items VariableItems } -// SecureVariableMetadata specifies the metadata for a secure variable and +// VariableMetadata specifies the metadata for a variable and // is used as the list object -type SecureVariableMetadata struct { - // Namespace is the Nomad namespace associated with the secure variable +type VariableMetadata struct { + // Namespace is the Nomad namespace associated with the variable Namespace string - // Path is the path to the secure variable + // Path is the path to the variable Path string // Raft indexes to track creation and modification @@ -345,35 +345,35 @@ type SecureVariableMetadata struct { ModifyTime int64 } -type SecureVariableItems map[string]string +type VariableItems map[string]string -// NewSecureVariable is a convenience method to more easily create a -// ready-to-use secure variable -func NewSecureVariable(path string) *SecureVariable { +// NewVariable is a convenience method to more easily create a +// ready-to-use variable +func NewVariable(path string) *Variable { - return &SecureVariable{ + return &Variable{ Path: path, - Items: make(SecureVariableItems), + Items: make(VariableItems), } } -// Copy returns a new deep copy of this SecureVariable -func (sv1 *SecureVariable) Copy() *SecureVariable { +// Copy returns a new deep copy of this Variable +func (sv1 *Variable) Copy() *Variable { - var out SecureVariable = *sv1 - out.Items = make(SecureVariableItems) + var out Variable = *sv1 + out.Items = make(VariableItems) for k, v := range sv1.Items { out.Items[k] = v } return &out } -// Metadata returns the SecureVariableMetadata component of -// a SecureVariable. This can be useful for comparing against +// Metadata returns the VariableMetadata component of +// a Variable. This can be useful for comparing against // a List result. -func (sv *SecureVariable) Metadata() *SecureVariableMetadata { +func (sv *Variable) Metadata() *VariableMetadata { - return &SecureVariableMetadata{ + return &VariableMetadata{ Namespace: sv.Namespace, Path: sv.Path, CreateIndex: sv.CreateIndex, @@ -383,10 +383,10 @@ func (sv *SecureVariable) Metadata() *SecureVariableMetadata { } } -// IsZeroValue can be used to test if a SecureVariable has been changed +// IsZeroValue can be used to test if a Variable has been changed // from the default values it gets at creation -func (sv *SecureVariable) IsZeroValue() bool { - return *sv.Metadata() == SecureVariableMetadata{} && sv.Items == nil +func (sv *Variable) IsZeroValue() bool { + return *sv.Metadata() == VariableMetadata{} && sv.Items == nil } // cleanPathString removes leading and trailing slashes since they @@ -396,16 +396,16 @@ func cleanPathString(path string) string { return strings.Trim(path, " /") } -// AsJSON returns the SecureVariable as a JSON-formatted string -func (sv SecureVariable) AsJSON() string { +// AsJSON returns the Variable as a JSON-formatted string +func (sv Variable) AsJSON() string { var b []byte b, _ = json.Marshal(sv) return string(b) } -// AsPrettyJSON returns the SecureVariable as a JSON-formatted string with +// AsPrettyJSON returns the Variable as a JSON-formatted string with // indentation -func (sv SecureVariable) AsPrettyJSON() string { +func (sv Variable) AsPrettyJSON() string { var b []byte b, _ = json.MarshalIndent(sv, "", " ") return string(b) @@ -413,7 +413,7 @@ func (sv SecureVariable) AsPrettyJSON() string { type ErrCASConflict struct { CheckIndex uint64 - Conflict *SecureVariable + Conflict *Variable } func (e ErrCASConflict) Error() string { @@ -449,7 +449,7 @@ func requireStatusIn(statuses ...int) doRequestWrapper { // generateUnexpectedResponseCodeError creates a standardized error // when the the API client's newRequest method receives an unexpected -// HTTP response code when accessing the secure variable's HTTP API +// HTTP response code when accessing the variable's HTTP API func generateUnexpectedResponseCodeError(resp *http.Response) error { var buf bytes.Buffer io.Copy(&buf, resp.Body) diff --git a/api/variables_test.go b/api/variables_test.go index 5252e39eb..1aaf5ae96 100644 --- a/api/variables_test.go +++ b/api/variables_test.go @@ -9,13 +9,13 @@ import ( "github.com/stretchr/testify/require" ) -func TestSecureVariables_SimpleCRUD(t *testing.T) { +func TestVariables_SimpleCRUD(t *testing.T) { testutil.Parallel(t) c, s := makeClient(t, nil, nil) defer s.Stop() - nsv := c.SecureVariables() - sv1 := NewSecureVariable("my/first/variable") + nsv := c.Variables() + sv1 := NewVariable("my/first/variable") sv1.Namespace = "default" sv1.Items["k1"] = "v1" sv1.Items["k2"] = "v2" @@ -27,9 +27,9 @@ func TestSecureVariables_SimpleCRUD(t *testing.T) { t.Run("1 fail create when no items", func(t *testing.T) { - _, _, err := nsv.Create(&SecureVariable{Path: "bad/var"}, nil) + _, _, err := nsv.Create(&Variable{Path: "bad/var"}, nil) require.Error(t, err) - require.EqualError(t, err, "Unexpected response code: 400 (secure variable missing required Items object)") + require.EqualError(t, err, "Unexpected response code: 400 (variable missing required Items object)") }) t.Run("2 create sv1", func(t *testing.T) { @@ -79,7 +79,7 @@ func TestSecureVariables_SimpleCRUD(t *testing.T) { l, _, err := nsv.List(nil) require.NoError(t, err) require.Len(t, l, 2) - require.ElementsMatch(t, []*SecureVariableMetadata{sv1.Metadata(), sv2.Metadata()}, l) + require.ElementsMatch(t, []*VariableMetadata{sv1.Metadata(), sv2.Metadata()}, l) }) t.Run("5a list vars opts", func(t *testing.T) { @@ -118,13 +118,13 @@ func TestSecureVariables_SimpleCRUD(t *testing.T) { }) } -func TestSecureVariables_CRUDWithCAS(t *testing.T) { +func TestVariables_CRUDWithCAS(t *testing.T) { testutil.Parallel(t) c, s := makeClient(t, nil, nil) defer s.Stop() - nsv := c.SecureVariables() - sv1 := &SecureVariable{ + nsv := c.Variables() + sv1 := &Variable{ Path: "cas/variable/a", Items: map[string]string{ "key1": "value1", @@ -173,14 +173,14 @@ func TestSecureVariables_CRUDWithCAS(t *testing.T) { } -func TestSecureVariables_Read(t *testing.T) { +func TestVariables_Read(t *testing.T) { testutil.Parallel(t) c, s := makeClient(t, nil, nil) defer s.Stop() - nsv := c.SecureVariables() + nsv := c.Variables() tID := fmt.Sprint(time.Now().UTC().UnixNano()) - sv1 := SecureVariable{ + sv1 := Variable{ Namespace: "default", Path: tID + "/sv1", Items: map[string]string{ @@ -195,7 +195,7 @@ func TestSecureVariables_Read(t *testing.T) { path string expectedError string checkValue bool - expectedValue *SecureVariable + expectedValue *Variable }{ { name: "not found", @@ -231,18 +231,18 @@ func TestSecureVariables_Read(t *testing.T) { } } -func writeTestVariable(t *testing.T, c *Client, sv *SecureVariable) { +func writeTestVariable(t *testing.T, c *Client, sv *Variable) { _, err := c.write("/v1/var/"+sv.Path, sv, sv, nil) require.NoError(t, err, "Error writing test variable") require.NoError(t, err, "Error writing test variable") } -func TestSecureVariable_CreateReturnsContent(t *testing.T) { +func TestVariable_CreateReturnsContent(t *testing.T) { c, s := makeClient(t, nil, nil) defer s.Stop() - nsv := c.SecureVariables() - sv1 := NewSecureVariable("my/first/variable") + nsv := c.Variables() + sv1 := NewVariable("my/first/variable") sv1.Namespace = "default" sv1.Items["k1"] = "v1" sv1.Items["k2"] = "v2" diff --git a/command/agent/http.go b/command/agent/http.go index b0676ec82..a645fdec0 100644 --- a/command/agent/http.go +++ b/command/agent/http.go @@ -442,8 +442,8 @@ func (s HTTPServer) registerHandlers(enableDebug bool) { s.mux.HandleFunc("/v1/namespace", s.wrap(s.NamespaceCreateRequest)) s.mux.HandleFunc("/v1/namespace/", s.wrap(s.NamespaceSpecificRequest)) - s.mux.Handle("/v1/vars", wrapCORS(s.wrap(s.SecureVariablesListRequest))) - s.mux.Handle("/v1/var/", wrapCORSWithAllowedMethods(s.wrap(s.SecureVariableSpecificRequest), "HEAD", "GET", "PUT", "DELETE")) + s.mux.Handle("/v1/vars", wrapCORS(s.wrap(s.VariablesListRequest))) + s.mux.Handle("/v1/var/", wrapCORSWithAllowedMethods(s.wrap(s.VariableSpecificRequest), "HEAD", "GET", "PUT", "DELETE")) uiConfigEnabled := s.agent.config.UI != nil && s.agent.config.UI.Enabled diff --git a/command/agent/search_endpoint_test.go b/command/agent/search_endpoint_test.go index e9029de7f..894b0732e 100644 --- a/command/agent/search_endpoint_test.go +++ b/command/agent/search_endpoint_test.go @@ -623,24 +623,24 @@ func TestHTTP_FuzzySearch_AllContext(t *testing.T) { }) } -func TestHTTP_PrefixSearch_SecureVariables(t *testing.T) { +func TestHTTP_PrefixSearch_Variables(t *testing.T) { ci.Parallel(t) testPath := "alpha/beta/charlie" testPathPrefix := "alpha/beta" httpTest(t, nil, func(s *TestAgent) { - sv := mock.SecureVariableEncrypted() + sv := mock.VariableEncrypted() state := s.Agent.server.State() sv.Path = testPath - setResp := state.SVESet(8000, &structs.SVApplyStateRequest{ - Op: structs.SVOpSet, + setResp := state.VarSet(8000, &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, Var: sv, }) require.NoError(t, setResp.Error) - data := structs.SearchRequest{Prefix: testPathPrefix, Context: structs.SecureVariables} + data := structs.SearchRequest{Prefix: testPathPrefix, Context: structs.Variables} req, err := http.NewRequest("POST", "/v1/search", encodeReq(data)) require.NoError(t, err) @@ -650,14 +650,14 @@ func TestHTTP_PrefixSearch_SecureVariables(t *testing.T) { require.NoError(t, err) res := resp.(structs.SearchResponse) - matchedVars := res.Matches[structs.SecureVariables] + matchedVars := res.Matches[structs.Variables] require.Len(t, matchedVars, 1) require.Equal(t, testPath, matchedVars[0]) require.Equal(t, "8000", header(respW, "X-Nomad-Index")) }) } -func TestHTTP_FuzzySearch_SecureVariables(t *testing.T) { +func TestHTTP_FuzzySearch_Variables(t *testing.T) { ci.Parallel(t) testPath := "alpha/beta/charlie" @@ -665,15 +665,15 @@ func TestHTTP_FuzzySearch_SecureVariables(t *testing.T) { httpTest(t, nil, func(s *TestAgent) { state := s.Agent.server.State() - sv := mock.SecureVariableEncrypted() + sv := mock.VariableEncrypted() sv.Path = testPath - setResp := state.SVESet(8000, &structs.SVApplyStateRequest{ - Op: structs.SVOpSet, + setResp := state.VarSet(8000, &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, Var: sv, }) require.NoError(t, setResp.Error) - data := structs.FuzzySearchRequest{Text: testPathText, Context: structs.SecureVariables} + data := structs.FuzzySearchRequest{Text: testPathText, Context: structs.Variables} req, err := http.NewRequest("POST", "/v1/search/", encodeReq(data)) require.NoError(t, err) @@ -683,7 +683,7 @@ func TestHTTP_FuzzySearch_SecureVariables(t *testing.T) { require.NoError(t, err) res := resp.(structs.FuzzySearchResponse) - matchedVars := res.Matches[structs.SecureVariables] + matchedVars := res.Matches[structs.Variables] require.Len(t, matchedVars, 1) require.Equal(t, testPath, matchedVars[0].ID) require.Equal(t, []string{ @@ -693,7 +693,7 @@ func TestHTTP_FuzzySearch_SecureVariables(t *testing.T) { }) } -func TestHTTP_PrefixSearch_SecureVariables_ACL(t *testing.T) { +func TestHTTP_PrefixSearch_Variables_ACL(t *testing.T) { ci.Parallel(t) testPath := "alpha/beta/charlie" @@ -702,19 +702,19 @@ func TestHTTP_PrefixSearch_SecureVariables_ACL(t *testing.T) { httpACLTest(t, nil, func(s *TestAgent) { state := s.Agent.server.State() ns := mock.Namespace() - sv1 := mock.SecureVariableEncrypted() + sv1 := mock.VariableEncrypted() sv1.Path = testPath sv2 := sv1.Copy() sv2.Namespace = ns.Name require.NoError(t, state.UpsertNamespaces(7000, []*structs.Namespace{ns})) - setResp := state.SVESet(8000, &structs.SVApplyStateRequest{ - Op: structs.SVOpSet, + setResp := state.VarSet(8000, &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, Var: sv1, }) require.NoError(t, setResp.Error) - setResp = state.SVESet(8001, &structs.SVApplyStateRequest{ - Op: structs.SVOpSet, + setResp = state.VarSet(8001, &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, Var: &sv2, }) require.NoError(t, setResp.Error) @@ -722,12 +722,12 @@ func TestHTTP_PrefixSearch_SecureVariables_ACL(t *testing.T) { rootToken := s.RootToken defNSToken := mock.CreatePolicyAndToken(t, state, 8002, "default", - mock.NamespacePolicyWithSecureVariables( + mock.NamespacePolicyWithVariables( "default", "read", []string{}, map[string][]string{"*": []string{"read", "list"}})) ns1NSToken := mock.CreatePolicyAndToken(t, state, 8004, "ns-"+ns.Name, - mock.NamespacePolicyWithSecureVariables( + mock.NamespacePolicyWithVariables( ns.Name, "read", []string{}, map[string][]string{"*": []string{"read", "list"}})) @@ -776,7 +776,7 @@ func TestHTTP_PrefixSearch_SecureVariables_ACL(t *testing.T) { tC := tC data := structs.SearchRequest{ Prefix: testPathPrefix, - Context: structs.SecureVariables, + Context: structs.Variables, QueryOptions: structs.QueryOptions{ AuthToken: tC.token.SecretID, Namespace: tC.namespace, @@ -796,7 +796,7 @@ func TestHTTP_PrefixSearch_SecureVariables_ACL(t *testing.T) { } require.NoError(t, err) res := resp.(structs.SearchResponse) - matchedVars := res.Matches[structs.SecureVariables] + matchedVars := res.Matches[structs.Variables] require.Len(t, matchedVars, tC.expectedCount) for _, mv := range matchedVars { require.Equal(t, testPath, mv) @@ -807,7 +807,7 @@ func TestHTTP_PrefixSearch_SecureVariables_ACL(t *testing.T) { }) } -func TestHTTP_FuzzySearch_SecureVariables_ACL(t *testing.T) { +func TestHTTP_FuzzySearch_Variables_ACL(t *testing.T) { ci.Parallel(t) testPath := "alpha/beta/charlie" @@ -816,19 +816,19 @@ func TestHTTP_FuzzySearch_SecureVariables_ACL(t *testing.T) { httpACLTest(t, nil, func(s *TestAgent) { state := s.Agent.server.State() ns := mock.Namespace() - sv1 := mock.SecureVariableEncrypted() + sv1 := mock.VariableEncrypted() sv1.Path = testPath sv2 := sv1.Copy() sv2.Namespace = ns.Name require.NoError(t, state.UpsertNamespaces(7000, []*structs.Namespace{ns})) - setResp := state.SVESet(8000, &structs.SVApplyStateRequest{ - Op: structs.SVOpSet, + setResp := state.VarSet(8000, &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, Var: sv1, }) require.NoError(t, setResp.Error) - setResp = state.SVESet(8001, &structs.SVApplyStateRequest{ - Op: structs.SVOpSet, + setResp = state.VarSet(8001, &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, Var: &sv2, }) require.NoError(t, setResp.Error) @@ -891,7 +891,7 @@ func TestHTTP_FuzzySearch_SecureVariables_ACL(t *testing.T) { t.Run(tC.desc, func(t *testing.T) { data := structs.FuzzySearchRequest{ Text: testPathText, - Context: structs.SecureVariables, + Context: structs.Variables, QueryOptions: structs.QueryOptions{ AuthToken: tC.token.SecretID, Namespace: tcNS(tC), @@ -911,7 +911,7 @@ func TestHTTP_FuzzySearch_SecureVariables_ACL(t *testing.T) { } res := resp.(structs.FuzzySearchResponse) - matchedVars := res.Matches[structs.SecureVariables] + matchedVars := res.Matches[structs.Variables] require.Len(t, matchedVars, tC.expectedCount) for _, mv := range matchedVars { require.Equal(t, testPath, mv.ID) diff --git a/command/agent/variable_endpoint.go b/command/agent/variable_endpoint.go index 04d008e89..17f55ac9c 100644 --- a/command/agent/variable_endpoint.go +++ b/command/agent/variable_endpoint.go @@ -9,83 +9,83 @@ import ( "github.com/hashicorp/nomad/nomad/structs" ) -func (s *HTTPServer) SecureVariablesListRequest(resp http.ResponseWriter, req *http.Request) (interface{}, error) { +func (s *HTTPServer) VariablesListRequest(resp http.ResponseWriter, req *http.Request) (interface{}, error) { if req.Method != "GET" { return nil, CodedError(http.StatusMethodNotAllowed, ErrInvalidMethod) } - args := structs.SecureVariablesListRequest{} + args := structs.VariablesListRequest{} if s.parse(resp, req, &args.Region, &args.QueryOptions) { return nil, nil } - var out structs.SecureVariablesListResponse - if err := s.agent.RPC(structs.SecureVariablesListRPCMethod, &args, &out); err != nil { + var out structs.VariablesListResponse + if err := s.agent.RPC(structs.VariablesListRPCMethod, &args, &out); err != nil { return nil, err } setMeta(resp, &out.QueryMeta) if out.Data == nil { - out.Data = make([]*structs.SecureVariableMetadata, 0) + out.Data = make([]*structs.VariableMetadata, 0) } return out.Data, nil } -func (s *HTTPServer) SecureVariableSpecificRequest(resp http.ResponseWriter, req *http.Request) (interface{}, error) { +func (s *HTTPServer) VariableSpecificRequest(resp http.ResponseWriter, req *http.Request) (interface{}, error) { path := strings.TrimPrefix(req.URL.Path, "/v1/var/") if len(path) == 0 { - return nil, CodedError(http.StatusBadRequest, "missing secure variable path") + return nil, CodedError(http.StatusBadRequest, "missing variable path") } switch req.Method { case http.MethodGet: - return s.secureVariableQuery(resp, req, path) + return s.variableQuery(resp, req, path) case http.MethodPut, http.MethodPost: - return s.secureVariableUpsert(resp, req, path) + return s.variableUpsert(resp, req, path) case http.MethodDelete: - return s.secureVariableDelete(resp, req, path) + return s.variableDelete(resp, req, path) default: return nil, CodedError(http.StatusBadRequest, ErrInvalidMethod) } } -func (s *HTTPServer) secureVariableQuery(resp http.ResponseWriter, req *http.Request, +func (s *HTTPServer) variableQuery(resp http.ResponseWriter, req *http.Request, path string) (interface{}, error) { - args := structs.SecureVariablesReadRequest{ + args := structs.VariablesReadRequest{ Path: path, } if s.parse(resp, req, &args.Region, &args.QueryOptions) { return nil, nil } - var out structs.SecureVariablesReadResponse - if err := s.agent.RPC(structs.SecureVariablesReadRPCMethod, &args, &out); err != nil { + var out structs.VariablesReadResponse + if err := s.agent.RPC(structs.VariablesReadRPCMethod, &args, &out); err != nil { return nil, err } setMeta(resp, &out.QueryMeta) if out.Data == nil { - return nil, CodedError(http.StatusNotFound, "secure variable not found") + return nil, CodedError(http.StatusNotFound, "variable not found") } return out.Data, nil } -func (s *HTTPServer) secureVariableUpsert(resp http.ResponseWriter, req *http.Request, +func (s *HTTPServer) variableUpsert(resp http.ResponseWriter, req *http.Request, path string) (interface{}, error) { - // Parse the SecureVariable - var SecureVariable structs.SecureVariableDecrypted - if err := decodeBody(req, &SecureVariable); err != nil { + // Parse the Variable + var Variable structs.VariableDecrypted + if err := decodeBody(req, &Variable); err != nil { return nil, CodedError(http.StatusBadRequest, err.Error()) } - if len(SecureVariable.Items) == 0 { - return nil, CodedError(http.StatusBadRequest, "secure variable missing required Items object") + if len(Variable.Items) == 0 { + return nil, CodedError(http.StatusBadRequest, "variable missing required Items object") } - SecureVariable.Path = path + Variable.Path = path - args := structs.SecureVariablesApplyRequest{ - Op: structs.SVOpSet, - Var: &SecureVariable, + args := structs.VariablesApplyRequest{ + Op: structs.VarOpSet, + Var: &Variable, } s.parseWriteRequest(req, &args.WriteRequest) @@ -93,12 +93,12 @@ func (s *HTTPServer) secureVariableUpsert(resp http.ResponseWriter, req *http.Re if isCas, checkIndex, err := parseCAS(req); err != nil { return nil, err } else if isCas { - args.Op = structs.SVOpCAS + args.Op = structs.VarOpCAS args.Var.ModifyIndex = checkIndex } - var out structs.SecureVariablesApplyResponse - if err := s.agent.RPC(structs.SecureVariablesApplyRPCMethod, &args, &out); err != nil { + var out structs.VariablesApplyResponse + if err := s.agent.RPC(structs.VariablesApplyRPCMethod, &args, &out); err != nil { // This handles the cases where there is an error in the CAS checking // function that renders it unable to return the conflicting variable @@ -124,13 +124,13 @@ func (s *HTTPServer) secureVariableUpsert(resp http.ResponseWriter, req *http.Re return out.Output, nil } -func (s *HTTPServer) secureVariableDelete(resp http.ResponseWriter, req *http.Request, +func (s *HTTPServer) variableDelete(resp http.ResponseWriter, req *http.Request, path string) (interface{}, error) { - args := structs.SecureVariablesApplyRequest{ - Op: structs.SVOpDelete, - Var: &structs.SecureVariableDecrypted{ - SecureVariableMetadata: structs.SecureVariableMetadata{ + args := structs.VariablesApplyRequest{ + Op: structs.VarOpDelete, + Var: &structs.VariableDecrypted{ + VariableMetadata: structs.VariableMetadata{ Path: path, }, }, @@ -141,12 +141,12 @@ func (s *HTTPServer) secureVariableDelete(resp http.ResponseWriter, req *http.Re if isCas, checkIndex, err := parseCAS(req); err != nil { return nil, err } else if isCas { - args.Op = structs.SVOpDeleteCAS + args.Op = structs.VarOpDeleteCAS args.Var.ModifyIndex = checkIndex } - var out structs.SecureVariablesApplyResponse - if err := s.agent.RPC(structs.SecureVariablesApplyRPCMethod, &args, &out); err != nil { + var out structs.VariablesApplyResponse + if err := s.agent.RPC(structs.VariablesApplyRPCMethod, &args, &out); err != nil { // This handles the cases where there is an error in the CAS checking // function that renders it unable to return the conflicting variable diff --git a/command/agent/variable_endpoint_test.go b/command/agent/variable_endpoint_test.go index fee751334..4cda2b955 100644 --- a/command/agent/variable_endpoint_test.go +++ b/command/agent/variable_endpoint_test.go @@ -25,7 +25,7 @@ var ( } ) -func TestHTTP_SecureVariables(t *testing.T) { +func TestHTTP_Variables(t *testing.T) { ci.Parallel(t) httpTest(t, cb, func(s *TestAgent) { @@ -36,14 +36,14 @@ func TestHTTP_SecureVariables(t *testing.T) { req, err := http.NewRequest("LOLWUT", "/v1/vars", nil) require.NoError(t, err) respW := httptest.NewRecorder() - _, err = s.Server.SecureVariablesListRequest(respW, req) + _, err = s.Server.VariablesListRequest(respW, req) require.EqualError(t, err, ErrInvalidMethod) }) t.Run("error_parse_list", func(t *testing.T) { req, err := http.NewRequest("GET", "/v1/vars?wait=99a", nil) require.NoError(t, err) respW := httptest.NewRecorder() - _, _ = s.Server.SecureVariablesListRequest(respW, req) + _, _ = s.Server.VariablesListRequest(respW, req) require.Equal(t, http.StatusBadRequest, respW.Code) require.Equal(t, "Invalid wait time", string(respW.Body.Bytes())) }) @@ -51,7 +51,7 @@ func TestHTTP_SecureVariables(t *testing.T) { req, err := http.NewRequest("GET", "/v1/vars?region=bad", nil) require.NoError(t, err) respW := httptest.NewRecorder() - obj, err := s.Server.SecureVariablesListRequest(respW, req) + obj, err := s.Server.VariablesListRequest(respW, req) require.EqualError(t, err, "No path to region") require.Nil(t, obj) }) @@ -62,11 +62,11 @@ func TestHTTP_SecureVariables(t *testing.T) { respW := httptest.NewRecorder() // Make the request - obj, err := s.Server.SecureVariablesListRequest(respW, req) + obj, err := s.Server.VariablesListRequest(respW, req) require.NoError(t, err) // add vars and test a populated backend - svMap := mock.SecureVariables(4, 4) + svMap := mock.Variables(4, 4) svs := svMap.List() svs[3].Path = svs[0].Path + "/child" for _, sv := range svs { @@ -79,7 +79,7 @@ func TestHTTP_SecureVariables(t *testing.T) { respW = httptest.NewRecorder() // Make the request - obj, err = s.Server.SecureVariablesListRequest(respW, req) + obj, err = s.Server.VariablesListRequest(respW, req) require.NoError(t, err) // Check for the index @@ -88,7 +88,7 @@ func TestHTTP_SecureVariables(t *testing.T) { require.NotZero(t, respW.HeaderMap.Get("X-Nomad-LastContact")) // Check the output (the 4 we register ) - require.Len(t, obj.([]*structs.SecureVariableMetadata), 4) + require.Len(t, obj.([]*structs.VariableMetadata), 4) // test prefix query req, err = http.NewRequest("GET", "/v1/vars?prefix="+svs[0].Path, nil) @@ -96,9 +96,9 @@ func TestHTTP_SecureVariables(t *testing.T) { respW = httptest.NewRecorder() // Make the request - obj, err = s.Server.SecureVariablesListRequest(respW, req) + obj, err = s.Server.VariablesListRequest(respW, req) require.NoError(t, err) - require.Len(t, obj.([]*structs.SecureVariableMetadata), 2) + require.Len(t, obj.([]*structs.VariableMetadata), 2) }) rpcResetSV(s) @@ -106,7 +106,7 @@ func TestHTTP_SecureVariables(t *testing.T) { req, err := http.NewRequest("LOLWUT", "/v1/var/does/not/exist", nil) require.NoError(t, err) respW := httptest.NewRecorder() - obj, err := s.Server.SecureVariableSpecificRequest(respW, req) + obj, err := s.Server.VariableSpecificRequest(respW, req) require.EqualError(t, err, ErrInvalidMethod) require.Nil(t, obj) }) @@ -114,7 +114,7 @@ func TestHTTP_SecureVariables(t *testing.T) { req, err := http.NewRequest("GET", "/v1/var/does/not/exist?wait=99a", nil) require.NoError(t, err) respW := httptest.NewRecorder() - _, _ = s.Server.SecureVariableSpecificRequest(respW, req) + _, _ = s.Server.VariableSpecificRequest(respW, req) require.Equal(t, http.StatusBadRequest, respW.Code) require.Equal(t, "Invalid wait time", string(respW.Body.Bytes())) }) @@ -122,7 +122,7 @@ func TestHTTP_SecureVariables(t *testing.T) { req, err := http.NewRequest("GET", "/v1/var/does/not/exist?region=bad", nil) require.NoError(t, err) respW := httptest.NewRecorder() - obj, err := s.Server.SecureVariableSpecificRequest(respW, req) + obj, err := s.Server.VariableSpecificRequest(respW, req) require.EqualError(t, err, "No path to region") require.Nil(t, obj) }) @@ -131,8 +131,8 @@ func TestHTTP_SecureVariables(t *testing.T) { req, err := http.NewRequest("GET", "/v1/var/", nil) require.NoError(t, err) respW := httptest.NewRecorder() - obj, err := s.Server.SecureVariableSpecificRequest(respW, req) - require.EqualError(t, err, "missing secure variable path") + obj, err := s.Server.VariableSpecificRequest(respW, req) + require.EqualError(t, err, "missing variable path") require.Nil(t, obj) }) t.Run("query_unset_variable", func(t *testing.T) { @@ -140,21 +140,21 @@ func TestHTTP_SecureVariables(t *testing.T) { req, err := http.NewRequest("GET", "/v1/var/not/real", nil) require.NoError(t, err) respW := httptest.NewRecorder() - obj, err := s.Server.SecureVariableSpecificRequest(respW, req) - require.EqualError(t, err, "secure variable not found") + obj, err := s.Server.VariableSpecificRequest(respW, req) + require.EqualError(t, err, "variable not found") require.Nil(t, obj) }) t.Run("query", func(t *testing.T) { // Use RPC to make a test variable - out := new(structs.SecureVariableDecrypted) - sv1 := mock.SecureVariable() + out := new(structs.VariableDecrypted) + sv1 := mock.Variable() require.NoError(t, rpcWriteSV(s, sv1, out)) // Query a variable req, err := http.NewRequest("GET", "/v1/var/"+sv1.Path, nil) require.NoError(t, err) respW := httptest.NewRecorder() - obj, err := s.Server.SecureVariableSpecificRequest(respW, req) + obj, err := s.Server.VariableSpecificRequest(respW, req) require.NoError(t, err) // Check for the index @@ -163,17 +163,17 @@ func TestHTTP_SecureVariables(t *testing.T) { require.NotZero(t, respW.HeaderMap.Get("X-Nomad-LastContact")) // Check the output - require.Equal(t, out, obj.(*structs.SecureVariableDecrypted)) + require.Equal(t, out, obj.(*structs.VariableDecrypted)) }) rpcResetSV(s) - sv1 := mock.SecureVariable() + sv1 := mock.Variable() t.Run("error_parse_create", func(t *testing.T) { buf := encodeBrokenReq(&sv1) req, err := http.NewRequest("PUT", "/v1/var/"+sv1.Path, buf) require.NoError(t, err) respW := httptest.NewRecorder() - obj, err := s.Server.SecureVariableSpecificRequest(respW, req) + obj, err := s.Server.VariableSpecificRequest(respW, req) require.EqualError(t, err, "unexpected EOF") require.Nil(t, obj) }) @@ -182,7 +182,7 @@ func TestHTTP_SecureVariables(t *testing.T) { req, err := http.NewRequest("PUT", "/v1/var/does/not/exist?region=bad", buf) require.NoError(t, err) respW := httptest.NewRecorder() - obj, err := s.Server.SecureVariableSpecificRequest(respW, req) + obj, err := s.Server.VariableSpecificRequest(respW, req) require.EqualError(t, err, "No path to region") require.Nil(t, obj) }) @@ -193,8 +193,8 @@ func TestHTTP_SecureVariables(t *testing.T) { req, err := http.NewRequest("PUT", "/v1/var/"+sv1.Path, buf) require.NoError(t, err) respW := httptest.NewRecorder() - obj, err := s.Server.SecureVariableSpecificRequest(respW, req) - require.EqualError(t, err, "secure variable missing required Items object") + obj, err := s.Server.VariableSpecificRequest(respW, req) + require.EqualError(t, err, "variable missing required Items object") require.Nil(t, obj) }) t.Run("create", func(t *testing.T) { @@ -202,13 +202,13 @@ func TestHTTP_SecureVariables(t *testing.T) { req, err := http.NewRequest("PUT", "/v1/var/"+sv1.Path, buf) require.NoError(t, err) respW := httptest.NewRecorder() - obj, err := s.Server.SecureVariableSpecificRequest(respW, req) + obj, err := s.Server.VariableSpecificRequest(respW, req) require.NoError(t, err) - // Test the returned object and rehydrate to a SecureVariableDecrypted + // Test the returned object and rehydrate to a VariableDecrypted require.NotNil(t, obj) - sv1, ok := obj.(*structs.SecureVariableDecrypted) - require.True(t, ok, "Unable to convert obj to SecureVariableDecrypted") + sv1, ok := obj.(*structs.VariableDecrypted) + require.True(t, ok, "Unable to convert obj to VariableDecrypted") // Check for the index require.NotZero(t, respW.HeaderMap.Get("X-Nomad-Index")) @@ -235,7 +235,7 @@ func TestHTTP_SecureVariables(t *testing.T) { respW := httptest.NewRecorder() // Make the request - obj, err := s.Server.SecureVariableSpecificRequest(respW, req) + obj, err := s.Server.VariableSpecificRequest(respW, req) require.EqualError(t, err, "unexpected EOF") var cErr HTTPCodedError require.ErrorAs(t, err, &cErr) @@ -253,12 +253,12 @@ func TestHTTP_SecureVariables(t *testing.T) { respW := httptest.NewRecorder() // Make the request - obj, err := s.Server.SecureVariableSpecificRequest(respW, req) + obj, err := s.Server.VariableSpecificRequest(respW, req) require.EqualError(t, err, "No path to region") require.Nil(t, obj) }) t.Run("update", func(t *testing.T) { - sv := mock.SecureVariable() + sv := mock.Variable() require.NoError(t, rpcWriteSV(s, sv, sv)) svU := sv.Copy() @@ -270,13 +270,13 @@ func TestHTTP_SecureVariables(t *testing.T) { respW := httptest.NewRecorder() // Make the request - obj, err := s.Server.SecureVariableSpecificRequest(respW, req) + obj, err := s.Server.VariableSpecificRequest(respW, req) require.NoError(t, err) - // Test the returned object and rehydrate to a SecureVariableDecrypted + // Test the returned object and rehydrate to a VariableDecrypted require.NotNil(t, obj) - out, ok := obj.(*structs.SecureVariableDecrypted) - require.True(t, ok, "Unable to convert obj to SecureVariableDecrypted") + out, ok := obj.(*structs.VariableDecrypted) + require.True(t, ok, "Unable to convert obj to VariableDecrypted") // Check for the index require.NotZero(t, respW.HeaderMap.Get("X-Nomad-Index")) @@ -284,7 +284,7 @@ func TestHTTP_SecureVariables(t *testing.T) { { // Check that written varible does not equal the input to rule out input mutation - require.NotEqual(t, &svU.SecureVariableMetadata, out.SecureVariableMetadata) + require.NotEqual(t, &svU.VariableMetadata, out.VariableMetadata) // Update the input token with the updated metadata so that we // can use a simple equality check @@ -294,7 +294,7 @@ func TestHTTP_SecureVariables(t *testing.T) { } }) t.Run("update-cas", func(t *testing.T) { - sv := mock.SecureVariable() + sv := mock.Variable() require.NoError(t, rpcWriteSV(s, sv, sv)) svU := sv.Copy() @@ -308,14 +308,14 @@ func TestHTTP_SecureVariables(t *testing.T) { respW := httptest.NewRecorder() // Make the request - obj, err := s.Server.SecureVariableSpecificRequest(respW, req) + obj, err := s.Server.VariableSpecificRequest(respW, req) require.NoError(t, err) require.Equal(t, http.StatusConflict, respW.Result().StatusCode) // Evaluate the conflict variable require.NotNil(t, obj) - conflict, ok := obj.(*structs.SecureVariableDecrypted) - require.True(t, ok, "Expected *structs.SecureVariableDecrypted, got %T", obj) + conflict, ok := obj.(*structs.VariableDecrypted) + require.True(t, ok, "Expected *structs.VariableDecrypted, got %T", obj) require.Equal(t, conflict, sv) // Check for the index @@ -335,13 +335,13 @@ func TestHTTP_SecureVariables(t *testing.T) { respW := httptest.NewRecorder() // Make the request - obj, err := s.Server.SecureVariableSpecificRequest(respW, req) + obj, err := s.Server.VariableSpecificRequest(respW, req) require.NoError(t, err) - // Test the returned object and rehydrate to a SecureVariableDecrypted + // Test the returned object and rehydrate to a VariableDecrypted require.NotNil(t, obj) - sv1, ok := obj.(*structs.SecureVariableDecrypted) - require.True(t, ok, "Unable to convert obj to SecureVariableDecrypted") + sv1, ok := obj.(*structs.VariableDecrypted) + require.True(t, ok, "Unable to convert obj to VariableDecrypted") // Check for the index require.NotZero(t, respW.HeaderMap.Get("X-Nomad-Index")) @@ -362,13 +362,13 @@ func TestHTTP_SecureVariables(t *testing.T) { require.NotNil(t, out) require.NotEqual(t, sv, out) - require.NotEqual(t, svU.SecureVariableMetadata, out.SecureVariableMetadata) + require.NotEqual(t, svU.VariableMetadata, out.VariableMetadata) // Update the input token with the updated metadata so that we // can use a simple equality check svU.CreateIndex, svU.ModifyIndex = out.CreateIndex, out.ModifyIndex svU.CreateTime, svU.ModifyTime = out.CreateTime, out.ModifyTime - require.Equal(t, svU.SecureVariableMetadata, out.SecureVariableMetadata) + require.Equal(t, svU.VariableMetadata, out.VariableMetadata) // fmt writes sorted output of maps for testability. require.Equal(t, fmt.Sprint(svU.Items), fmt.Sprint(out.Items)) @@ -377,7 +377,7 @@ func TestHTTP_SecureVariables(t *testing.T) { rpcResetSV(s) t.Run("error_rpc_delete", func(t *testing.T) { - sv1 := mock.SecureVariable() + sv1 := mock.Variable() require.NoError(t, rpcWriteSV(s, sv1, nil)) // Make the HTTP request @@ -386,12 +386,12 @@ func TestHTTP_SecureVariables(t *testing.T) { respW := httptest.NewRecorder() // Make the request - obj, err := s.Server.SecureVariableSpecificRequest(respW, req) + obj, err := s.Server.VariableSpecificRequest(respW, req) require.EqualError(t, err, "No path to region") require.Nil(t, obj) }) t.Run("delete-cas", func(t *testing.T) { - sv := mock.SecureVariable() + sv := mock.Variable() require.NoError(t, rpcWriteSV(s, sv, nil)) sv, err := rpcReadSV(s, sv.Namespace, sv.Path) require.NoError(t, err) @@ -403,14 +403,14 @@ func TestHTTP_SecureVariables(t *testing.T) { respW := httptest.NewRecorder() // Make the request - obj, err := s.Server.SecureVariableSpecificRequest(respW, req) + obj, err := s.Server.VariableSpecificRequest(respW, req) require.NoError(t, err) require.Equal(t, http.StatusConflict, respW.Result().StatusCode) // Evaluate the conflict variable require.NotNil(t, obj) - conflict, ok := obj.(*structs.SecureVariableDecrypted) - require.True(t, ok, "Expected *structs.SecureVariableDecrypted, got %T", obj) + conflict, ok := obj.(*structs.VariableDecrypted) + require.True(t, ok, "Expected *structs.VariableDecrypted, got %T", obj) require.True(t, sv.Equals(*conflict)) // Check for the index @@ -431,7 +431,7 @@ func TestHTTP_SecureVariables(t *testing.T) { respW := httptest.NewRecorder() // Make the request - obj, err := s.Server.SecureVariableSpecificRequest(respW, req) + obj, err := s.Server.VariableSpecificRequest(respW, req) require.NoError(t, err) require.Nil(t, obj) } @@ -443,7 +443,7 @@ func TestHTTP_SecureVariables(t *testing.T) { } }) t.Run("delete", func(t *testing.T) { - sv1 := mock.SecureVariable() + sv1 := mock.Variable() require.NoError(t, rpcWriteSV(s, sv1, nil)) // Make the HTTP request @@ -452,7 +452,7 @@ func TestHTTP_SecureVariables(t *testing.T) { respW := httptest.NewRecorder() // Make the request - obj, err := s.Server.SecureVariableSpecificRequest(respW, req) + obj, err := s.Server.VariableSpecificRequest(respW, req) require.NoError(t, err) require.Nil(t, obj) @@ -479,25 +479,25 @@ func encodeBrokenReq(obj interface{}) io.ReadCloser { return ioutil.NopCloser(bytes.NewReader(b)) } -// rpcReadSV lets this test read a secure variable using the RPC endpoint -func rpcReadSV(s *TestAgent, ns, p string) (*structs.SecureVariableDecrypted, error) { - checkArgs := structs.SecureVariablesReadRequest{Path: p, QueryOptions: structs.QueryOptions{Namespace: ns, Region: "global"}} - var checkResp structs.SecureVariablesReadResponse - err := s.Agent.RPC(structs.SecureVariablesReadRPCMethod, &checkArgs, &checkResp) +// rpcReadSV lets this test read a variable using the RPC endpoint +func rpcReadSV(s *TestAgent, ns, p string) (*structs.VariableDecrypted, error) { + checkArgs := structs.VariablesReadRequest{Path: p, QueryOptions: structs.QueryOptions{Namespace: ns, Region: "global"}} + var checkResp structs.VariablesReadResponse + err := s.Agent.RPC(structs.VariablesReadRPCMethod, &checkArgs, &checkResp) return checkResp.Data, err } -// rpcWriteSV lets this test write a secure variable using the RPC endpoint -func rpcWriteSV(s *TestAgent, sv, out *structs.SecureVariableDecrypted) error { +// rpcWriteSV lets this test write a variable using the RPC endpoint +func rpcWriteSV(s *TestAgent, sv, out *structs.VariableDecrypted) error { - args := structs.SecureVariablesApplyRequest{ - Op: structs.SVOpSet, + args := structs.VariablesApplyRequest{ + Op: structs.VarOpSet, Var: sv, WriteRequest: structs.WriteRequest{Namespace: sv.Namespace, Region: "global"}, } - var resp structs.SecureVariablesApplyResponse - err := s.Agent.RPC(structs.SecureVariablesApplyRPCMethod, &args, &resp) + var resp structs.VariablesApplyResponse + err := s.Agent.RPC(structs.VariablesApplyRPCMethod, &args, &resp) if err != nil { return err } @@ -507,39 +507,39 @@ func rpcWriteSV(s *TestAgent, sv, out *structs.SecureVariableDecrypted) error { return nil } -// rpcResetSV lists all the secure variables for every namespace in the global +// rpcResetSV lists all the variables for every namespace in the global // region and deletes them using the RPC endpoints func rpcResetSV(s *TestAgent) { - var lArgs structs.SecureVariablesListRequest - var lResp structs.SecureVariablesListResponse + var lArgs structs.VariablesListRequest + var lResp structs.VariablesListResponse - lArgs = structs.SecureVariablesListRequest{ + lArgs = structs.VariablesListRequest{ QueryOptions: structs.QueryOptions{ Namespace: "*", Region: "global", }, } - err := s.Agent.RPC(structs.SecureVariablesListRPCMethod, &lArgs, &lResp) + err := s.Agent.RPC(structs.VariablesListRPCMethod, &lArgs, &lResp) require.NoError(s.T, err) - dArgs := structs.SecureVariablesApplyRequest{ - Op: structs.SVOpDelete, - Var: &structs.SecureVariableDecrypted{}, + dArgs := structs.VariablesApplyRequest{ + Op: structs.VarOpDelete, + Var: &structs.VariableDecrypted{}, WriteRequest: structs.WriteRequest{ Region: "global", }, } - var dResp structs.SecureVariablesApplyResponse + var dResp structs.VariablesApplyResponse for _, v := range lResp.Data { dArgs.Var.Path = v.Path dArgs.Var.Namespace = v.Namespace - err := s.Agent.RPC(structs.SecureVariablesApplyRPCMethod, &dArgs, &dResp) + err := s.Agent.RPC(structs.VariablesApplyRPCMethod, &dArgs, &dResp) require.NoError(s.T, err) } - err = s.Agent.RPC(structs.SecureVariablesListRPCMethod, &lArgs, &lResp) + err = s.Agent.RPC(structs.VariablesListRPCMethod, &lArgs, &lResp) require.NoError(s.T, err) require.Equal(s.T, 0, len(lResp.Data)) } diff --git a/command/commands.go b/command/commands.go index 0ddfe59f2..a69880d5d 100644 --- a/command/commands.go +++ b/command/commands.go @@ -619,28 +619,28 @@ func Commands(metaPtr *Meta, agentUi cli.Ui) map[string]cli.CommandFactory { Meta: meta, }, nil }, - "operator secure-variables keyring": func() (cli.Command, error) { - return &OperatorSecureVariablesKeyringCommand{ + "operator root keyring": func() (cli.Command, error) { + return &OperatorRootKeyringCommand{ Meta: meta, }, nil }, - "operator secure-variables keyring install": func() (cli.Command, error) { - return &OperatorSecureVariablesKeyringInstallCommand{ + "operator root keyring install": func() (cli.Command, error) { + return &OperatorRootKeyringInstallCommand{ Meta: meta, }, nil }, - "operator secure-variables keyring list": func() (cli.Command, error) { - return &OperatorSecureVariablesKeyringListCommand{ + "operator root keyring list": func() (cli.Command, error) { + return &OperatorRootKeyringListCommand{ Meta: meta, }, nil }, - "operator secure-variables keyring remove": func() (cli.Command, error) { - return &OperatorSecureVariablesKeyringRemoveCommand{ + "operator root keyring remove": func() (cli.Command, error) { + return &OperatorRootKeyringRemoveCommand{ Meta: meta, }, nil }, - "operator secure-variables keyring rotate": func() (cli.Command, error) { - return &OperatorSecureVariablesKeyringRotateCommand{ + "operator root keyring rotate": func() (cli.Command, error) { + return &OperatorRootKeyringRotateCommand{ Meta: meta, }, nil }, diff --git a/command/operator_root_keyring.go b/command/operator_root_keyring.go index 390dc9760..24a8d80cc 100644 --- a/command/operator_root_keyring.go +++ b/command/operator_root_keyring.go @@ -10,67 +10,67 @@ import ( "github.com/hashicorp/nomad/api" ) -// OperatorSecureVariablesKeyringCommand is a Command implementation -// that handles querying, installing, and removing secure variables +// OperatorRootKeyringCommand is a Command implementation +// that handles querying, installing, and removing root // encryption keys from a keyring. -type OperatorSecureVariablesKeyringCommand struct { +type OperatorRootKeyringCommand struct { Meta } -func (c *OperatorSecureVariablesKeyringCommand) Help() string { +func (c *OperatorRootKeyringCommand) Help() string { helpText := ` -Usage: nomad operator secure-variables keyring [options] +Usage: nomad operator root keyring [options] - Manages encryption keys used for storing secure variables. This command may be - used to examine active encryption keys in the cluster, rotate keys, add new - keys from backups, or remove unused keys. + Manages encryption keys used for storing variables and signing workload + identities. This command may be used to examine active encryption keys + in the cluster, rotate keys, add new keys from backups, or remove unused keys. If ACLs are enabled, all subcommands requires a management token. Rotate the encryption key: - $ nomad operator secure-variables keyring rotate + $ nomad operator root keyring rotate List all encryption key metadata: - $ nomad operator secure-variables keyring list + $ nomad operator root keyring list Remove an encryption key from the keyring: - $ nomad operator secure-variables keyring remove + $ nomad operator root keyring remove Install an encryption key from backup: - $ nomad operator secure-variables keyring install + $ nomad operator root keyring install Please see individual subcommand help for detailed usage information. ` return strings.TrimSpace(helpText) } -func (c *OperatorSecureVariablesKeyringCommand) Synopsis() string { - return "Manages secure variables encryption keys" +func (c *OperatorRootKeyringCommand) Synopsis() string { + return "Manages root encryption keys" } -func (c *OperatorSecureVariablesKeyringCommand) AutocompleteFlags() complete.Flags { +func (c *OperatorRootKeyringCommand) AutocompleteFlags() complete.Flags { return c.Meta.AutocompleteFlags(FlagSetClient) } -func (c *OperatorSecureVariablesKeyringCommand) AutocompleteArgs() complete.Predictor { +func (c *OperatorRootKeyringCommand) AutocompleteArgs() complete.Predictor { return complete.PredictNothing } -func (c *OperatorSecureVariablesKeyringCommand) Name() string { - return "secure-variables keyring" +func (c *OperatorRootKeyringCommand) Name() string { + return "root keyring" } -func (c *OperatorSecureVariablesKeyringCommand) Run(args []string) int { +func (c *OperatorRootKeyringCommand) Run(args []string) int { return cli.RunResultHelp } -// renderSecureVariablesKeysResponse is a helper for formatting the +// renderVariablesKeysResponse is a helper for formatting the // keyring API responses -func renderSecureVariablesKeysResponse(keys []*api.RootKeyMeta, verbose bool) string { +func renderVariablesKeysResponse(keys []*api.RootKeyMeta, verbose bool) string { length := fullId if !verbose { length = 8 diff --git a/command/operator_root_keyring_install.go b/command/operator_root_keyring_install.go index 4657a92a4..8f0d2d918 100644 --- a/command/operator_root_keyring_install.go +++ b/command/operator_root_keyring_install.go @@ -12,18 +12,18 @@ import ( "github.com/posener/complete" ) -// OperatorSecureVariablesKeyringInstallCommand is a Command -// implementation that handles installing secure variables encryption +// OperatorRootKeyringInstallCommand is a Command +// implementation that handles installing variables encryption // keys from a keyring. -type OperatorSecureVariablesKeyringInstallCommand struct { +type OperatorRootKeyringInstallCommand struct { Meta } -func (c *OperatorSecureVariablesKeyringInstallCommand) Help() string { +func (c *OperatorRootKeyringInstallCommand) Help() string { helpText := ` -Usage: nomad operator secure-variables keyring install [options] +Usage: nomad operator root keyring install [options] - Install a new encryption key used for storing secure variables and workload + Install a new encryption key used for storing variables and workload identity signing. The key file must be a JSON file previously written by Nomad to the keystore. The key file will be read from stdin by specifying "-", otherwise a path to the file is expected. @@ -37,26 +37,26 @@ General Options: return strings.TrimSpace(helpText) } -func (c *OperatorSecureVariablesKeyringInstallCommand) Synopsis() string { - return "Installs a secure variables encryption key" +func (c *OperatorRootKeyringInstallCommand) Synopsis() string { + return "Installs a root encryption key" } -func (c *OperatorSecureVariablesKeyringInstallCommand) AutocompleteFlags() complete.Flags { +func (c *OperatorRootKeyringInstallCommand) AutocompleteFlags() complete.Flags { return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient), complete.Flags{ "-verbose": complete.PredictNothing, }) } -func (c *OperatorSecureVariablesKeyringInstallCommand) AutocompleteArgs() complete.Predictor { +func (c *OperatorRootKeyringInstallCommand) AutocompleteArgs() complete.Predictor { return complete.PredictFiles("*.json") } -func (c *OperatorSecureVariablesKeyringInstallCommand) Name() string { - return "secure-variables keyring install" +func (c *OperatorRootKeyringInstallCommand) Name() string { + return "root keyring install" } -func (c *OperatorSecureVariablesKeyringInstallCommand) Run(args []string) int { - flags := c.Meta.FlagSet("secure-variables keyring install", FlagSetClient) +func (c *OperatorRootKeyringInstallCommand) Run(args []string) int { + flags := c.Meta.FlagSet("root keyring install", FlagSetClient) flags.Usage = func() { c.Ui.Output(c.Help()) } if err := flags.Parse(args); err != nil { diff --git a/command/operator_root_keyring_list.go b/command/operator_root_keyring_list.go index 573b12ea6..4891a56a4 100644 --- a/command/operator_root_keyring_list.go +++ b/command/operator_root_keyring_list.go @@ -7,15 +7,15 @@ import ( "github.com/posener/complete" ) -// OperatorSecureVariablesKeyringListCommand is a Command -// implementation that lists the secure variables encryption keys. -type OperatorSecureVariablesKeyringListCommand struct { +// OperatorRootKeyringListCommand is a Command +// implementation that lists the variables encryption keys. +type OperatorRootKeyringListCommand struct { Meta } -func (c *OperatorSecureVariablesKeyringListCommand) Help() string { +func (c *OperatorRootKeyringListCommand) Help() string { helpText := ` -Usage: nomad operator secure-variables keyring list [options] +Usage: nomad operator root keyring list [options] List the currently installed keys. This list returns key metadata and not sensitive key material. @@ -35,29 +35,29 @@ Keyring Options: return strings.TrimSpace(helpText) } -func (c *OperatorSecureVariablesKeyringListCommand) Synopsis() string { - return "Lists the secure variables encryption keys" +func (c *OperatorRootKeyringListCommand) Synopsis() string { + return "Lists the root encryption keys" } -func (c *OperatorSecureVariablesKeyringListCommand) AutocompleteFlags() complete.Flags { +func (c *OperatorRootKeyringListCommand) AutocompleteFlags() complete.Flags { return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient), complete.Flags{ "-verbose": complete.PredictNothing, }) } -func (c *OperatorSecureVariablesKeyringListCommand) AutocompleteArgs() complete.Predictor { +func (c *OperatorRootKeyringListCommand) AutocompleteArgs() complete.Predictor { return complete.PredictNothing } -func (c *OperatorSecureVariablesKeyringListCommand) Name() string { - return "secure-variables keyring list" +func (c *OperatorRootKeyringListCommand) Name() string { + return "root keyring list" } -func (c *OperatorSecureVariablesKeyringListCommand) Run(args []string) int { +func (c *OperatorRootKeyringListCommand) Run(args []string) int { var verbose bool - flags := c.Meta.FlagSet("secure-variables keyring list", FlagSetClient) + flags := c.Meta.FlagSet("root keyring list", FlagSetClient) flags.Usage = func() { c.Ui.Output(c.Help()) } flags.BoolVar(&verbose, "verbose", false, "") @@ -83,6 +83,6 @@ func (c *OperatorSecureVariablesKeyringListCommand) Run(args []string) int { c.Ui.Error(fmt.Sprintf("error: %s", err)) return 1 } - c.Ui.Output(renderSecureVariablesKeysResponse(resp, verbose)) + c.Ui.Output(renderVariablesKeysResponse(resp, verbose)) return 0 } diff --git a/command/operator_root_keyring_remove.go b/command/operator_root_keyring_remove.go index 43f55d1ac..a4bc86838 100644 --- a/command/operator_root_keyring_remove.go +++ b/command/operator_root_keyring_remove.go @@ -8,16 +8,16 @@ import ( "github.com/posener/complete" ) -// OperatorSecureVariablesKeyringRemoveCommand is a Command -// implementation that handles removeing secure variables encryption +// OperatorRootKeyringRemoveCommand is a Command +// implementation that handles removeing variables encryption // keys from a keyring. -type OperatorSecureVariablesKeyringRemoveCommand struct { +type OperatorRootKeyringRemoveCommand struct { Meta } -func (c *OperatorSecureVariablesKeyringRemoveCommand) Help() string { +func (c *OperatorRootKeyringRemoveCommand) Help() string { helpText := ` -Usage: nomad operator secure-variables keyring remove [options] +Usage: nomad operator root keyring remove [options] Remove an encryption key from the cluster. This operation may only be performed on keys that are not the active key. @@ -31,26 +31,26 @@ General Options: return strings.TrimSpace(helpText) } -func (c *OperatorSecureVariablesKeyringRemoveCommand) Synopsis() string { - return "Removes a secure variables encryption key" +func (c *OperatorRootKeyringRemoveCommand) Synopsis() string { + return "Removes a root encryption key" } -func (c *OperatorSecureVariablesKeyringRemoveCommand) AutocompleteFlags() complete.Flags { +func (c *OperatorRootKeyringRemoveCommand) AutocompleteFlags() complete.Flags { return c.Meta.AutocompleteFlags(FlagSetClient) } -func (c *OperatorSecureVariablesKeyringRemoveCommand) AutocompleteArgs() complete.Predictor { +func (c *OperatorRootKeyringRemoveCommand) AutocompleteArgs() complete.Predictor { return complete.PredictAnything } -func (c *OperatorSecureVariablesKeyringRemoveCommand) Name() string { - return "secure-variables keyring remove" +func (c *OperatorRootKeyringRemoveCommand) Name() string { + return "root keyring remove" } -func (c *OperatorSecureVariablesKeyringRemoveCommand) Run(args []string) int { +func (c *OperatorRootKeyringRemoveCommand) Run(args []string) int { var verbose bool - flags := c.Meta.FlagSet("secure-variables keyring remove", FlagSetClient) + flags := c.Meta.FlagSet("root keyring remove", FlagSetClient) flags.Usage = func() { c.Ui.Output(c.Help()) } flags.BoolVar(&verbose, "verbose", false, "") diff --git a/command/operator_root_keyring_rotate.go b/command/operator_root_keyring_rotate.go index 7d688c512..99fc92352 100644 --- a/command/operator_root_keyring_rotate.go +++ b/command/operator_root_keyring_rotate.go @@ -8,15 +8,15 @@ import ( "github.com/posener/complete" ) -// OperatorSecureVariablesKeyringRotateCommand is a Command -// implementation that rotates the secure variables encryption key. -type OperatorSecureVariablesKeyringRotateCommand struct { +// OperatorRootKeyringRotateCommand is a Command +// implementation that rotates the variables encryption key. +type OperatorRootKeyringRotateCommand struct { Meta } -func (c *OperatorSecureVariablesKeyringRotateCommand) Help() string { +func (c *OperatorRootKeyringRotateCommand) Help() string { helpText := ` -Usage: nomad operator secure-variables keyring rotate [options] +Usage: nomad operator root keyring rotate [options] Generate a new encryption key for all future variables. @@ -40,11 +40,11 @@ Keyring Options: return strings.TrimSpace(helpText) } -func (c *OperatorSecureVariablesKeyringRotateCommand) Synopsis() string { - return "Rotates the secure variables encryption key" +func (c *OperatorRootKeyringRotateCommand) Synopsis() string { + return "Rotates the root encryption key" } -func (c *OperatorSecureVariablesKeyringRotateCommand) AutocompleteFlags() complete.Flags { +func (c *OperatorRootKeyringRotateCommand) AutocompleteFlags() complete.Flags { return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient), complete.Flags{ "-full": complete.PredictNothing, @@ -52,18 +52,18 @@ func (c *OperatorSecureVariablesKeyringRotateCommand) AutocompleteFlags() comple }) } -func (c *OperatorSecureVariablesKeyringRotateCommand) AutocompleteArgs() complete.Predictor { +func (c *OperatorRootKeyringRotateCommand) AutocompleteArgs() complete.Predictor { return complete.PredictNothing } -func (c *OperatorSecureVariablesKeyringRotateCommand) Name() string { - return "secure-variables keyring rotate" +func (c *OperatorRootKeyringRotateCommand) Name() string { + return "root keyring rotate" } -func (c *OperatorSecureVariablesKeyringRotateCommand) Run(args []string) int { +func (c *OperatorRootKeyringRotateCommand) Run(args []string) int { var rotateFull, verbose bool - flags := c.Meta.FlagSet("secure-variables keyring rotate", FlagSetClient) + flags := c.Meta.FlagSet("root keyring rotate", FlagSetClient) flags.Usage = func() { c.Ui.Output(c.Help()) } flags.BoolVar(&rotateFull, "full", false, "full key rotation") flags.BoolVar(&verbose, "verbose", false, "") @@ -91,6 +91,6 @@ func (c *OperatorSecureVariablesKeyringRotateCommand) Run(args []string) int { c.Ui.Error(fmt.Sprintf("error: %s", err)) return 1 } - c.Ui.Output(renderSecureVariablesKeysResponse([]*api.RootKeyMeta{resp}, verbose)) + c.Ui.Output(renderVariablesKeysResponse([]*api.RootKeyMeta{resp}, verbose)) return 0 } diff --git a/command/quota_apply.go b/command/quota_apply.go index a60a01876..564adb36a 100644 --- a/command/quota_apply.go +++ b/command/quota_apply.go @@ -198,7 +198,7 @@ func parseQuotaLimits(result *[]*api.QuotaLimit, list *ast.ObjectList) error { valid := []string{ "region", "region_limit", - "secure_variables_limit", + "variables_limit", } if err := helper.CheckHCLKeys(o.Val, valid); err != nil { return err diff --git a/command/quota_init.go b/command/quota_init.go index 62254ce8e..96f3fb48c 100644 --- a/command/quota_init.go +++ b/command/quota_init.go @@ -121,7 +121,7 @@ limit { memory = 1000 memory_max = 1000 } - secure_variables_limit = 1000 + variables_limit = 1000 } `) @@ -137,7 +137,7 @@ var defaultJsonQuotaSpec = strings.TrimSpace(` "MemoryMB": 1000, "MemoryMaxMB": 1000 }, - "SecureVariablesLimit": 1000 + "VariablesLimit": 1000 } ] } diff --git a/command/quota_status.go b/command/quota_status.go index b87b839fe..543c99a80 100644 --- a/command/quota_status.go +++ b/command/quota_status.go @@ -158,7 +158,7 @@ func formatQuotaLimits(spec *api.QuotaSpec, usages map[string]*api.QuotaUsage) s sort.Sort(api.QuotaLimitSort(spec.Limits)) limits := make([]string, len(spec.Limits)+1) - limits[0] = "Region|CPU Usage|Memory Usage|Memory Max Usage|Network Usage|Secure Variables Usage" + limits[0] = "Region|CPU Usage|Memory Usage|Memory Max Usage|Network Usage|Variables Usage" i := 0 for _, specLimit := range spec.Limits { i++ @@ -186,7 +186,7 @@ func formatQuotaLimits(spec *api.QuotaSpec, usages map[string]*api.QuotaUsage) s memoryMax := fmt.Sprintf("- / %s", formatQuotaLimitInt(specLimit.RegionLimit.MemoryMaxMB)) net := fmt.Sprintf("- / %s", formatQuotaLimitInt(&specBits)) - vars := fmt.Sprintf("- / %s", formatQuotaLimitInt(specLimit.SecureVariablesLimit)) + vars := fmt.Sprintf("- / %s", formatQuotaLimitInt(specLimit.VariablesLimit)) limits[i] = fmt.Sprintf("%s|%s|%s|%s|%s|%s", specLimit.Region, cpu, memory, memoryMax, net, vars) continue } @@ -207,7 +207,7 @@ func formatQuotaLimits(spec *api.QuotaSpec, usages map[string]*api.QuotaUsage) s net = fmt.Sprintf("%d / %s", *used.RegionLimit.Networks[0].MBits, formatQuotaLimitInt(&specBits)) } - vars := fmt.Sprintf("%d / %s", orZero(used.SecureVariablesLimit), formatQuotaLimitInt(specLimit.SecureVariablesLimit)) + vars := fmt.Sprintf("%d / %s", orZero(used.VariablesLimit), formatQuotaLimitInt(specLimit.VariablesLimit)) limits[i] = fmt.Sprintf("%s|%s|%s|%s|%s|%s", specLimit.Region, cpu, memory, memoryMax, net, vars) } diff --git a/command/var.go b/command/var.go index e4541ed30..dbb3fb20c 100644 --- a/command/var.go +++ b/command/var.go @@ -16,28 +16,28 @@ func (f *VarCommand) Help() string { helpText := ` Usage: nomad var [options] [args] - This command groups subcommands for interacting with secure variables. Secure - variables allow operators to provide credentials and otherwise sensitive - material to Nomad jobs at runtime via the template stanza or directly through + This command groups subcommands for interacting with variables. Variables + allow operators to provide credentials and otherwise sensitive material to + Nomad jobs at runtime via the template stanza or directly through the Nomad API and CLI. - Users can create new secure variables; list, inspect, and delete existing - secure variables, and more. For a full guide on secure variables see: + Users can create new variables; list, inspect, and delete existing + variables, and more. For a full guide on variables see: https://www.nomadproject.io/guides/vars.html - Create a secure variable specification file: + Create a variable specification file: $ nomad var init - Upsert a secure variable: + Upsert a variable: $ nomad var put - Examine a secure variable: + Examine a variable: $ nomad var get - List existing secure variables: + List existing variables: $ nomad var list @@ -48,7 +48,7 @@ Usage: nomad var [options] [args] } func (f *VarCommand) Synopsis() string { - return "Interact with secure variables" + return "Interact with variables" } func (f *VarCommand) Name() string { return "var" } @@ -57,18 +57,18 @@ func (f *VarCommand) Run(args []string) int { return cli.RunResultHelp } -// SecureVariablePathPredictor returns a var predictor -func SecureVariablePathPredictor(factory ApiClientFactory) complete.Predictor { +// VariablePathPredictor returns a var predictor +func VariablePathPredictor(factory ApiClientFactory) complete.Predictor { return complete.PredictFunc(func(a complete.Args) []string { client, err := factory() if err != nil { return nil } - resp, _, err := client.Search().PrefixSearch(a.Last, contexts.SecureVariables, nil) + resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Variables, nil) if err != nil { return []string{} } - return resp.Matches[contexts.SecureVariables] + return resp.Matches[contexts.Variables] }) } diff --git a/command/var_init.go b/command/var_init.go index 965777e0a..df7a69a55 100644 --- a/command/var_init.go +++ b/command/var_init.go @@ -21,7 +21,7 @@ const ( DefaultJsonVarInitName = "spec.nsv.json" ) -// VarInitCommand generates a new secure variable specification +// VarInitCommand generates a new variable specification type VarInitCommand struct { Meta } @@ -30,14 +30,14 @@ func (c *VarInitCommand) Help() string { helpText := ` Usage: nomad var init - Creates an example secure variable specification file that can be used as a + Creates an example variable specification file that can be used as a starting point to customize further. If no filename is given, the default of "spec.nsv.hcl" or "spec.nsv.json" will be used. Init Options: -json - Create an example JSON secure variable specification. + Create an example JSON variable specification. -q Suppress non-error output @@ -46,7 +46,7 @@ Init Options: } func (c *VarInitCommand) Synopsis() string { - return "Create an example secure variable specification file" + return "Create an example variable specification file" } func (c *VarInitCommand) AutocompleteFlags() complete.Flags { @@ -113,7 +113,7 @@ func (c *VarInitCommand) Run(args []string) int { // Success if !quiet { c.Ui.Warn(WrapAndPrepend(TidyRawString(msgWarnKeys), 70, "")) - c.Ui.Output(fmt.Sprintf("Example secure variable specification written to %s", fileName)) + c.Ui.Output(fmt.Sprintf("Example variable specification written to %s", fileName)) } return 0 } @@ -126,17 +126,17 @@ const ( ) var defaultHclVarSpec = strings.TrimSpace(` -# A secure variable path can be specified in the specification file +# A variable path can be specified in the specification file # and will be used when writing the variable without specifying a # path in the command or when writing JSON directly to the `+"`/var/`"+` # HTTP API endpoint -# path = "path/to/variable" +# path = "path/to/variable" # The Namespace to write the variable can be included in the specification # and is the highest precedence way to set the namespace value. # namespace = "default" -# The items map is the only strictly required part of a secure variable +# The items map is the only strictly required part of a variable # specification, since path and namespace can be set via other means. It # contains the sensitive material to encrypt and store as a Nomad secure # variable. The entire items map is encrypted and decrypted as a single unit. diff --git a/command/var_list.go b/command/var_list.go index 28b6e38c3..6b174f0a0 100644 --- a/command/var_list.go +++ b/command/var_list.go @@ -11,8 +11,8 @@ import ( ) const ( - msgSecureVariableNotFound = "No matching secure variables found" - msgWarnFilterPerformance = "Filter queries require a full scan of the data; use prefix searching where possible" + msgVariableNotFound = "No matching variables found" + msgWarnFilterPerformance = "Filter queries require a full scan of the data; use prefix searching where possible" ) type VarListCommand struct { @@ -24,10 +24,10 @@ func (c *VarListCommand) Help() string { helpText := ` Usage: nomad var list [options] - List is used to list available secure variables. Supplying an optional prefix, + List is used to list available variables. Supplying an optional prefix, filters the list to variables having a path starting with the prefix. - If ACLs are enabled, this command will return only secure variables stored at + If ACLs are enabled, this command will return only variables stored at namespaced paths where the token has the ` + "`read`" + ` capability. General Options: @@ -48,13 +48,13 @@ List Options: the prefix parameter should be used whenever possible. -json - Output the secure variables in JSON format. + Output the variables in JSON format. -t - Format and display the secure variables using a Go template. + Format and display the variables using a Go template. -q - Output matching secure variable paths with no additional information. + Output matching variable paths with no additional information. This option overrides the ` + "`-t`" + ` option. ` return strings.TrimSpace(helpText) @@ -74,7 +74,7 @@ func (c *VarListCommand) AutocompleteArgs() complete.Predictor { } func (c *VarListCommand) Synopsis() string { - return "List secure variable metadata" + return "List variable metadata" } func (c *VarListCommand) Name() string { return "var list" } @@ -126,7 +126,7 @@ func (c *VarListCommand) Run(args []string) int { Params: map[string]string{}, } - vars, qm, err := client.SecureVariables().PrefixList(prefix, qo) + vars, qm, err := client.Variables().PrefixList(prefix, qo) if err != nil { c.Ui.Error(fmt.Sprintf("Error retrieving vars: %s", err)) return 1 @@ -203,9 +203,9 @@ func (c *VarListCommand) Run(args []string) int { return 0 } -func formatVarStubs(vars []*api.SecureVariableMetadata) string { +func formatVarStubs(vars []*api.VariableMetadata) string { if len(vars) == 0 { - return msgSecureVariableNotFound + return msgVariableNotFound } // Sort the output by variable namespace, path @@ -228,11 +228,11 @@ func formatVarStubs(vars []*api.SecureVariableMetadata) string { return formatList(rows) } -func dataToQuietStringSlice(vars []*api.SecureVariableMetadata, ns string) []string { +func dataToQuietStringSlice(vars []*api.VariableMetadata, ns string) []string { // If ns is the wildcard namespace, we have to provide namespace // as part of the quiet output, otherwise it can be a simple list // of paths. - toPathStr := func(v *api.SecureVariableMetadata) string { + toPathStr := func(v *api.VariableMetadata) string { if ns == "*" { return fmt.Sprintf("%s|%s", v.Namespace, v.Path) } @@ -249,7 +249,7 @@ func dataToQuietStringSlice(vars []*api.SecureVariableMetadata, ns string) []str return pList } -func dataToQuietJSONReadySlice(vars []*api.SecureVariableMetadata, ns string) interface{} { +func dataToQuietJSONReadySlice(vars []*api.VariableMetadata, ns string) interface{} { // If ns is the wildcard namespace, we have to provide namespace // as part of the quiet output, otherwise it can be a simple list // of paths. diff --git a/command/var_list_test.go b/command/var_list_test.go index 15fd44cd9..024ebeeb9 100644 --- a/command/var_list_test.go +++ b/command/var_list_test.go @@ -152,7 +152,7 @@ func TestVarListCommand_Online(t *testing.T) { { name: "plaintext/not found", args: []string{"does/not/exist"}, - expectStdOut: msgSecureVariableNotFound, + expectStdOut: msgVariableNotFound, }, { name: "plaintext/single variable", @@ -178,7 +178,7 @@ func TestVarListCommand_Online(t *testing.T) { }, { name: "plaintext/quiet/filter", - args: []string{"-q", "-filter", "SecureVariableMetadata.Path == \"a/b/c\""}, + args: []string{"-q", "-filter", "VariableMetadata.Path == \"a/b/c\""}, expectStdOut: "a/b/c", expectStdErrPrefix: msgWarnFilterPerformance, }, @@ -278,7 +278,7 @@ func TestVarListCommand_Online(t *testing.T) { }, { name: "template/filter", - args: []string{"-t", testTmpl, "-filter", "SecureVariableMetadata.Path == \"a/b/c\""}, + args: []string{"-t", testTmpl, "-filter", "VariableMetadata.Path == \"a/b/c\""}, expectStdOut: "default\ta/b/c", expectStdErrPrefix: msgWarnFilterPerformance, }, @@ -387,9 +387,9 @@ func setupTestVariables(c *api.Client, nsList, pathList []string) SVMSlice { } func setupTestVariable(c *api.Client, ns, p string, out *SVMSlice) { - testVar := &api.SecureVariable{Items: map[string]string{"k": "v"}} + testVar := &api.Variable{Items: map[string]string{"k": "v"}} c.Raw().Write("/v1/var/"+p, testVar, nil, &api.WriteOptions{Namespace: ns}) - v, _, _ := c.SecureVariables().Read(p, &api.QueryOptions{Namespace: ns}) + v, _, _ := c.Variables().Read(p, &api.QueryOptions{Namespace: ns}) *out = append(*out, *v.Metadata()) } @@ -405,7 +405,7 @@ func (ps testSVNamespacePaths) NSPaths() testSVNamespacePaths { return ps } -type SVMSlice []api.SecureVariableMetadata +type SVMSlice []api.VariableMetadata func (s SVMSlice) Len() int { return len(s) } func (s SVMSlice) NSPaths() testSVNamespacePaths { diff --git a/helper/raftutil/msgtypes.go b/helper/raftutil/msgtypes.go index 1fa74a267..73306d6aa 100644 --- a/helper/raftutil/msgtypes.go +++ b/helper/raftutil/msgtypes.go @@ -54,7 +54,7 @@ var msgTypeNames = map[structs.MessageType]string{ structs.ServiceRegistrationUpsertRequestType: "ServiceRegistrationUpsertRequestType", structs.ServiceRegistrationDeleteByIDRequestType: "ServiceRegistrationDeleteByIDRequestType", structs.ServiceRegistrationDeleteByNodeIDRequestType: "ServiceRegistrationDeleteByNodeIDRequestType", - structs.SVApplyStateRequestType: "SVApplyStateRequestType", + structs.VarApplyStateRequestType: "VarApplyStateRequestType", structs.RootKeyMetaUpsertRequestType: "RootKeyMetaUpsertRequestType", structs.RootKeyMetaDeleteRequestType: "RootKeyMetaDeleteRequestType", structs.NamespaceUpsertRequestType: "NamespaceUpsertRequestType", diff --git a/nomad/config.go b/nomad/config.go index 900b9e554..0dc4d66a1 100644 --- a/nomad/config.go +++ b/nomad/config.go @@ -205,9 +205,9 @@ type Config struct { // before it's rotated RootKeyRotationThreshold time.Duration - // SecureVariablesRekeyInterval is how often we dispatch a job to + // VariablesRekeyInterval is how often we dispatch a job to // rekey any variables associated with a key in the Rekeying state - SecureVariablesRekeyInterval time.Duration + VariablesRekeyInterval time.Duration // EvalNackTimeout controls how long we allow a sub-scheduler to // work on an evaluation before we consider it failed and Nack it. @@ -442,7 +442,7 @@ func DefaultConfig() *Config { RootKeyGCInterval: 10 * time.Minute, RootKeyGCThreshold: 1 * time.Hour, RootKeyRotationThreshold: 720 * time.Hour, // 30 days - SecureVariablesRekeyInterval: 10 * time.Minute, + VariablesRekeyInterval: 10 * time.Minute, EvalNackTimeout: 60 * time.Second, EvalDeliveryLimit: 3, EvalNackInitialReenqueueDelay: 1 * time.Second, diff --git a/nomad/core_sched.go b/nomad/core_sched.go index 89985b591..460953d07 100644 --- a/nomad/core_sched.go +++ b/nomad/core_sched.go @@ -57,8 +57,8 @@ func (c *CoreScheduler) Process(eval *structs.Evaluation) error { return c.expiredOneTimeTokenGC(eval) case structs.CoreJobRootKeyRotateOrGC: return c.rootKeyRotateOrGC(eval) - case structs.CoreJobSecureVariablesRekey: - return c.secureVariablesRekey(eval) + case structs.CoreJobVariablesRekey: + return c.variablesRekey(eval) case structs.CoreJobForceGC: return c.forceGC(eval) default: @@ -832,7 +832,7 @@ func (c *CoreScheduler) rootKeyRotateOrGC(eval *structs.Evaluation) error { if keyMeta.CreateIndex > allocOldThreshold { continue // don't GC keys possibly used to sign live allocations } - varIter, err := c.snap.GetSecureVariablesByKeyID(ws, keyMeta.KeyID) + varIter, err := c.snap.GetVariablesByKeyID(ws, keyMeta.KeyID) if err != nil { return err } @@ -891,12 +891,12 @@ func (c *CoreScheduler) rootKeyRotation(eval *structs.Evaluation) (bool, error) return true, nil } -// secureVariablesReKey is optionally run after rotating the active +// variablesReKey is optionally run after rotating the active // root key. It iterates over all the variables for the keys in the // re-keying state, decrypts them, and re-encrypts them in batches // with the currently active key. This job does not GC the keys, which // is handled in the normal periodic GC job. -func (c *CoreScheduler) secureVariablesRekey(eval *structs.Evaluation) error { +func (c *CoreScheduler) variablesRekey(eval *structs.Evaluation) error { ws := memdb.NewWatchSet() iter, err := c.snap.RootKeyMetas(ws) @@ -913,7 +913,7 @@ func (c *CoreScheduler) secureVariablesRekey(eval *structs.Evaluation) error { if !keyMeta.Rekeying() { continue } - varIter, err := c.snap.GetSecureVariablesByKeyID(ws, keyMeta.KeyID) + varIter, err := c.snap.GetVariablesByKeyID(ws, keyMeta.KeyID) if err != nil { return err } @@ -950,13 +950,13 @@ func (c *CoreScheduler) secureVariablesRekey(eval *structs.Evaluation) error { return nil } -// rotateVariables runs over an iterator of secure variables and decrypts them, -// and then sends them back to be re-encrypted with the currently active key, +// rotateVariables runs over an iterator of variables and decrypts them, and +// then sends them back to be re-encrypted with the currently active key, // checking for conflicts func (c *CoreScheduler) rotateVariables(iter memdb.ResultIterator, eval *structs.Evaluation) error { - args := &structs.SecureVariablesApplyRequest{ - Op: structs.SVOpCAS, + args := &structs.VariablesApplyRequest{ + Op: structs.VarOpCAS, WriteRequest: structs.WriteRequest{ Region: c.srv.config.Region, AuthToken: eval.LeaderACL, @@ -1007,13 +1007,13 @@ func (c *CoreScheduler) rotateVariables(iter memdb.ResultIterator, eval *structs default: } - ev := raw.(*structs.SecureVariableEncrypted) + ev := raw.(*structs.VariableEncrypted) cleartext, err := c.srv.encrypter.Decrypt(ev.Data, ev.KeyID) if err != nil { return err } - dv := &structs.SecureVariableDecrypted{ - SecureVariableMetadata: ev.SecureVariableMetadata, + dv := &structs.VariableDecrypted{ + VariableMetadata: ev.VariableMetadata, } dv.Items = make(map[string]string) err = json.Unmarshal(cleartext, &dv.Items) @@ -1021,13 +1021,13 @@ func (c *CoreScheduler) rotateVariables(iter memdb.ResultIterator, eval *structs return err } args.Var = dv - reply := &structs.SecureVariablesApplyResponse{} + reply := &structs.VariablesApplyResponse{} if err := limiter.Wait(ctx); err != nil { return err } - err = c.srv.RPC("SecureVariables.Apply", args, reply) + err = c.srv.RPC("Variables.Apply", args, reply) if err != nil { return err } diff --git a/nomad/core_sched_test.go b/nomad/core_sched_test.go index bf0d8a3b6..200eb9086 100644 --- a/nomad/core_sched_test.go +++ b/nomad/core_sched_test.go @@ -2480,11 +2480,11 @@ func TestCoreScheduler_RootKeyGC(t *testing.T) { key2.SetInactive() require.NoError(t, store.UpsertRootKeyMeta(600, key2, false)) - variable := mock.SecureVariableEncrypted() + variable := mock.VariableEncrypted() variable.KeyID = key2.KeyID - setResp := store.SVESet(601, &structs.SVApplyStateRequest{ - Op: structs.SVOpSet, + setResp := store.VarSet(601, &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, Var: variable, }) require.NoError(t, setResp.Error) @@ -2539,8 +2539,8 @@ func TestCoreScheduler_RootKeyGC(t *testing.T) { require.NotNil(t, key, "new key should not have been GCd") } -// TestCoreScheduler_SecureVariablesRekey exercises secure variables rekeying -func TestCoreScheduler_SecureVariablesRekey(t *testing.T) { +// TestCoreScheduler_VariablesRekey exercises variables rekeying +func TestCoreScheduler_VariablesRekey(t *testing.T) { ci.Parallel(t) srv, cleanup := TestServer(t, nil) @@ -2553,13 +2553,13 @@ func TestCoreScheduler_SecureVariablesRekey(t *testing.T) { require.NoError(t, err) for i := 0; i < 3; i++ { - req := &structs.SecureVariablesApplyRequest{ - Op: structs.SVOpSet, - Var: mock.SecureVariable(), + req := &structs.VariablesApplyRequest{ + Op: structs.VarOpSet, + Var: mock.Variable(), WriteRequest: structs.WriteRequest{Region: srv.config.Region}, } - resp := &structs.SecureVariablesApplyResponse{} - require.NoError(t, srv.RPC("SecureVariables.Apply", req, resp)) + resp := &structs.VariablesApplyResponse{} + require.NoError(t, srv.RPC("Variables.Apply", req, resp)) } rotateReq := &structs.KeyringRotateRootKeyRequest{ @@ -2571,13 +2571,13 @@ func TestCoreScheduler_SecureVariablesRekey(t *testing.T) { require.NoError(t, srv.RPC("Keyring.Rotate", rotateReq, &rotateResp)) for i := 0; i < 3; i++ { - req := &structs.SecureVariablesApplyRequest{ - Op: structs.SVOpSet, - Var: mock.SecureVariable(), + req := &structs.VariablesApplyRequest{ + Op: structs.VarOpSet, + Var: mock.Variable(), WriteRequest: structs.WriteRequest{Region: srv.config.Region}, } - resp := &structs.SecureVariablesApplyResponse{} - require.NoError(t, srv.RPC("SecureVariables.Apply", req, resp)) + resp := &structs.VariablesApplyResponse{} + require.NoError(t, srv.RPC("Variables.Apply", req, resp)) } rotateReq.Full = true @@ -2586,21 +2586,21 @@ func TestCoreScheduler_SecureVariablesRekey(t *testing.T) { require.Eventually(t, func() bool { ws := memdb.NewWatchSet() - iter, err := store.SecureVariables(ws) + iter, err := store.Variables(ws) require.NoError(t, err) for { raw := iter.Next() if raw == nil { break } - variable := raw.(*structs.SecureVariableEncrypted) + variable := raw.(*structs.VariableEncrypted) if variable.KeyID != newKeyID { return false } } return true }, time.Second*5, 100*time.Millisecond, - "secure variable rekey should be complete") + "variable rekey should be complete") iter, err := store.RootKeyMetas(memdb.NewWatchSet()) require.NoError(t, err) diff --git a/nomad/encrypter.go b/nomad/encrypter.go index 4a0027e80..984196b46 100644 --- a/nomad/encrypter.go +++ b/nomad/encrypter.go @@ -31,7 +31,8 @@ import ( const nomadKeystoreExtension = ".nks.json" -// Encrypter is the keyring for secure variables. +// Encrypter is the keyring for encrypting variables and signing workload +// identities. type Encrypter struct { srv *Server keystorePath string diff --git a/nomad/fsm.go b/nomad/fsm.go index 9e84ad83b..34687efdb 100644 --- a/nomad/fsm.go +++ b/nomad/fsm.go @@ -55,8 +55,8 @@ const ( ScalingEventsSnapshot SnapshotType = 19 EventSinkSnapshot SnapshotType = 20 ServiceRegistrationSnapshot SnapshotType = 21 - SecureVariablesSnapshot SnapshotType = 22 - SecureVariablesQuotaSnapshot SnapshotType = 23 + VariablesSnapshot SnapshotType = 22 + VariablesQuotaSnapshot SnapshotType = 23 RootKeyMetaSnapshot SnapshotType = 24 // Namespace appliers were moved from enterprise and therefore start at 64 @@ -317,8 +317,8 @@ func (n *nomadFSM) Apply(log *raft.Log) interface{} { return n.applyDeleteServiceRegistrationByID(msgType, buf[1:], log.Index) case structs.ServiceRegistrationDeleteByNodeIDRequestType: return n.applyDeleteServiceRegistrationByNodeID(msgType, buf[1:], log.Index) - case structs.SVApplyStateRequestType: - return n.applySecureVariableOperation(msgType, buf[1:], log.Index) + case structs.VarApplyStateRequestType: + return n.applyVariableOperation(msgType, buf[1:], log.Index) case structs.RootKeyMetaUpsertRequestType: return n.applyRootKeyMetaUpsert(msgType, buf[1:], log.Index) case structs.RootKeyMetaDeleteRequestType: @@ -1719,23 +1719,23 @@ func (n *nomadFSM) restoreImpl(old io.ReadCloser, filter *FSMFilter) error { } } - case SecureVariablesSnapshot: - variable := new(structs.SecureVariableEncrypted) + case VariablesSnapshot: + variable := new(structs.VariableEncrypted) if err := dec.Decode(variable); err != nil { return err } - if err := restore.SecureVariablesRestore(variable); err != nil { + if err := restore.VariablesRestore(variable); err != nil { return err } - case SecureVariablesQuotaSnapshot: - quota := new(structs.SecureVariablesQuota) + case VariablesQuotaSnapshot: + quota := new(structs.VariablesQuota) if err := dec.Decode(quota); err != nil { return err } - if err := restore.SecureVariablesQuotaRestore(quota); err != nil { + if err := restore.VariablesQuotaRestore(quota); err != nil { return err } @@ -2034,25 +2034,25 @@ func (f *FSMFilter) Include(item interface{}) bool { return true } -func (n *nomadFSM) applySecureVariableOperation(msgType structs.MessageType, buf []byte, index uint64) interface{} { - var req structs.SVApplyStateRequest +func (n *nomadFSM) applyVariableOperation(msgType structs.MessageType, buf []byte, index uint64) interface{} { + var req structs.VarApplyStateRequest if err := structs.Decode(buf, &req); err != nil { panic(fmt.Errorf("failed to decode request: %v", err)) } defer metrics.MeasureSinceWithLabels([]string{"nomad", "fsm", "apply_sv_operation"}, time.Now(), []metrics.Label{{Name: "op", Value: string(req.Op)}}) switch req.Op { - case structs.SVOpSet: - return n.state.SVESet(index, &req) - case structs.SVOpDelete: - return n.state.SVEDelete(index, &req) - case structs.SVOpDeleteCAS: - return n.state.SVEDeleteCAS(index, &req) - case structs.SVOpCAS: - return n.state.SVESetCAS(index, &req) + case structs.VarOpSet: + return n.state.VarSet(index, &req) + case structs.VarOpDelete: + return n.state.VarDelete(index, &req) + case structs.VarOpDeleteCAS: + return n.state.VarDeleteCAS(index, &req) + case structs.VarOpCAS: + return n.state.VarSetCAS(index, &req) default: - err := fmt.Errorf("Invalid SVE operation '%s'", req.Op) - n.logger.Warn("Invalid SVE operation", "operation", req.Op) + err := fmt.Errorf("Invalid variable operation '%s'", req.Op) + n.logger.Warn("Invalid variable operation", "operation", req.Op) return err } } @@ -2197,11 +2197,11 @@ func (s *nomadSnapshot) Persist(sink raft.SnapshotSink) error { sink.Cancel() return err } - if err := s.persistSecureVariables(sink, encoder); err != nil { + if err := s.persistVariables(sink, encoder); err != nil { sink.Cancel() return err } - if err := s.persistSecureVariablesQuotas(sink, encoder); err != nil { + if err := s.persistVariablesQuotas(sink, encoder); err != nil { sink.Cancel() return err } @@ -2767,11 +2767,11 @@ func (s *nomadSnapshot) persistServiceRegistrations(sink raft.SnapshotSink, } } -func (s *nomadSnapshot) persistSecureVariables(sink raft.SnapshotSink, +func (s *nomadSnapshot) persistVariables(sink raft.SnapshotSink, encoder *codec.Encoder) error { ws := memdb.NewWatchSet() - variables, err := s.snap.SecureVariables(ws) + variables, err := s.snap.Variables(ws) if err != nil { return err } @@ -2781,8 +2781,8 @@ func (s *nomadSnapshot) persistSecureVariables(sink raft.SnapshotSink, if raw == nil { break } - variable := raw.(*structs.SecureVariableEncrypted) - sink.Write([]byte{byte(SecureVariablesSnapshot)}) + variable := raw.(*structs.VariableEncrypted) + sink.Write([]byte{byte(VariablesSnapshot)}) if err := encoder.Encode(variable); err != nil { return err } @@ -2790,11 +2790,11 @@ func (s *nomadSnapshot) persistSecureVariables(sink raft.SnapshotSink, return nil } -func (s *nomadSnapshot) persistSecureVariablesQuotas(sink raft.SnapshotSink, +func (s *nomadSnapshot) persistVariablesQuotas(sink raft.SnapshotSink, encoder *codec.Encoder) error { ws := memdb.NewWatchSet() - quotas, err := s.snap.SecureVariablesQuotas(ws) + quotas, err := s.snap.VariablesQuotas(ws) if err != nil { return err } @@ -2804,8 +2804,8 @@ func (s *nomadSnapshot) persistSecureVariablesQuotas(sink raft.SnapshotSink, if raw == nil { break } - dirEntry := raw.(*structs.SecureVariablesQuota) - sink.Write([]byte{byte(SecureVariablesQuotaSnapshot)}) + dirEntry := raw.(*structs.VariablesQuota) + sink.Write([]byte{byte(VariablesQuotaSnapshot)}) if err := encoder.Encode(dirEntry); err != nil { return err } diff --git a/nomad/fsm_test.go b/nomad/fsm_test.go index b851300dc..5c29a8ab8 100644 --- a/nomad/fsm_test.go +++ b/nomad/fsm_test.go @@ -3368,31 +3368,31 @@ func TestFSM_DeleteServiceRegistrationsByNodeID(t *testing.T) { assert.Nil(t, out) } -func TestFSM_SnapshotRestore_SecureVariables(t *testing.T) { +func TestFSM_SnapshotRestore_Variables(t *testing.T) { ci.Parallel(t) // Create our initial FSM which will be snapshotted. fsm := testFSM(t) testState := fsm.State() - // Generate and upsert some secure variables. - msvs := mock.SecureVariablesEncrypted(3, 3) + // Generate and upsert some variables. + msvs := mock.VariablesEncrypted(3, 3) svs := msvs.List() for _, sv := range svs { - setResp := testState.SVESet(10, &structs.SVApplyStateRequest{ - Op: structs.SVOpSet, + setResp := testState.VarSet(10, &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, Var: sv, }) require.NoError(t, setResp.Error) } - // Update the mock secure variables data with the actual create information - iter, err := testState.SecureVariables(memdb.NewWatchSet()) + // Update the mock variables data with the actual create information + iter, err := testState.Variables(memdb.NewWatchSet()) require.NoError(t, err) for raw := iter.Next(); raw != nil; raw = iter.Next() { - sv := raw.(*structs.SecureVariableEncrypted) + sv := raw.(*structs.VariableEncrypted) msvs[sv.Path].CreateIndex = sv.CreateIndex msvs[sv.Path].CreateTime = sv.CreateTime msvs[sv.Path].ModifyIndex = sv.ModifyIndex @@ -3400,22 +3400,22 @@ func TestFSM_SnapshotRestore_SecureVariables(t *testing.T) { } svs = msvs.List() - // List the secure variables from restored state and ensure everything + // List the variables from restored state and ensure everything // is as expected. // Perform a snapshot restore. restoredFSM := testSnapshotRestore(t, fsm) restoredState := restoredFSM.State() - // List the secure variables from restored state and ensure everything + // List the variables from restored state and ensure everything // is as expected. - iter, err = restoredState.SecureVariables(memdb.NewWatchSet()) + iter, err = restoredState.Variables(memdb.NewWatchSet()) require.NoError(t, err) - var restoredSVs []*structs.SecureVariableEncrypted + var restoredSVs []*structs.VariableEncrypted for raw := iter.Next(); raw != nil; raw = iter.Next() { - restoredSVs = append(restoredSVs, raw.(*structs.SecureVariableEncrypted)) + restoredSVs = append(restoredSVs, raw.(*structs.VariableEncrypted)) } require.ElementsMatch(t, restoredSVs, svs) } diff --git a/nomad/keyring_endpoint.go b/nomad/keyring_endpoint.go index df0e3f000..78d4808ce 100644 --- a/nomad/keyring_endpoint.go +++ b/nomad/keyring_endpoint.go @@ -13,7 +13,7 @@ import ( "github.com/hashicorp/nomad/nomad/structs" ) -// Keyring endpoint serves RPCs for secure variables key management +// Keyring endpoint serves RPCs for root key management type Keyring struct { srv *Server logger hclog.Logger @@ -78,7 +78,7 @@ func (k *Keyring) Rotate(args *structs.KeyringRotateRootKeyRequest, reply *struc Priority: structs.CoreJobPriority, Type: structs.JobTypeCore, TriggeredBy: structs.EvalTriggerJobRegister, - JobID: structs.CoreJobSecureVariablesRekey, + JobID: structs.CoreJobVariablesRekey, Status: structs.EvalStatusPending, ModifyIndex: index, LeaderACL: k.srv.getLeaderAcl(), diff --git a/nomad/leader.go b/nomad/leader.go index 412251c77..de3d63066 100644 --- a/nomad/leader.go +++ b/nomad/leader.go @@ -769,8 +769,8 @@ func (s *Server) schedulePeriodic(stopCh chan struct{}) { defer oneTimeTokenGC.Stop() rootKeyGC := time.NewTicker(s.config.RootKeyGCInterval) defer rootKeyGC.Stop() - secureVariablesRekey := time.NewTicker(s.config.SecureVariablesRekeyInterval) - defer secureVariablesRekey.Stop() + variablesRekey := time.NewTicker(s.config.VariablesRekeyInterval) + defer variablesRekey.Stop() // getLatest grabs the latest index from the state store. It returns true if // the index was retrieved successfully. @@ -823,9 +823,9 @@ func (s *Server) schedulePeriodic(stopCh chan struct{}) { if index, ok := getLatest(); ok { s.evalBroker.Enqueue(s.coreJobEval(structs.CoreJobRootKeyRotateOrGC, index)) } - case <-secureVariablesRekey.C: + case <-variablesRekey.C: if index, ok := getLatest(); ok { - s.evalBroker.Enqueue(s.coreJobEval(structs.CoreJobSecureVariablesRekey, index)) + s.evalBroker.Enqueue(s.coreJobEval(structs.CoreJobVariablesRekey, index)) } case <-stopCh: diff --git a/nomad/mock/acl.go b/nomad/mock/acl.go index 71afd9007..07d1f69b3 100644 --- a/nomad/mock/acl.go +++ b/nomad/mock/acl.go @@ -40,7 +40,7 @@ func NamespacePolicy(namespace string, policy string, capabilities []string) str // NamespacePolicy is a helper for generating the policy hcl for a given // namespace. Either policy or capabilities may be nil but not both. -func NamespacePolicyWithSecureVariables(namespace string, policy string, capabilities []string, svars map[string][]string) string { +func NamespacePolicyWithVariables(namespace string, policy string, capabilities []string, svars map[string][]string) string { policyHCL := fmt.Sprintf("namespace %q {", namespace) if policy != "" { policyHCL += fmt.Sprintf("\n\tpolicy = %q", policy) @@ -54,17 +54,17 @@ func NamespacePolicyWithSecureVariables(namespace string, policy string, capabil policyHCL += fmt.Sprintf("\n\tcapabilities = [%v]", strings.Join(capabilities, ",")) } - policyHCL += SecureVariablePolicy(svars) + policyHCL += VariablePolicy(svars) policyHCL += "\n}" return policyHCL } -// SecureVariablePolicy is a helper for generating the policy hcl for a given -// secure_variable block inside of a namespace. -func SecureVariablePolicy(svars map[string][]string) string { +// VariablePolicy is a helper for generating the policy hcl for a given +// variable block inside of a namespace. +func VariablePolicy(svars map[string][]string) string { policyHCL := "" if len(svars) > 0 { - policyHCL = "\n\n\tsecure_variables {" + policyHCL = "\n\n\tvariables {" for p, c := range svars { for i, s := range c { if !strings.HasPrefix(s, "\"") { diff --git a/nomad/mock/mock.go b/nomad/mock/mock.go index d5df8d285..bf7bba02f 100644 --- a/nomad/mock/mock.go +++ b/nomad/mock/mock.go @@ -2372,21 +2372,21 @@ func ServiceRegistrations() []*structs.ServiceRegistration { } } -type MockSecureVariables map[string]*structs.SecureVariableDecrypted +type MockVariables map[string]*structs.VariableDecrypted -func SecureVariable() *structs.SecureVariableDecrypted { - return &structs.SecureVariableDecrypted{ - SecureVariableMetadata: mockSecureVariableMetadata(), - Items: structs.SecureVariableItems{ +func Variable() *structs.VariableDecrypted { + return &structs.VariableDecrypted{ + VariableMetadata: mockVariableMetadata(), + Items: structs.VariableItems{ "key1": "value1", "key2": "value2", }, } } -// SecureVariables returns a random number of secure variables between min +// Variables returns a random number of variables between min // and max inclusive. -func SecureVariables(minU, maxU uint8) MockSecureVariables { +func Variables(minU, maxU uint8) MockVariables { // the unsignedness of the args is to prevent goofy parameters, they're // easier to work with as ints in this code. min := int(minU) @@ -2396,12 +2396,12 @@ func SecureVariables(minU, maxU uint8) MockSecureVariables { if max > min { vc = rand.Intn(max-min) + min } - svs := make([]*structs.SecureVariableDecrypted, vc) - paths := make(map[string]*structs.SecureVariableDecrypted, vc) + svs := make([]*structs.VariableDecrypted, vc) + paths := make(map[string]*structs.VariableDecrypted, vc) for i := 0; i < vc; i++ { - nv := SecureVariable() + nv := Variable() // There is an extremely rare chance of path collision because the mock - // secure variables generate their paths randomly. This check will add + // variables generate their paths randomly. This check will add // an extra component on conflict to (ideally) disambiguate them. if _, found := paths[nv.Path]; found { nv.Path = nv.Path + "/" + fmt.Sprint(time.Now().UnixNano()) @@ -2412,7 +2412,7 @@ func SecureVariables(minU, maxU uint8) MockSecureVariables { return paths } -func (svs MockSecureVariables) ListPaths() []string { +func (svs MockVariables) ListPaths() []string { out := make([]string, 0, len(svs)) for _, sv := range svs { out = append(out, sv.Path) @@ -2421,8 +2421,8 @@ func (svs MockSecureVariables) ListPaths() []string { return out } -func (svs MockSecureVariables) List() []*structs.SecureVariableDecrypted { - out := make([]*structs.SecureVariableDecrypted, 0, len(svs)) +func (svs MockVariables) List() []*structs.VariableDecrypted { + out := make([]*structs.VariableDecrypted, 0, len(svs)) for _, p := range svs.ListPaths() { pc := svs[p].Copy() out = append(out, &pc) @@ -2430,21 +2430,21 @@ func (svs MockSecureVariables) List() []*structs.SecureVariableDecrypted { return out } -type MockSecureVariablesEncrypted map[string]*structs.SecureVariableEncrypted +type MockVariablesEncrypted map[string]*structs.VariableEncrypted -func SecureVariableEncrypted() *structs.SecureVariableEncrypted { - return &structs.SecureVariableEncrypted{ - SecureVariableMetadata: mockSecureVariableMetadata(), - SecureVariableData: structs.SecureVariableData{ +func VariableEncrypted() *structs.VariableEncrypted { + return &structs.VariableEncrypted{ + VariableMetadata: mockVariableMetadata(), + VariableData: structs.VariableData{ KeyID: "foo", Data: []byte("foo"), }, } } -// SecureVariables returns a random number of secure variables between min +// Variables returns a random number of variables between min // and max inclusive. -func SecureVariablesEncrypted(minU, maxU uint8) MockSecureVariablesEncrypted { +func VariablesEncrypted(minU, maxU uint8) MockVariablesEncrypted { // the unsignedness of the args is to prevent goofy parameters, they're // easier to work with as ints in this code. min := int(minU) @@ -2454,12 +2454,12 @@ func SecureVariablesEncrypted(minU, maxU uint8) MockSecureVariablesEncrypted { if max > min { vc = rand.Intn(max-min) + min } - svs := make([]*structs.SecureVariableEncrypted, vc) - paths := make(map[string]*structs.SecureVariableEncrypted, vc) + svs := make([]*structs.VariableEncrypted, vc) + paths := make(map[string]*structs.VariableEncrypted, vc) for i := 0; i < vc; i++ { - nv := SecureVariableEncrypted() + nv := VariableEncrypted() // There is an extremely rare chance of path collision because the mock - // secure variables generate their paths randomly. This check will add + // variables generate their paths randomly. This check will add // an extra component on conflict to (ideally) disambiguate them. if _, found := paths[nv.Path]; found { nv.Path = nv.Path + "/" + fmt.Sprint(time.Now().UnixNano()) @@ -2470,7 +2470,7 @@ func SecureVariablesEncrypted(minU, maxU uint8) MockSecureVariablesEncrypted { return paths } -func (svs MockSecureVariablesEncrypted) ListPaths() []string { +func (svs MockVariablesEncrypted) ListPaths() []string { out := make([]string, 0, len(svs)) for _, sv := range svs { out = append(out, sv.Path) @@ -2479,8 +2479,8 @@ func (svs MockSecureVariablesEncrypted) ListPaths() []string { return out } -func (svs MockSecureVariablesEncrypted) List() []*structs.SecureVariableEncrypted { - out := make([]*structs.SecureVariableEncrypted, 0, len(svs)) +func (svs MockVariablesEncrypted) List() []*structs.VariableEncrypted { + out := make([]*structs.VariableEncrypted, 0, len(svs)) for _, p := range svs.ListPaths() { pc := svs[p].Copy() out = append(out, &pc) @@ -2488,13 +2488,13 @@ func (svs MockSecureVariablesEncrypted) List() []*structs.SecureVariableEncrypte return out } -func mockSecureVariableMetadata() structs.SecureVariableMetadata { +func mockVariableMetadata() structs.VariableMetadata { envs := []string{"dev", "test", "prod"} envIdx := rand.Intn(3) env := envs[envIdx] domain := fake.DomainName() - out := structs.SecureVariableMetadata{ + out := structs.VariableMetadata{ Namespace: "default", Path: strings.ReplaceAll(env+"."+domain, ".", "/"), CreateIndex: uint64(rand.Intn(100) + 100), diff --git a/nomad/search_endpoint.go b/nomad/search_endpoint.go index 86b4b861e..33def9374 100644 --- a/nomad/search_endpoint.go +++ b/nomad/search_endpoint.go @@ -35,7 +35,7 @@ var ( structs.Plugins, structs.Volumes, structs.ScalingPolicies, - structs.SecureVariables, + structs.Variables, structs.Namespaces, } ) @@ -77,7 +77,7 @@ func (s *Search) getPrefixMatches(iter memdb.ResultIterator, prefix string) ([]s id = t.ID case *structs.Namespace: id = t.Name - case *structs.SecureVariableEncrypted: + case *structs.VariableEncrypted: id = t.Path default: matchID, ok := getEnterpriseMatch(raw) @@ -218,10 +218,10 @@ func (s *Search) fuzzyMatchSingle(raw interface{}, text string) (structs.Context case *structs.CSIPlugin: name = t.ID ctx = structs.Plugins - case *structs.SecureVariableEncrypted: + case *structs.VariableEncrypted: name = t.Path scope = []string{t.Namespace, t.Path} - ctx = structs.SecureVariables + ctx = structs.Variables } if idx := fuzzyIndex(name, text); idx >= 0 { @@ -390,8 +390,8 @@ func getResourceIter(context structs.Context, aclObj *acl.ACL, namespace, prefix return iter, nil } return memdb.NewFilterIterator(iter, nsCapFilter(aclObj)), nil - case structs.SecureVariables: - iter, err := store.GetSecureVariablesByPrefix(ws, prefix) + case structs.Variables: + iter, err := store.GetVariablesByPrefix(ws, prefix) if err != nil { return nil, err } @@ -427,12 +427,12 @@ func getFuzzyResourceIterator(context structs.Context, aclObj *acl.ACL, namespac } return store.AllocsByNamespace(ws, namespace) - case structs.SecureVariables: + case structs.Variables: if wildcard(namespace) { - iter, err := store.SecureVariables(ws) + iter, err := store.Variables(ws) return nsCapIterFilter(iter, err, aclObj) } - return store.GetSecureVariablesByNamespace(ws, namespace) + return store.GetVariablesByNamespace(ws, namespace) case structs.Nodes: if wildcard(namespace) { @@ -481,7 +481,7 @@ func nsCapFilter(aclObj *acl.ACL) memdb.FilterFunc { case *structs.Allocation: return !aclObj.AllowNsOp(t.Namespace, acl.NamespaceCapabilityReadJob) - case *structs.SecureVariableEncrypted: + case *structs.VariableEncrypted: // FIXME: Update to final implementation. return !aclObj.AllowNsOp(t.Namespace, acl.NamespaceCapabilityReadJob) @@ -643,8 +643,8 @@ func sufficientSearchPerms(aclObj *acl.ACL, namespace string, context structs.Co acl.NamespaceCapabilityCSIReadVolume, acl.NamespaceCapabilityListJobs, acl.NamespaceCapabilityReadJob)(aclObj, namespace) - case structs.SecureVariables: - return aclObj.AllowSecureVariableSearch(namespace) + case structs.Variables: + return aclObj.AllowVariableSearch(namespace) } return true @@ -864,7 +864,7 @@ func filteredSearchContexts(aclObj *acl.ACL, namespace string, context structs.C if aclObj.AllowNamespace(namespace) { available = append(available, c) } - case structs.SecureVariables: + case structs.Variables: if jobRead { available = append(available, c) } diff --git a/nomad/search_endpoint_oss.go b/nomad/search_endpoint_oss.go index a9410db2f..f35f52886 100644 --- a/nomad/search_endpoint_oss.go +++ b/nomad/search_endpoint_oss.go @@ -22,8 +22,8 @@ var ( func contextToIndex(ctx structs.Context) string { switch ctx { // Handle cases where context name and state store table name do not match - case structs.SecureVariables: - return state.TableSecureVariables + case structs.Variables: + return state.TableVariables default: return string(ctx) } diff --git a/nomad/server.go b/nomad/server.go index 948f4362f..1fca7622a 100644 --- a/nomad/server.go +++ b/nomad/server.go @@ -215,11 +215,12 @@ type Server struct { // volumeWatcher is used to release volume claims volumeWatcher *volumewatcher.Watcher - // keyringReplicator is used to replicate encryption keys for - // secure variables from the leader + // keyringReplicator is used to replicate root encryption keys from the + // leader keyringReplicator *KeyringReplicator - // encrypter is the keyring for secure variables + // encrypter is the root keyring for encrypting variables and signing + // workload identities encrypter *Encrypter // periodicDispatcher is used to track and create evaluations for periodic jobs. @@ -297,7 +298,7 @@ type endpoints struct { Enterprise *EnterpriseEndpoints Event *Event Namespace *Namespace - SecureVariables *SecureVariables + Variables *Variables Keyring *Keyring ServiceRegistration *ServiceRegistration @@ -1211,7 +1212,7 @@ func (s *Server) setupRpcServer(server *rpc.Server, ctx *RPCContext) error { s.staticEndpoints.System = &System{srv: s, logger: s.logger.Named("system")} s.staticEndpoints.Search = &Search{srv: s, logger: s.logger.Named("search")} s.staticEndpoints.Namespace = &Namespace{srv: s} - s.staticEndpoints.SecureVariables = &SecureVariables{srv: s, logger: s.logger.Named("secure_variables"), encrypter: s.encrypter} + s.staticEndpoints.Variables = &Variables{srv: s, logger: s.logger.Named("variables"), encrypter: s.encrypter} s.staticEndpoints.Keyring = &Keyring{srv: s, logger: s.logger.Named("keyring"), encrypter: s.encrypter} s.staticEndpoints.Enterprise = NewEnterpriseEndpoints(s) @@ -1261,7 +1262,7 @@ func (s *Server) setupRpcServer(server *rpc.Server, ctx *RPCContext) error { server.Register(s.staticEndpoints.FileSystem) server.Register(s.staticEndpoints.Agent) server.Register(s.staticEndpoints.Namespace) - server.Register(s.staticEndpoints.SecureVariables) + server.Register(s.staticEndpoints.Variables) // Create new dynamic endpoints and add them to the RPC server. alloc := &Alloc{srv: s, ctx: ctx, logger: s.logger.Named("alloc")} diff --git a/nomad/state/schema.go b/nomad/state/schema.go index e966d89c6..6eeb383f3 100644 --- a/nomad/state/schema.go +++ b/nomad/state/schema.go @@ -12,11 +12,11 @@ import ( const ( tableIndex = "index" - TableNamespaces = "namespaces" - TableServiceRegistrations = "service_registrations" - TableSecureVariables = "secure_variables" - TableSecureVariablesQuotas = "secure_variables_quota" - TableRootKeyMeta = "secure_variables_root_key_meta" + TableNamespaces = "namespaces" + TableServiceRegistrations = "service_registrations" + TableVariables = "variables" + TableVariablesQuotas = "variables_quota" + TableRootKeyMeta = "root_key_meta" ) const ( @@ -75,9 +75,9 @@ func init() { scalingEventTableSchema, namespaceTableSchema, serviceRegistrationsTableSchema, - secureVariablesTableSchema, - secureVariablesQuotasTableSchema, - secureVariablesRootKeyMetaSchema, + variablesTableSchema, + variablesQuotasTableSchema, + variablesRootKeyMetaSchema, }...) } @@ -1281,11 +1281,10 @@ func serviceRegistrationsTableSchema() *memdb.TableSchema { } } -// secureVariablesTableSchema returns the MemDB schema for Nomad -// secure variables. -func secureVariablesTableSchema() *memdb.TableSchema { +// variablesTableSchema returns the MemDB schema for Nomad variables. +func variablesTableSchema() *memdb.TableSchema { return &memdb.TableSchema{ - Name: TableSecureVariables, + Name: TableVariables, Indexes: map[string]*memdb.IndexSchema{ indexID: { Name: indexID, @@ -1305,7 +1304,7 @@ func secureVariablesTableSchema() *memdb.TableSchema { indexKeyID: { Name: indexKeyID, AllowMissing: false, - Indexer: &secureVariableKeyIDFieldIndexer{}, + Indexer: &variableKeyIDFieldIndexer{}, }, indexPath: { Name: indexPath, @@ -1319,11 +1318,11 @@ func secureVariablesTableSchema() *memdb.TableSchema { } } -type secureVariableKeyIDFieldIndexer struct{} +type variableKeyIDFieldIndexer struct{} // FromArgs implements go-memdb/Indexer and is used to build an exact // index lookup based on arguments -func (s *secureVariableKeyIDFieldIndexer) FromArgs(args ...interface{}) ([]byte, error) { +func (s *variableKeyIDFieldIndexer) FromArgs(args ...interface{}) ([]byte, error) { if len(args) != 1 { return nil, fmt.Errorf("must provide only a single argument") } @@ -1338,7 +1337,7 @@ func (s *secureVariableKeyIDFieldIndexer) FromArgs(args ...interface{}) ([]byte, // PrefixFromArgs implements go-memdb/PrefixIndexer and returns a // prefix that should be used for scanning based on the arguments -func (s *secureVariableKeyIDFieldIndexer) PrefixFromArgs(args ...interface{}) ([]byte, error) { +func (s *variableKeyIDFieldIndexer) PrefixFromArgs(args ...interface{}) ([]byte, error) { val, err := s.FromArgs(args...) if err != nil { return nil, err @@ -1355,10 +1354,10 @@ func (s *secureVariableKeyIDFieldIndexer) PrefixFromArgs(args ...interface{}) ([ // FromObject implements go-memdb/SingleIndexer and is used to extract // an index value from an object or to indicate that the index value // is missing. -func (s *secureVariableKeyIDFieldIndexer) FromObject(obj interface{}) (bool, []byte, error) { - variable, ok := obj.(*structs.SecureVariableEncrypted) +func (s *variableKeyIDFieldIndexer) FromObject(obj interface{}) (bool, []byte, error) { + variable, ok := obj.(*structs.VariableEncrypted) if !ok { - return false, nil, fmt.Errorf("object %#v is not a SecureVariable", obj) + return false, nil, fmt.Errorf("object %#v is not a Variable", obj) } keyID := variable.KeyID @@ -1371,11 +1370,11 @@ func (s *secureVariableKeyIDFieldIndexer) FromObject(obj interface{}) (bool, []b return true, []byte(keyID), nil } -// secureVariablesQuotasTableSchema returns the MemDB schema for Nomad -// secure variables quotas tracking -func secureVariablesQuotasTableSchema() *memdb.TableSchema { +// variablesQuotasTableSchema returns the MemDB schema for Nomad variables +// quotas tracking +func variablesQuotasTableSchema() *memdb.TableSchema { return &memdb.TableSchema{ - Name: TableSecureVariablesQuotas, + Name: TableVariablesQuotas, Indexes: map[string]*memdb.IndexSchema{ indexID: { Name: indexID, @@ -1390,9 +1389,8 @@ func secureVariablesQuotasTableSchema() *memdb.TableSchema { } } -// secureVariablesRootKeyMetaSchema returns the MemDB schema for Nomad -// secure variables root keys -func secureVariablesRootKeyMetaSchema() *memdb.TableSchema { +// variablesRootKeyMetaSchema returns the MemDB schema for Nomad root keys +func variablesRootKeyMetaSchema() *memdb.TableSchema { return &memdb.TableSchema{ Name: TableRootKeyMeta, Indexes: map[string]*memdb.IndexSchema{ diff --git a/nomad/state/state_store.go b/nomad/state/state_store.go index 4861392ac..596dc66db 100644 --- a/nomad/state/state_store.go +++ b/nomad/state/state_store.go @@ -6366,15 +6366,15 @@ func (s *StateStore) DeleteNamespaces(index uint64, names []string) error { "All CSI volumes in namespace must be deleted before it can be deleted", name, vol.ID) } - varIter, err := s.getSecureVariablesByNamespaceImpl(txn, nil, name) + varIter, err := s.getVariablesByNamespaceImpl(txn, nil, name) if err != nil { return err } if varIter.Next() != nil { // unlike job/volume, don't show the path here because the user may - // not have List permissions on the secure vars in this namespace - return fmt.Errorf("namespace %q contains at least one secure variable. "+ - "All secure variables in namespace must be deleted before it can be deleted", name) + // not have List permissions on the vars in this namespace + return fmt.Errorf("namespace %q contains at least one variable. "+ + "All variables in namespace must be deleted before it can be deleted", name) } // Delete the namespace diff --git a/nomad/state/state_store_restore.go b/nomad/state/state_store_restore.go index a746d0aa5..dcfe0be69 100644 --- a/nomad/state/state_store_restore.go +++ b/nomad/state/state_store_restore.go @@ -198,26 +198,26 @@ func (r *StateRestore) ServiceRegistrationRestore(service *structs.ServiceRegist return nil } -// SecureVariablesRestore is used to restore a single secure variable -// into the secure_variables table. -func (r *StateRestore) SecureVariablesRestore(variable *structs.SecureVariableEncrypted) error { - if err := r.txn.Insert(TableSecureVariables, variable); err != nil { - return fmt.Errorf("secure variable insert failed: %v", err) +// VariablesRestore is used to restore a single variable into the variables +// table. +func (r *StateRestore) VariablesRestore(variable *structs.VariableEncrypted) error { + if err := r.txn.Insert(TableVariables, variable); err != nil { + return fmt.Errorf("variable insert failed: %v", err) } return nil } -// SecureVariablesQuotaRestore is used to restore a single secure variable quota -// into the secure_variables_quota table. -func (r *StateRestore) SecureVariablesQuotaRestore(quota *structs.SecureVariablesQuota) error { - if err := r.txn.Insert(TableSecureVariablesQuotas, quota); err != nil { - return fmt.Errorf("secure variable quota insert failed: %v", err) +// VariablesQuotaRestore is used to restore a single variable quota into the +// variables_quota table. +func (r *StateRestore) VariablesQuotaRestore(quota *structs.VariablesQuota) error { + if err := r.txn.Insert(TableVariablesQuotas, quota); err != nil { + return fmt.Errorf("variable quota insert failed: %v", err) } return nil } -// RootKeyMetaQuotaRestore is used to restore a single root key meta -// into the secure_variables_root_key_meta table. +// RootKeyMetaQuotaRestore is used to restore a single root key meta into the +// root_key_meta table. func (r *StateRestore) RootKeyMetaRestore(quota *structs.RootKeyMeta) error { if err := r.txn.Insert(TableRootKeyMeta, quota); err != nil { return fmt.Errorf("root key meta insert failed: %v", err) diff --git a/nomad/state/state_store_restore_test.go b/nomad/state/state_store_restore_test.go index 4574ee495..0063f2907 100644 --- a/nomad/state/state_store_restore_test.go +++ b/nomad/state/state_store_restore_test.go @@ -574,13 +574,13 @@ func TestStateStore_ServiceRegistrationRestore(t *testing.T) { } } -func TestStateStore_SecureVariablesRestore(t *testing.T) { +func TestStateStore_VariablesRestore(t *testing.T) { ci.Parallel(t) testState := testStateStore(t) // Set up our test variables and index. expectedIndex := uint64(13) - svs := mock.SecureVariablesEncrypted(5, 5) + svs := mock.VariablesEncrypted(5, 5) restore, err := testState.Restore() require.NoError(t, err) @@ -590,7 +590,7 @@ func TestStateStore_SecureVariablesRestore(t *testing.T) { for i := range svs { svs[i].ModifyIndex = expectedIndex svs[i].CreateIndex = expectedIndex - require.NoError(t, restore.SecureVariablesRestore(svs[i])) + require.NoError(t, restore.VariablesRestore(svs[i])) } require.NoError(t, restore.Commit()) @@ -599,7 +599,7 @@ func TestStateStore_SecureVariablesRestore(t *testing.T) { ws := memdb.NewWatchSet() for i := range svs { - out, err := testState.GetSecureVariable(ws, svs[i].Namespace, svs[i].Path) + out, err := testState.GetVariable(ws, svs[i].Namespace, svs[i].Path) require.NoError(t, err) require.Equal(t, svs[i], out) } diff --git a/nomad/state/state_store_test.go b/nomad/state/state_store_test.go index 739c7d2db..35ba81b1d 100644 --- a/nomad/state/state_store_test.go +++ b/nomad/state/state_store_test.go @@ -1044,7 +1044,7 @@ func TestStateStore_DeleteNamespaces_CSIVolumes(t *testing.T) { require.False(t, watchFired(ws)) } -func TestStateStore_DeleteNamespaces_SecureVariables(t *testing.T) { +func TestStateStore_DeleteNamespaces_Variables(t *testing.T) { ci.Parallel(t) state := testStateStore(t) @@ -1052,11 +1052,11 @@ func TestStateStore_DeleteNamespaces_SecureVariables(t *testing.T) { ns := mock.Namespace() require.NoError(t, state.UpsertNamespaces(1000, []*structs.Namespace{ns})) - sv := mock.SecureVariableEncrypted() + sv := mock.VariableEncrypted() sv.Namespace = ns.Name - resp := state.SVESet(1001, &structs.SVApplyStateRequest{ - Op: structs.SVOpSet, + resp := state.VarSet(1001, &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, Var: sv, }) require.NoError(t, resp.Error) @@ -1068,7 +1068,7 @@ func TestStateStore_DeleteNamespaces_SecureVariables(t *testing.T) { err = state.DeleteNamespaces(1002, []string{ns.Name}) require.Error(t, err) - require.Contains(t, err.Error(), "one secure variable") + require.Contains(t, err.Error(), "one variable") require.False(t, watchFired(ws)) ws = memdb.NewWatchSet() diff --git a/nomad/state/state_store_variables.go b/nomad/state/state_store_variables.go index 9fbc7e64a..66894d031 100644 --- a/nomad/state/state_store_variables.go +++ b/nomad/state/state_store_variables.go @@ -10,12 +10,12 @@ import ( "github.com/hashicorp/nomad/nomad/structs" ) -// SecureVariables queries all the variables and is used only for +// Variables queries all the variables and is used only for // snapshot/restore and key rotation -func (s *StateStore) SecureVariables(ws memdb.WatchSet) (memdb.ResultIterator, error) { +func (s *StateStore) Variables(ws memdb.WatchSet) (memdb.ResultIterator, error) { txn := s.db.ReadTxn() - iter, err := txn.Get(TableSecureVariables, indexID) + iter, err := txn.Get(TableVariables, indexID) if err != nil { return nil, err } @@ -24,101 +24,101 @@ func (s *StateStore) SecureVariables(ws memdb.WatchSet) (memdb.ResultIterator, e return iter, nil } -// GetSecureVariablesByNamespace returns an iterator that contains all +// GetVariablesByNamespace returns an iterator that contains all // variables belonging to the provided namespace. -func (s *StateStore) GetSecureVariablesByNamespace( +func (s *StateStore) GetVariablesByNamespace( ws memdb.WatchSet, namespace string) (memdb.ResultIterator, error) { txn := s.db.ReadTxn() - return s.getSecureVariablesByNamespaceImpl(txn, ws, namespace) + return s.getVariablesByNamespaceImpl(txn, ws, namespace) } -func (s *StateStore) getSecureVariablesByNamespaceImpl( +func (s *StateStore) getVariablesByNamespaceImpl( txn *txn, ws memdb.WatchSet, namespace string) (memdb.ResultIterator, error) { // Walk the entire table. - iter, err := txn.Get(TableSecureVariables, indexID+"_prefix", namespace, "") + iter, err := txn.Get(TableVariables, indexID+"_prefix", namespace, "") if err != nil { - return nil, fmt.Errorf("secure variable lookup failed: %v", err) + return nil, fmt.Errorf("variable lookup failed: %v", err) } ws.Add(iter.WatchCh()) return iter, nil } -// GetSecureVariablesByNamespaceAndPrefix returns an iterator that contains all +// GetVariablesByNamespaceAndPrefix returns an iterator that contains all // variables belonging to the provided namespace that match the prefix. -func (s *StateStore) GetSecureVariablesByNamespaceAndPrefix( +func (s *StateStore) GetVariablesByNamespaceAndPrefix( ws memdb.WatchSet, namespace, prefix string) (memdb.ResultIterator, error) { txn := s.db.ReadTxn() // Walk the entire table. - iter, err := txn.Get(TableSecureVariables, indexID+"_prefix", namespace, prefix) + iter, err := txn.Get(TableVariables, indexID+"_prefix", namespace, prefix) if err != nil { - return nil, fmt.Errorf("secure variable lookup failed: %v", err) + return nil, fmt.Errorf("variable lookup failed: %v", err) } ws.Add(iter.WatchCh()) return iter, nil } -// GetSecureVariablesByPrefix returns an iterator that contains all variables that +// GetVariablesByPrefix returns an iterator that contains all variables that // match the prefix in any namespace. Namespace filtering is the responsibility // of the caller. -func (s *StateStore) GetSecureVariablesByPrefix( +func (s *StateStore) GetVariablesByPrefix( ws memdb.WatchSet, prefix string) (memdb.ResultIterator, error) { txn := s.db.ReadTxn() // Walk the entire table. - iter, err := txn.Get(TableSecureVariables, indexPath+"_prefix", prefix) + iter, err := txn.Get(TableVariables, indexPath+"_prefix", prefix) if err != nil { - return nil, fmt.Errorf("secure variable lookup failed: %v", err) + return nil, fmt.Errorf("variable lookup failed: %v", err) } ws.Add(iter.WatchCh()) return iter, nil } -// GetSecureVariablesByKeyID returns an iterator that contains all +// GetVariablesByKeyID returns an iterator that contains all // variables that were encrypted with a particular key -func (s *StateStore) GetSecureVariablesByKeyID( +func (s *StateStore) GetVariablesByKeyID( ws memdb.WatchSet, keyID string) (memdb.ResultIterator, error) { txn := s.db.ReadTxn() - iter, err := txn.Get(TableSecureVariables, indexKeyID, keyID) + iter, err := txn.Get(TableVariables, indexKeyID, keyID) if err != nil { - return nil, fmt.Errorf("secure variable lookup failed: %v", err) + return nil, fmt.Errorf("variable lookup failed: %v", err) } ws.Add(iter.WatchCh()) return iter, nil } -// GetSecureVariable returns a single secure variable at a given namespace and +// GetVariable returns a single variable at a given namespace and // path. -func (s *StateStore) GetSecureVariable( - ws memdb.WatchSet, namespace, path string) (*structs.SecureVariableEncrypted, error) { +func (s *StateStore) GetVariable( + ws memdb.WatchSet, namespace, path string) (*structs.VariableEncrypted, error) { txn := s.db.ReadTxn() - // Try to fetch the secure variable. - watchCh, raw, err := txn.FirstWatch(TableSecureVariables, indexID, namespace, path) + // Try to fetch the variable. + watchCh, raw, err := txn.FirstWatch(TableVariables, indexID, namespace, path) if err != nil { // error during fetch - return nil, fmt.Errorf("secure variable lookup failed: %v", err) + return nil, fmt.Errorf("variable lookup failed: %v", err) } ws.Add(watchCh) if raw == nil { // not found return nil, nil } - sv := raw.(*structs.SecureVariableEncrypted) + sv := raw.(*structs.VariableEncrypted) return sv, nil } -// SVESet is used to store a secure variable object. -func (s *StateStore) SVESet(idx uint64, sv *structs.SVApplyStateRequest) *structs.SVApplyStateResponse { +// VarSet is used to store a variable object. +func (s *StateStore) VarSet(idx uint64, sv *structs.VarApplyStateRequest) *structs.VarApplyStateResponse { tx := s.db.WriteTxn(idx) defer tx.Abort() // Perform the actual set. - resp := s.svSetTxn(tx, idx, sv) + resp := s.varSetTxn(tx, idx, sv) if resp.IsError() { return resp } @@ -129,14 +129,14 @@ func (s *StateStore) SVESet(idx uint64, sv *structs.SVApplyStateRequest) *struct return resp } -// SVESetCAS is used to do a check-and-set operation on a secure +// VarSetCAS is used to do a check-and-set operation on a // variable. The ModifyIndex in the provided entry is used to determine if // we should write the entry to the state store or not. -func (s *StateStore) SVESetCAS(idx uint64, sv *structs.SVApplyStateRequest) *structs.SVApplyStateResponse { +func (s *StateStore) VarSetCAS(idx uint64, sv *structs.VarApplyStateRequest) *structs.VarApplyStateResponse { tx := s.db.WriteTxn(idx) defer tx.Abort() - resp := s.svSetCASTxn(tx, idx, sv) + resp := s.varSetCASTxn(tx, idx, sv) if resp.IsError() || resp.IsConflict() { return resp } @@ -147,15 +147,15 @@ func (s *StateStore) SVESetCAS(idx uint64, sv *structs.SVApplyStateRequest) *str return resp } -// svSetCASTxn is the inner method used to do a CAS inside an existing +// varSetCASTxn is the inner method used to do a CAS inside an existing // transaction. -func (s *StateStore) svSetCASTxn(tx WriteTxn, idx uint64, req *structs.SVApplyStateRequest) *structs.SVApplyStateResponse { +func (s *StateStore) varSetCASTxn(tx WriteTxn, idx uint64, req *structs.VarApplyStateRequest) *structs.VarApplyStateResponse { sv := req.Var - raw, err := tx.First(TableSecureVariables, indexID, sv.Namespace, sv.Path) + raw, err := tx.First(TableVariables, indexID, sv.Namespace, sv.Path) if err != nil { - return req.ErrorResponse(idx, fmt.Errorf("failed sve lookup: %s", err)) + return req.ErrorResponse(idx, fmt.Errorf("failed variable lookup: %s", err)) } - svEx, ok := raw.(*structs.SecureVariableEncrypted) + svEx, ok := raw.(*structs.VariableEncrypted) // ModifyIndex of 0 means that we are doing a set-if-not-exists. if sv.ModifyIndex == 0 && raw != nil { @@ -165,8 +165,8 @@ func (s *StateStore) svSetCASTxn(tx WriteTxn, idx uint64, req *structs.SVApplySt // If the ModifyIndex is set but the variable doesn't exist, return a // plausible zero value as the conflict if sv.ModifyIndex != 0 && raw == nil { - zeroVal := &structs.SecureVariableEncrypted{ - SecureVariableMetadata: structs.SecureVariableMetadata{ + zeroVal := &structs.VariableEncrypted{ + VariableMetadata: structs.VariableMetadata{ Namespace: sv.Namespace, Path: sv.Path, }, @@ -181,22 +181,22 @@ func (s *StateStore) svSetCASTxn(tx WriteTxn, idx uint64, req *structs.SVApplySt } // If we made it this far, we should perform the set. - return s.svSetTxn(tx, idx, req) + return s.varSetTxn(tx, idx, req) } -// svSetTxn is used to insert or update a secure variable in the state +// varSetTxn is used to insert or update a variable in the state // store. It is the inner method used and handles only the actual storage. -func (s *StateStore) svSetTxn(tx WriteTxn, idx uint64, req *structs.SVApplyStateRequest) *structs.SVApplyStateResponse { +func (s *StateStore) varSetTxn(tx WriteTxn, idx uint64, req *structs.VarApplyStateRequest) *structs.VarApplyStateResponse { sv := req.Var - existingRaw, err := tx.First(TableSecureVariables, indexID, sv.Namespace, sv.Path) + existingRaw, err := tx.First(TableVariables, indexID, sv.Namespace, sv.Path) if err != nil { return req.ErrorResponse(idx, fmt.Errorf("failed sve lookup: %s", err)) } - existing, _ := existingRaw.(*structs.SecureVariableEncrypted) + existing, _ := existingRaw.(*structs.VariableEncrypted) - existingQuota, err := tx.First(TableSecureVariablesQuotas, indexID, sv.Namespace) + existingQuota, err := tx.First(TableVariablesQuotas, indexID, sv.Namespace) if err != nil { - return req.ErrorResponse(idx, fmt.Errorf("secure variable quota lookup failed: %v", err)) + return req.ErrorResponse(idx, fmt.Errorf("variable quota lookup failed: %v", err)) } var quotaChange int64 @@ -222,17 +222,17 @@ func (s *StateStore) svSetTxn(tx WriteTxn, idx uint64, req *structs.SVApplyState quotaChange = int64(len(sv.Data)) } - if err := tx.Insert(TableSecureVariables, sv); err != nil { - return req.ErrorResponse(idx, fmt.Errorf("failed inserting secure variable: %s", err)) + if err := tx.Insert(TableVariables, sv); err != nil { + return req.ErrorResponse(idx, fmt.Errorf("failed inserting variable: %s", err)) } // Track quota usage - var quotaUsed *structs.SecureVariablesQuota + var quotaUsed *structs.VariablesQuota if existingQuota != nil { - quotaUsed = existingQuota.(*structs.SecureVariablesQuota) + quotaUsed = existingQuota.(*structs.VariablesQuota) quotaUsed = quotaUsed.Copy() } else { - quotaUsed = &structs.SecureVariablesQuota{ + quotaUsed = &structs.VariablesQuota{ Namespace: sv.Namespace, CreateIndex: idx, } @@ -242,7 +242,7 @@ func (s *StateStore) svSetTxn(tx WriteTxn, idx uint64, req *structs.SVApplyState // this limit is actually shared across all namespaces in the region's // quota (if there is one), but we need this check here to prevent // overflow as well - return req.ErrorResponse(idx, fmt.Errorf("secure variables can store a maximum of %d bytes of encrypted data per namespace", math.MaxInt)) + return req.ErrorResponse(idx, fmt.Errorf("variables can store a maximum of %d bytes of encrypted data per namespace", math.MaxInt)) } if quotaChange > 0 { @@ -251,7 +251,7 @@ func (s *StateStore) svSetTxn(tx WriteTxn, idx uint64, req *structs.SVApplyState quotaUsed.Size -= helper.Min(quotaUsed.Size, -quotaChange) } - err = s.enforceSecureVariablesQuota(idx, tx, sv.Namespace, quotaChange) + err = s.enforceVariablesQuota(idx, tx, sv.Namespace, quotaChange) if err != nil { return req.ErrorResponse(idx, err) } @@ -261,49 +261,49 @@ func (s *StateStore) svSetTxn(tx WriteTxn, idx uint64, req *structs.SVApplyState // only update the table if this namespace has changed if quotaChange != 0 { quotaUsed.ModifyIndex = idx - if err := tx.Insert(TableSecureVariablesQuotas, quotaUsed); err != nil { - return req.ErrorResponse(idx, fmt.Errorf("secure variable quota insert failed: %v", err)) + if err := tx.Insert(TableVariablesQuotas, quotaUsed); err != nil { + return req.ErrorResponse(idx, fmt.Errorf("variable quota insert failed: %v", err)) } } if err := tx.Insert(tableIndex, - &IndexEntry{TableSecureVariables, idx}); err != nil { - return req.ErrorResponse(idx, fmt.Errorf("failed updating secure variable index: %s", err)) + &IndexEntry{TableVariables, idx}); err != nil { + return req.ErrorResponse(idx, fmt.Errorf("failed updating variable index: %s", err)) } - return req.SuccessResponse(idx, &sv.SecureVariableMetadata) + return req.SuccessResponse(idx, &sv.VariableMetadata) } -// SVEGet is used to retrieve a key/value pair from the state store. -func (s *StateStore) SVEGet(ws memdb.WatchSet, namespace, path string) (uint64, *structs.SecureVariableEncrypted, error) { +// VarGet is used to retrieve a key/value pair from the state store. +func (s *StateStore) VarGet(ws memdb.WatchSet, namespace, path string) (uint64, *structs.VariableEncrypted, error) { tx := s.db.ReadTxn() defer tx.Abort() return svGetTxn(tx, ws, namespace, path) } -// svGetTxn is the inner method that gets a secure variable inside an existing +// svGetTxn is the inner method that gets a variable inside an existing // transaction. func svGetTxn(tx ReadTxn, - ws memdb.WatchSet, namespace, path string) (uint64, *structs.SecureVariableEncrypted, error) { + ws memdb.WatchSet, namespace, path string) (uint64, *structs.VariableEncrypted, error) { // Get the table index. idx := svMaxIndex(tx) - watchCh, entry, err := tx.FirstWatch(TableSecureVariables, indexID, namespace, path) + watchCh, entry, err := tx.FirstWatch(TableVariables, indexID, namespace, path) if err != nil { - return 0, nil, fmt.Errorf("failed secure variable lookup: %s", err) + return 0, nil, fmt.Errorf("failed variable lookup: %s", err) } ws.Add(watchCh) if entry != nil { - return idx, entry.(*structs.SecureVariableEncrypted), nil + return idx, entry.(*structs.VariableEncrypted), nil } return idx, nil, nil } -// SVEDelete is used to delete a single secure variable in the +// VarDelete is used to delete a single variable in the // the state store. -func (s *StateStore) SVEDelete(idx uint64, req *structs.SVApplyStateRequest) *structs.SVApplyStateResponse { +func (s *StateStore) VarDelete(idx uint64, req *structs.VarApplyStateRequest) *structs.VarApplyStateResponse { tx := s.db.WriteTxn(idx) defer tx.Abort() @@ -321,12 +321,11 @@ func (s *StateStore) SVEDelete(idx uint64, req *structs.SVApplyStateRequest) *st return resp } -// SVEDeleteCAS is used to conditionally delete a secure -// variable if and only if it has a given modify index. If the CAS -// index (cidx) specified is not equal to the last observed index for -// the given variable, then the call is a noop, otherwise a normal -// delete is invoked. -func (s *StateStore) SVEDeleteCAS(idx uint64, req *structs.SVApplyStateRequest) *structs.SVApplyStateResponse { +// VarDeleteCAS is used to conditionally delete a variable if and only if it has +// a given modify index. If the CAS index (cidx) specified is not equal to the +// last observed index for the given variable, then the call is a noop, +// otherwise a normal delete is invoked. +func (s *StateStore) VarDeleteCAS(idx uint64, req *structs.VarApplyStateRequest) *structs.VarApplyStateResponse { tx := s.db.WriteTxn(idx) defer tx.Abort() @@ -344,16 +343,16 @@ func (s *StateStore) SVEDeleteCAS(idx uint64, req *structs.SVApplyStateRequest) } // svDeleteCASTxn is an inner method used to check the existing value -// of a secure variable within an existing transaction as part of a +// of a variable within an existing transaction as part of a // conditional delete. -func (s *StateStore) svDeleteCASTxn(tx WriteTxn, idx uint64, req *structs.SVApplyStateRequest) *structs.SVApplyStateResponse { +func (s *StateStore) svDeleteCASTxn(tx WriteTxn, idx uint64, req *structs.VarApplyStateRequest) *structs.VarApplyStateResponse { sv := req.Var - raw, err := tx.First(TableSecureVariables, indexID, sv.Namespace, sv.Path) + raw, err := tx.First(TableVariables, indexID, sv.Namespace, sv.Path) if err != nil { - return req.ErrorResponse(idx, fmt.Errorf("failed secure variable lookup: %s", err)) + return req.ErrorResponse(idx, fmt.Errorf("failed variable lookup: %s", err)) } - svEx, ok := raw.(*structs.SecureVariableEncrypted) + svEx, ok := raw.(*structs.VariableEncrypted) // ModifyIndex of 0 means that we are doing a delete-if-not-exists. if sv.ModifyIndex == 0 && raw != nil { @@ -363,8 +362,8 @@ func (s *StateStore) svDeleteCASTxn(tx WriteTxn, idx uint64, req *structs.SVAppl // If the ModifyIndex is set but the variable doesn't exist, return a // plausible zero value as the conflict if sv.ModifyIndex != 0 && raw == nil { - zeroVal := &structs.SecureVariableEncrypted{ - SecureVariableMetadata: structs.SecureVariableMetadata{ + zeroVal := &structs.VariableEncrypted{ + VariableMetadata: structs.VariableMetadata{ Namespace: sv.Namespace, Path: sv.Path, }, @@ -383,43 +382,43 @@ func (s *StateStore) svDeleteCASTxn(tx WriteTxn, idx uint64, req *structs.SVAppl } // svDeleteTxn is the inner method used to perform the actual deletion -// of a secure variable within an existing transaction. -func (s *StateStore) svDeleteTxn(tx WriteTxn, idx uint64, req *structs.SVApplyStateRequest) *structs.SVApplyStateResponse { +// of a variable within an existing transaction. +func (s *StateStore) svDeleteTxn(tx WriteTxn, idx uint64, req *structs.VarApplyStateRequest) *structs.VarApplyStateResponse { // Look up the entry in the state store. - existingRaw, err := tx.First(TableSecureVariables, indexID, req.Var.Namespace, req.Var.Path) + existingRaw, err := tx.First(TableVariables, indexID, req.Var.Namespace, req.Var.Path) if err != nil { - return req.ErrorResponse(idx, fmt.Errorf("failed secure variable lookup: %s", err)) + return req.ErrorResponse(idx, fmt.Errorf("failed variable lookup: %s", err)) } if existingRaw == nil { return req.SuccessResponse(idx, nil) } - existingQuota, err := tx.First(TableSecureVariablesQuotas, indexID, req.Var.Namespace) + existingQuota, err := tx.First(TableVariablesQuotas, indexID, req.Var.Namespace) if err != nil { - return req.ErrorResponse(idx, fmt.Errorf("secure variable quota lookup failed: %v", err)) + return req.ErrorResponse(idx, fmt.Errorf("variable quota lookup failed: %v", err)) } - sv := existingRaw.(*structs.SecureVariableEncrypted) + sv := existingRaw.(*structs.VariableEncrypted) // Track quota usage if existingQuota != nil { - quotaUsed := existingQuota.(*structs.SecureVariablesQuota) + quotaUsed := existingQuota.(*structs.VariablesQuota) quotaUsed = quotaUsed.Copy() quotaUsed.Size -= helper.Min(quotaUsed.Size, int64(len(sv.Data))) quotaUsed.ModifyIndex = idx - if err := tx.Insert(TableSecureVariablesQuotas, quotaUsed); err != nil { - return req.ErrorResponse(idx, fmt.Errorf("secure variable quota insert failed: %v", err)) + if err := tx.Insert(TableVariablesQuotas, quotaUsed); err != nil { + return req.ErrorResponse(idx, fmt.Errorf("variable quota insert failed: %v", err)) } } - // Delete the secure variable and update the index table. - if err := tx.Delete(TableSecureVariables, sv); err != nil { - return req.ErrorResponse(idx, fmt.Errorf("failed deleting secure variable entry: %s", err)) + // Delete the variable and update the index table. + if err := tx.Delete(TableVariables, sv); err != nil { + return req.ErrorResponse(idx, fmt.Errorf("failed deleting variable entry: %s", err)) } - if err := tx.Insert(tableIndex, &IndexEntry{TableSecureVariables, idx}); err != nil { - return req.ErrorResponse(idx, fmt.Errorf("failed updating secure variable index: %s", err)) + if err := tx.Insert(tableIndex, &IndexEntry{TableVariables, idx}); err != nil { + return req.ErrorResponse(idx, fmt.Errorf("failed updating variable index: %s", err)) } return req.SuccessResponse(idx, nil) @@ -427,7 +426,7 @@ func (s *StateStore) svDeleteTxn(tx WriteTxn, idx uint64, req *structs.SVApplySt // This extra indirection is to facilitate the tombstone case if it matters. func svMaxIndex(tx ReadTxn) uint64 { - return maxIndexTxn(tx, TableSecureVariables) + return maxIndexTxn(tx, TableVariables) } // WriteTxn is implemented by memdb.Txn to perform write operations. @@ -469,12 +468,12 @@ func maxIndexWatchTxn(tx ReadTxn, ws memdb.WatchSet, tables ...string) uint64 { return lindex } -// SecureVariablesQuotas queries all the quotas and is used only for +// VariablesQuotas queries all the quotas and is used only for // snapshot/restore and key rotation -func (s *StateStore) SecureVariablesQuotas(ws memdb.WatchSet) (memdb.ResultIterator, error) { +func (s *StateStore) VariablesQuotas(ws memdb.WatchSet) (memdb.ResultIterator, error) { txn := s.db.ReadTxn() - iter, err := txn.Get(TableSecureVariablesQuotas, indexID) + iter, err := txn.Get(TableVariablesQuotas, indexID) if err != nil { return nil, err } @@ -483,18 +482,18 @@ func (s *StateStore) SecureVariablesQuotas(ws memdb.WatchSet) (memdb.ResultItera return iter, nil } -// SecureVariablesQuotaByNamespace queries for quotas for a particular namespace -func (s *StateStore) SecureVariablesQuotaByNamespace(ws memdb.WatchSet, namespace string) (*structs.SecureVariablesQuota, error) { +// VariablesQuotaByNamespace queries for quotas for a particular namespace +func (s *StateStore) VariablesQuotaByNamespace(ws memdb.WatchSet, namespace string) (*structs.VariablesQuota, error) { txn := s.db.ReadTxn() - watchCh, raw, err := txn.FirstWatch(TableSecureVariablesQuotas, indexID, namespace) + watchCh, raw, err := txn.FirstWatch(TableVariablesQuotas, indexID, namespace) if err != nil { - return nil, fmt.Errorf("secure variable quota lookup failed: %v", err) + return nil, fmt.Errorf("variable quota lookup failed: %v", err) } ws.Add(watchCh) if raw == nil { return nil, nil } - quotaUsed := raw.(*structs.SecureVariablesQuota) + quotaUsed := raw.(*structs.VariablesQuota) return quotaUsed, nil } diff --git a/nomad/state/state_store_variables_oss.go b/nomad/state/state_store_variables_oss.go index f730fec6b..a9ab23242 100644 --- a/nomad/state/state_store_variables_oss.go +++ b/nomad/state/state_store_variables_oss.go @@ -3,6 +3,6 @@ package state -func (s *StateStore) enforceSecureVariablesQuota(_ uint64, _ WriteTxn, _ string, _ int64) error { +func (s *StateStore) enforceVariablesQuota(_ uint64, _ WriteTxn, _ string, _ int64) error { return nil } diff --git a/nomad/state/state_store_variables_test.go b/nomad/state/state_store_variables_test.go index 4b0f00cc7..0856812c7 100644 --- a/nomad/state/state_store_variables_test.go +++ b/nomad/state/state_store_variables_test.go @@ -15,23 +15,23 @@ import ( "github.com/hashicorp/nomad/nomad/structs" ) -func TestStateStore_GetSecureVariable(t *testing.T) { +func TestStateStore_GetVariable(t *testing.T) { ci.Parallel(t) testState := testStateStore(t) ws := memdb.NewWatchSet() - sve, err := testState.GetSecureVariable(ws, "default", "not/a/path") + sve, err := testState.GetVariable(ws, "default", "not/a/path") require.NoError(t, err) require.Nil(t, sve) } -func TestStateStore_UpsertSecureVariables(t *testing.T) { +func TestStateStore_UpsertVariables(t *testing.T) { ci.Parallel(t) testState := testStateStore(t) ws := memdb.NewWatchSet() - svs := []*structs.SecureVariableEncrypted{ - mock.SecureVariableEncrypted(), - mock.SecureVariableEncrypted(), + svs := []*structs.VariableEncrypted{ + mock.VariableEncrypted(), + mock.VariableEncrypted(), } svs[0].Path = "aaaaa" svs[1].Path = "bbbbb" @@ -43,36 +43,36 @@ func TestStateStore_UpsertSecureVariables(t *testing.T) { expectedQuotaSize += len(v.Data) } - // Ensure new secure variables are inserted as expected with their + // Ensure new variables are inserted as expected with their // correct indexes, along with an update to the index table. t.Run("1 create new variables", func(t *testing.T) { - // Perform the initial upsert of secure variables. + // Perform the initial upsert of variables. for _, sv := range svs { insertIndex++ - resp := testState.SVESet(insertIndex, &structs.SVApplyStateRequest{ - Op: structs.SVOpSet, + resp := testState.VarSet(insertIndex, &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, Var: sv, }) require.NoError(t, resp.Error) } // Check that the index for the table was modified as expected. - initialIndex, err := testState.Index(TableSecureVariables) + initialIndex, err := testState.Index(TableVariables) require.NoError(t, err) require.Equal(t, insertIndex, initialIndex) - // List all the secure variables in the table - iter, err := testState.SecureVariables(ws) + // List all the variables in the table + iter, err := testState.Variables(ws) require.NoError(t, err) - got := []*structs.SecureVariableEncrypted{} + got := []*structs.VariableEncrypted{} for raw := iter.Next(); raw != nil; raw = iter.Next() { - sv := raw.(*structs.SecureVariableEncrypted) - var svCopy structs.SecureVariableEncrypted + sv := raw.(*structs.VariableEncrypted) + var svCopy structs.VariableEncrypted svCopy = sv.Copy() got = append(got, &svCopy) } - require.Len(t, got, 2, "incorrect number of secure variables found") + require.Len(t, got, 2, "incorrect number of variables found") // Ensure the create and modify indexes are populated correctly. require.Equal(t, uint64(21), got[0].CreateIndex, "%s: incorrect create index", got[0].Path) @@ -80,7 +80,7 @@ func TestStateStore_UpsertSecureVariables(t *testing.T) { require.Equal(t, uint64(22), got[1].CreateIndex, "%s: incorrect create index", got[1].Path) require.Equal(t, uint64(22), got[1].ModifyIndex, "%s: incorrect modify index", got[1].Path) - quotaUsed, err := testState.SecureVariablesQuotaByNamespace(ws, structs.DefaultNamespace) + quotaUsed, err := testState.VariablesQuotaByNamespace(ws, structs.DefaultNamespace) require.NoError(t, err) require.Equal(t, int64(expectedQuotaSize), quotaUsed.Size) @@ -90,39 +90,39 @@ func TestStateStore_UpsertSecureVariables(t *testing.T) { }) t.Run("1a fetch variable", func(t *testing.T) { - sve, err := testState.GetSecureVariable(ws, svs[0].Namespace, svs[0].Path) + sve, err := testState.GetVariable(ws, svs[0].Namespace, svs[0].Path) require.NoError(t, err) require.NotNil(t, sve) }) - // Upsert the exact same secure variables without any modification. In this + // Upsert the exact same variables without any modification. In this // case, the index table should not be updated, indicating no write actually // happened due to equality checking. t.Run("2 upsert same", func(t *testing.T) { reInsertIndex := uint64(30) for _, sv := range svs { - svReq := &structs.SVApplyStateRequest{ - Op: structs.SVOpSet, + svReq := &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, Var: sv, } reInsertIndex++ - resp := testState.SVESet(reInsertIndex, svReq) + resp := testState.VarSet(reInsertIndex, svReq) require.NoError(t, resp.Error) } - reInsertActualIndex, err := testState.Index(TableSecureVariables) + reInsertActualIndex, err := testState.Index(TableVariables) require.NoError(t, err) require.Equal(t, insertIndex, reInsertActualIndex, "index should not have changed") - quotaUsed, err := testState.SecureVariablesQuotaByNamespace(ws, structs.DefaultNamespace) + quotaUsed, err := testState.VariablesQuotaByNamespace(ws, structs.DefaultNamespace) require.NoError(t, err) require.Equal(t, int64(expectedQuotaSize), quotaUsed.Size) }) - // Modify a single one of the previously inserted secure variables and + // Modify a single one of the previously inserted variables and // performs an upsert. This ensures the index table is modified correctly - // and that each secure variable is updated, or not, as expected. + // and that each variable is updated, or not, as expected. t.Run("3 modify one", func(t *testing.T) { sv1Update := svs[0].Copy() sv1Update.KeyID = "sv1-update" @@ -134,27 +134,27 @@ func TestStateStore_UpsertSecureVariables(t *testing.T) { update1Index := uint64(40) - resp := testState.SVESet(update1Index, &structs.SVApplyStateRequest{ - Op: structs.SVOpSet, + resp := testState.VarSet(update1Index, &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, Var: &sv1Update, }) require.NoError(t, resp.Error) // Check that the index for the table was modified as expected. - updateActualIndex, err := testState.Index(TableSecureVariables) + updateActualIndex, err := testState.Index(TableVariables) require.NoError(t, err) require.Equal(t, update1Index, updateActualIndex, "index should have changed") - // Get the secure variables from the table. - iter, err := testState.SecureVariables(ws) + // Get the variables from the table. + iter, err := testState.Variables(ws) require.NoError(t, err) - got := []*structs.SecureVariableEncrypted{} + got := []*structs.VariableEncrypted{} // Iterate all the stored variables and assert indexes have been updated as expected for raw := iter.Next(); raw != nil; raw = iter.Next() { - sv := raw.(*structs.SecureVariableEncrypted) - var svCopy structs.SecureVariableEncrypted + sv := raw.(*structs.VariableEncrypted) + var svCopy structs.VariableEncrypted svCopy = sv.Copy() got = append(got, &svCopy) } @@ -166,7 +166,7 @@ func TestStateStore_UpsertSecureVariables(t *testing.T) { // indexes and times now that we have validated them svs = got - quotaUsed, err := testState.SecureVariablesQuotaByNamespace(ws, structs.DefaultNamespace) + quotaUsed, err := testState.VariablesQuotaByNamespace(ws, structs.DefaultNamespace) require.NoError(t, err) require.Equal(t, int64(expectedQuotaSize+1), quotaUsed.Size) }) @@ -179,26 +179,26 @@ func TestStateStore_UpsertSecureVariables(t *testing.T) { sv2.KeyID = "sv2-update" sv2.ModifyIndex = update2Index - resp := testState.SVESet(update2Index, &structs.SVApplyStateRequest{ - Op: structs.SVOpSet, + resp := testState.VarSet(update2Index, &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, Var: &sv2, }) require.NoError(t, resp.Error) // Check that the index for the table was modified as expected. - update2ActualIndex, err := testState.Index(TableSecureVariables) + update2ActualIndex, err := testState.Index(TableVariables) require.NoError(t, err) require.Equal(t, update2Index, update2ActualIndex, "index should have changed") - // Get the secure variables from the table. - iter, err := testState.SecureVariables(ws) + // Get the variables from the table. + iter, err := testState.Variables(ws) require.NoError(t, err) - got := []structs.SecureVariableEncrypted{} + got := []structs.VariableEncrypted{} // Iterate all the stored variables and assert indexes have been updated as expected for raw := iter.Next(); raw != nil; raw = iter.Next() { - sv := raw.(*structs.SecureVariableEncrypted) + sv := raw.(*structs.VariableEncrypted) got = append(got, sv.Copy()) } require.Len(t, got, 2) @@ -208,45 +208,45 @@ func TestStateStore_UpsertSecureVariables(t *testing.T) { require.True(t, svs[0].Equals(got[0])) require.True(t, sv2.Equals(got[1])) - quotaUsed, err := testState.SecureVariablesQuotaByNamespace(ws, structs.DefaultNamespace) + quotaUsed, err := testState.VariablesQuotaByNamespace(ws, structs.DefaultNamespace) require.NoError(t, err) require.Equal(t, int64(expectedQuotaSize+1), quotaUsed.Size) }) } -func TestStateStore_DeleteSecureVariable(t *testing.T) { +func TestStateStore_DeleteVariable(t *testing.T) { ci.Parallel(t) testState := testStateStore(t) - // Generate some test secure variables that we will use and modify throughout. - svs := []*structs.SecureVariableEncrypted{ - mock.SecureVariableEncrypted(), - mock.SecureVariableEncrypted(), + // Generate some test variables that we will use and modify throughout. + svs := []*structs.VariableEncrypted{ + mock.VariableEncrypted(), + mock.VariableEncrypted(), } svs[0].Path = "aaaaa" svs[1].Path = "bbbbb" initialIndex := uint64(10) - t.Run("1 delete a secure variable that does not exist", func(t *testing.T) { + t.Run("1 delete a variable that does not exist", func(t *testing.T) { - resp := testState.SVEDelete(initialIndex, &structs.SVApplyStateRequest{ - Op: structs.SVOpDelete, + resp := testState.VarDelete(initialIndex, &structs.VarApplyStateRequest{ + Op: structs.VarOpDelete, Var: svs[0], }) - require.NoError(t, resp.Error, "deleting non-existing secure var is not an error") + require.NoError(t, resp.Error, "deleting non-existing var is not an error") - actualInitialIndex, err := testState.Index(TableSecureVariables) + actualInitialIndex, err := testState.Index(TableVariables) require.NoError(t, err) require.Equal(t, uint64(0), actualInitialIndex, "index should not have changed") - quotaUsed, err := testState.SecureVariablesQuotaByNamespace(nil, structs.DefaultNamespace) + quotaUsed, err := testState.VariablesQuotaByNamespace(nil, structs.DefaultNamespace) require.NoError(t, err) require.Nil(t, quotaUsed) }) - // Upsert two secure variables, deletes one, then ensure the + // Upsert two variables, deletes one, then ensure the // remaining is left as expected. t.Run("2 upsert variable and delete", func(t *testing.T) { @@ -255,33 +255,33 @@ func TestStateStore_DeleteSecureVariable(t *testing.T) { require.NoError(t, testState.UpsertNamespaces(initialIndex, []*structs.Namespace{ns})) for _, sv := range svs { - svReq := &structs.SVApplyStateRequest{ - Op: structs.SVOpSet, + svReq := &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, Var: sv, } initialIndex++ - resp := testState.SVESet(initialIndex, svReq) + resp := testState.VarSet(initialIndex, svReq) require.NoError(t, resp.Error) } // Perform the delete. delete1Index := uint64(20) - resp := testState.SVEDelete(delete1Index, &structs.SVApplyStateRequest{ - Op: structs.SVOpDelete, + resp := testState.VarDelete(delete1Index, &structs.VarApplyStateRequest{ + Op: structs.VarOpDelete, Var: svs[0], }) require.NoError(t, resp.Error) // Check that the index for the table was modified as expected. - actualDelete1Index, err := testState.Index(TableSecureVariables) + actualDelete1Index, err := testState.Index(TableVariables) require.NoError(t, err) require.Equal(t, delete1Index, actualDelete1Index, "index should have changed") ws := memdb.NewWatchSet() - // Get the secure variables from the table. - iter, err := testState.SecureVariables(ws) + // Get the variables from the table. + iter, err := testState.Variables(ws) require.NoError(t, err) var delete1Count int @@ -291,11 +291,11 @@ func TestStateStore_DeleteSecureVariable(t *testing.T) { // number. for raw := iter.Next(); raw != nil; raw = iter.Next() { delete1Count++ - v := raw.(*structs.SecureVariableEncrypted) + v := raw.(*structs.VariableEncrypted) expectedQuotaSize += len(v.Data) } require.Equal(t, 1, delete1Count, "unexpected number of variables in table") - quotaUsed, err := testState.SecureVariablesQuotaByNamespace(ws, structs.DefaultNamespace) + quotaUsed, err := testState.VariablesQuotaByNamespace(ws, structs.DefaultNamespace) require.NoError(t, err) require.Equal(t, int64(expectedQuotaSize), quotaUsed.Size) }) @@ -303,20 +303,20 @@ func TestStateStore_DeleteSecureVariable(t *testing.T) { t.Run("3 delete remaining variable", func(t *testing.T) { delete2Index := uint64(30) - resp := testState.SVEDelete(delete2Index, &structs.SVApplyStateRequest{ - Op: structs.SVOpDelete, + resp := testState.VarDelete(delete2Index, &structs.VarApplyStateRequest{ + Op: structs.VarOpDelete, Var: svs[1], }) require.NoError(t, resp.Error) // Check that the index for the table was modified as expected. - actualDelete2Index, err := testState.Index(TableSecureVariables) + actualDelete2Index, err := testState.Index(TableVariables) require.NoError(t, err) require.Equal(t, delete2Index, actualDelete2Index, "index should have changed") - // Get the secure variables from the table. + // Get the variables from the table. ws := memdb.NewWatchSet() - iter, err := testState.SecureVariables(ws) + iter, err := testState.Variables(ws) require.NoError(t, err) var delete2Count int @@ -327,13 +327,13 @@ func TestStateStore_DeleteSecureVariable(t *testing.T) { } require.Equal(t, 0, delete2Count, "unexpected number of variables in table") - quotaUsed, err := testState.SecureVariablesQuotaByNamespace(ws, structs.DefaultNamespace) + quotaUsed, err := testState.VariablesQuotaByNamespace(ws, structs.DefaultNamespace) require.NoError(t, err) require.Equal(t, int64(0), quotaUsed.Size) }) } -func TestStateStore_GetSecureVariables(t *testing.T) { +func TestStateStore_GetVariables(t *testing.T) { ci.Parallel(t) testState := testStateStore(t) @@ -342,34 +342,34 @@ func TestStateStore_GetSecureVariables(t *testing.T) { initialIndex := uint64(10) require.NoError(t, testState.UpsertNamespaces(initialIndex, []*structs.Namespace{ns})) - // Generate some test secure variables in different namespaces and upsert them. - svs := []*structs.SecureVariableEncrypted{ - mock.SecureVariableEncrypted(), - mock.SecureVariableEncrypted(), + // Generate some test variables in different namespaces and upsert them. + svs := []*structs.VariableEncrypted{ + mock.VariableEncrypted(), + mock.VariableEncrypted(), } svs[0].Path = "aaaaa" svs[0].Namespace = "~*magical*~" svs[1].Path = "bbbbb" for _, sv := range svs { - svReq := &structs.SVApplyStateRequest{ - Op: structs.SVOpSet, + svReq := &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, Var: sv, } initialIndex++ - resp := testState.SVESet(initialIndex, svReq) + resp := testState.VarSet(initialIndex, svReq) require.NoError(t, resp.Error) } - // Look up secure variables using the namespace of the first mock variable. + // Look up variables using the namespace of the first mock variable. ws := memdb.NewWatchSet() - iter, err := testState.GetSecureVariablesByNamespace(ws, svs[0].Namespace) + iter, err := testState.GetVariablesByNamespace(ws, svs[0].Namespace) require.NoError(t, err) var count1 int for raw := iter.Next(); raw != nil; raw = iter.Next() { - sv := raw.(*structs.SecureVariableEncrypted) + sv := raw.(*structs.VariableEncrypted) require.Equal(t, svs[0].Namespace, sv.Namespace) require.Equal(t, uint64(11), sv.CreateIndex, "%s incorrect create index", sv.Path) require.Equal(t, uint64(11), sv.ModifyIndex, "%s incorrect modify index", sv.Path) @@ -379,14 +379,14 @@ func TestStateStore_GetSecureVariables(t *testing.T) { require.Equal(t, 1, count1) // Look up variables using the namespace of the second mock variable. - iter, err = testState.GetSecureVariablesByNamespace(ws, svs[1].Namespace) + iter, err = testState.GetVariablesByNamespace(ws, svs[1].Namespace) require.NoError(t, err) var count2 int for raw := iter.Next(); raw != nil; raw = iter.Next() { count2++ - sv := raw.(*structs.SecureVariableEncrypted) + sv := raw.(*structs.VariableEncrypted) require.Equal(t, initialIndex, sv.CreateIndex, "%s incorrect create index", sv.Path) require.Equal(t, initialIndex, sv.ModifyIndex, "%s incorrect modify index", sv.Path) require.Equal(t, svs[1].Namespace, sv.Namespace) @@ -395,7 +395,7 @@ func TestStateStore_GetSecureVariables(t *testing.T) { // Look up variables using a namespace that shouldn't contain any // variables. - iter, err = testState.GetSecureVariablesByNamespace(ws, "pony-club") + iter, err = testState.GetVariablesByNamespace(ws, "pony-club") require.NoError(t, err) var count3 int @@ -406,14 +406,14 @@ func TestStateStore_GetSecureVariables(t *testing.T) { require.Equal(t, 0, count3) } -func TestStateStore_ListSecureVariablesByNamespaceAndPrefix(t *testing.T) { +func TestStateStore_ListVariablesByNamespaceAndPrefix(t *testing.T) { ci.Parallel(t) testState := testStateStore(t) - // Generate some test secure variables and upsert them. - svs := []*structs.SecureVariableEncrypted{} + // Generate some test variables and upsert them. + svs := []*structs.VariableEncrypted{} for i := 0; i < 6; i++ { - sv := mock.SecureVariableEncrypted() + sv := mock.VariableEncrypted() svs = append(svs, sv) } @@ -433,12 +433,12 @@ func TestStateStore_ListSecureVariablesByNamespaceAndPrefix(t *testing.T) { require.NoError(t, testState.UpsertNamespaces(initialIndex, []*structs.Namespace{ns})) for _, sv := range svs { - svReq := &structs.SVApplyStateRequest{ - Op: structs.SVOpSet, + svReq := &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, Var: sv, } initialIndex++ - resp := testState.SVESet(initialIndex, svReq) + resp := testState.VarSet(initialIndex, svReq) require.NoError(t, resp.Error) } @@ -468,13 +468,13 @@ func TestStateStore_ListSecureVariablesByNamespaceAndPrefix(t *testing.T) { ws := memdb.NewWatchSet() for _, tC := range testCases { t.Run(tC.desc, func(t *testing.T) { - iter, err := testState.GetSecureVariablesByNamespace(ws, tC.namespace) + iter, err := testState.GetVariablesByNamespace(ws, tC.namespace) require.NoError(t, err) var count int = 0 for raw := iter.Next(); raw != nil; raw = iter.Next() { count++ - sv := raw.(*structs.SecureVariableEncrypted) + sv := raw.(*structs.VariableEncrypted) require.Equal(t, tC.namespace, sv.Namespace) } }) @@ -523,13 +523,13 @@ func TestStateStore_ListSecureVariablesByNamespaceAndPrefix(t *testing.T) { ws := memdb.NewWatchSet() for _, tC := range testCases { t.Run(tC.desc, func(t *testing.T) { - iter, err := testState.GetSecureVariablesByNamespaceAndPrefix(ws, tC.namespace, tC.prefix) + iter, err := testState.GetVariablesByNamespaceAndPrefix(ws, tC.namespace, tC.prefix) require.NoError(t, err) var count int = 0 for raw := iter.Next(); raw != nil; raw = iter.Next() { count++ - sv := raw.(*structs.SecureVariableEncrypted) + sv := raw.(*structs.VariableEncrypted) require.Equal(t, tC.namespace, sv.Namespace) require.True(t, strings.HasPrefix(sv.Path, tC.prefix)) } @@ -564,13 +564,13 @@ func TestStateStore_ListSecureVariablesByNamespaceAndPrefix(t *testing.T) { ws := memdb.NewWatchSet() for _, tC := range testCases { t.Run(tC.desc, func(t *testing.T) { - iter, err := testState.GetSecureVariablesByPrefix(ws, tC.prefix) + iter, err := testState.GetVariablesByPrefix(ws, tC.prefix) require.NoError(t, err) var count int = 0 for raw := iter.Next(); raw != nil; raw = iter.Next() { count++ - sv := raw.(*structs.SecureVariableEncrypted) + sv := raw.(*structs.VariableEncrypted) require.True(t, strings.HasPrefix(sv.Path, tC.prefix)) } require.Equal(t, tC.expectedCount, count) @@ -578,14 +578,14 @@ func TestStateStore_ListSecureVariablesByNamespaceAndPrefix(t *testing.T) { } }) } -func TestStateStore_ListSecureVariablesByKeyID(t *testing.T) { +func TestStateStore_ListVariablesByKeyID(t *testing.T) { ci.Parallel(t) testState := testStateStore(t) - // Generate some test secure variables and upsert them. - svs := []*structs.SecureVariableEncrypted{} + // Generate some test variables and upsert them. + svs := []*structs.VariableEncrypted{} for i := 0; i < 7; i++ { - sv := mock.SecureVariableEncrypted() + sv := mock.VariableEncrypted() sv.Path = uuid.Generate() svs = append(svs, sv) } @@ -604,22 +604,22 @@ func TestStateStore_ListSecureVariablesByKeyID(t *testing.T) { initialIndex := uint64(10) for _, sv := range svs { - svReq := &structs.SVApplyStateRequest{ - Op: structs.SVOpSet, + svReq := &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, Var: sv, } initialIndex++ - resp := testState.SVESet(initialIndex, svReq) + resp := testState.VarSet(initialIndex, svReq) require.NoError(t, resp.Error) } ws := memdb.NewWatchSet() - iter, err := testState.GetSecureVariablesByKeyID(ws, keyID) + iter, err := testState.GetVariablesByKeyID(ws, keyID) require.NoError(t, err) var count int for raw := iter.Next(); raw != nil; raw = iter.Next() { - sv := raw.(*structs.SecureVariableEncrypted) + sv := raw.(*structs.VariableEncrypted) require.Equal(t, keyID, sv.KeyID) require.Equal(t, expectedForKey[count], sv.Path) require.NotContains(t, expectedOrphaned, sv.Path) @@ -628,18 +628,18 @@ func TestStateStore_ListSecureVariablesByKeyID(t *testing.T) { require.Equal(t, 5, count) } -func printSecureVariable(tsv *structs.SecureVariableEncrypted) string { +func printVariable(tsv *structs.VariableEncrypted) string { b, _ := json.Marshal(tsv) return string(b) } -func printSecureVariables(tsvs []*structs.SecureVariableEncrypted) string { +func printVariables(tsvs []*structs.VariableEncrypted) string { if len(tsvs) == 0 { return "" } var out strings.Builder for _, tsv := range tsvs { - out.WriteString(printSecureVariable(tsv) + "\n") + out.WriteString(printVariable(tsv) + "\n") } return out.String() } diff --git a/nomad/structs/search.go b/nomad/structs/search.go index 52cdb43e5..699639f0c 100644 --- a/nomad/structs/search.go +++ b/nomad/structs/search.go @@ -16,7 +16,7 @@ const ( Recommendations Context = "recommendations" ScalingPolicies Context = "scaling_policy" Plugins Context = "plugins" - SecureVariables Context = "vars" + Variables Context = "vars" Volumes Context = "volumes" // Subtypes used in fuzzy matching. diff --git a/nomad/structs/structs.go b/nomad/structs/structs.go index aa089d1ab..04563bc66 100644 --- a/nomad/structs/structs.go +++ b/nomad/structs/structs.go @@ -110,7 +110,7 @@ const ( ServiceRegistrationUpsertRequestType MessageType = 47 ServiceRegistrationDeleteByIDRequestType MessageType = 48 ServiceRegistrationDeleteByNodeIDRequestType MessageType = 49 - SVApplyStateRequestType MessageType = 50 + VarApplyStateRequestType MessageType = 50 RootKeyMetaUpsertRequestType MessageType = 51 RootKeyMetaDeleteRequestType MessageType = 52 @@ -10878,10 +10878,10 @@ const ( // garbage collection of unused encryption keys. CoreJobRootKeyRotateOrGC = "root-key-rotate-gc" - // CoreJobSecureVariablesRekey is used to fully rotate the - // encryption keys for secure variables by decrypting all secure - // variables and re-encrypting them with the active key - CoreJobSecureVariablesRekey = "secure-variables-rekey" + // CoreJobVariablesRekey is used to fully rotate the encryption keys for + // variables by decrypting all variables and re-encrypting them with the + // active key + CoreJobVariablesRekey = "variables-rekey" // CoreJobForceGC is used to force garbage collection of all GCable objects. CoreJobForceGC = "force-gc" diff --git a/nomad/structs/variables.go b/nomad/structs/variables.go index dead3c1b0..23853b86f 100644 --- a/nomad/structs/variables.go +++ b/nomad/structs/variables.go @@ -17,38 +17,37 @@ import ( ) const ( - // SecureVariablesApplyRPCMethod is the RPC method for upserting or - // deleting a secure variable by its namespace and path, with optional - // conflict detection. + // VariablesApplyRPCMethod is the RPC method for upserting or deleting a + // variable by its namespace and path, with optional conflict detection. // - // Args: SecureVariablesApplyRequest - // Reply: SecureVariablesApplyResponse - SecureVariablesApplyRPCMethod = "SecureVariables.Apply" + // Args: VariablesApplyRequest + // Reply: VariablesApplyResponse + VariablesApplyRPCMethod = "Variables.Apply" - // SecureVariablesListRPCMethod is the RPC method for listing secure - // variables within Nomad. + // VariablesListRPCMethod is the RPC method for listing variables within + // Nomad. // - // Args: SecureVariablesListRequest - // Reply: SecureVariablesListResponse - SecureVariablesListRPCMethod = "SecureVariables.List" + // Args: VariablesListRequest + // Reply: VariablesListResponse + VariablesListRPCMethod = "Variables.List" - // SecureVariablesGetServiceRPCMethod is the RPC method for fetching a - // secure variable according to its namepace and path. + // VariablesGetServiceRPCMethod is the RPC method for fetching a variable + // according to its namepace and path. // - // Args: SecureVariablesByNameRequest - // Reply: SecureVariablesByNameResponse - SecureVariablesReadRPCMethod = "SecureVariables.Read" + // Args: VariablesByNameRequest + // Reply: VariablesByNameResponse + VariablesReadRPCMethod = "Variables.Read" - // maxVariableSize is the maximum size of the unencrypted contents of - // a variable. This size is deliberately set low and is not - // configurable, to discourage DoS'ing the cluster + // maxVariableSize is the maximum size of the unencrypted contents of a + // variable. This size is deliberately set low and is not configurable, to + // discourage DoS'ing the cluster maxVariableSize = 16384 ) -// SecureVariableMetadata is the metadata envelope for a Secure Variable, it -// is the list object and is shared data between an SecureVariableEncrypted and -// a SecureVariableDecrypted object. -type SecureVariableMetadata struct { +// VariableMetadata is the metadata envelope for a Variable, it is the list +// object and is shared data between an VariableEncrypted and a +// VariableDecrypted object. +type VariableMetadata struct { Namespace string Path string CreateIndex uint64 @@ -57,32 +56,32 @@ type SecureVariableMetadata struct { ModifyTime int64 } -// SecureVariableEncrypted structs are returned from the Encrypter's encrypt +// VariableEncrypted structs are returned from the Encrypter's encrypt // method. They are the only form that should ever be persisted to storage. -type SecureVariableEncrypted struct { - SecureVariableMetadata - SecureVariableData +type VariableEncrypted struct { + VariableMetadata + VariableData } -// SecureVariableData is the secret data for a Secure Variable -type SecureVariableData struct { +// VariableData is the secret data for a Variable +type VariableData struct { Data []byte // includes nonce KeyID string // ID of root key used to encrypt this entry } -// SecureVariableDecrypted structs are returned from the Encrypter's decrypt +// VariableDecrypted structs are returned from the Encrypter's decrypt // method. Since they contains sensitive material, they should never be // persisted to disk. -type SecureVariableDecrypted struct { - SecureVariableMetadata - Items SecureVariableItems +type VariableDecrypted struct { + VariableMetadata + Items VariableItems } -// SecureVariableItems are the actual secrets stored in a secure variable. They -// are always encrypted and decrypted as a single unit. -type SecureVariableItems map[string]string +// VariableItems are the actual secrets stored in a variable. They are always +// encrypted and decrypted as a single unit. +type VariableItems map[string]string -func (svi SecureVariableItems) Size() uint64 { +func (svi VariableItems) Size() uint64 { var out uint64 for k, v := range svi { out += uint64(len(k)) @@ -91,72 +90,70 @@ func (svi SecureVariableItems) Size() uint64 { return out } -// Equals checks both the metadata and items in a SecureVariableDecrypted -// struct -func (v1 SecureVariableDecrypted) Equals(v2 SecureVariableDecrypted) bool { - return v1.SecureVariableMetadata.Equals(v2.SecureVariableMetadata) && +// Equals checks both the metadata and items in a VariableDecrypted struct +func (v1 VariableDecrypted) Equals(v2 VariableDecrypted) bool { + return v1.VariableMetadata.Equals(v2.VariableMetadata) && v1.Items.Equals(v2.Items) } -// Equals is a convenience method to provide similar equality checking -// syntax for metadata and the SecureVariablesData or SecureVariableItems -// struct -func (sv SecureVariableMetadata) Equals(sv2 SecureVariableMetadata) bool { +// Equals is a convenience method to provide similar equality checking syntax +// for metadata and the VariablesData or VariableItems struct +func (sv VariableMetadata) Equals(sv2 VariableMetadata) bool { return sv == sv2 } -// Equals performs deep equality checking on the cleartext items -// of a SecureVariableDecrypted. Uses reflect.DeepEqual -func (i1 SecureVariableItems) Equals(i2 SecureVariableItems) bool { +// Equals performs deep equality checking on the cleartext items of a +// VariableDecrypted. Uses reflect.DeepEqual +func (i1 VariableItems) Equals(i2 VariableItems) bool { return reflect.DeepEqual(i1, i2) } -// Equals checks both the metadata and encrypted data for a -// SecureVariableEncrypted struct -func (v1 SecureVariableEncrypted) Equals(v2 SecureVariableEncrypted) bool { - return v1.SecureVariableMetadata.Equals(v2.SecureVariableMetadata) && - v1.SecureVariableData.Equals(v2.SecureVariableData) +// Equals checks both the metadata and encrypted data for a VariableEncrypted +// struct +func (v1 VariableEncrypted) Equals(v2 VariableEncrypted) bool { + return v1.VariableMetadata.Equals(v2.VariableMetadata) && + v1.VariableData.Equals(v2.VariableData) } -// Equals performs deep equality checking on the encrypted data part -// of a SecureVariableEncrypted -func (d1 SecureVariableData) Equals(d2 SecureVariableData) bool { +// Equals performs deep equality checking on the encrypted data part of a +// VariableEncrypted +func (d1 VariableData) Equals(d2 VariableData) bool { return d1.KeyID == d2.KeyID && bytes.Equal(d1.Data, d2.Data) } -func (sv SecureVariableDecrypted) Copy() SecureVariableDecrypted { - return SecureVariableDecrypted{ - SecureVariableMetadata: sv.SecureVariableMetadata, - Items: sv.Items.Copy(), +func (sv VariableDecrypted) Copy() VariableDecrypted { + return VariableDecrypted{ + VariableMetadata: sv.VariableMetadata, + Items: sv.Items.Copy(), } } -func (sv SecureVariableItems) Copy() SecureVariableItems { - out := make(SecureVariableItems, len(sv)) +func (sv VariableItems) Copy() VariableItems { + out := make(VariableItems, len(sv)) for k, v := range sv { out[k] = v } return out } -func (sv SecureVariableEncrypted) Copy() SecureVariableEncrypted { - return SecureVariableEncrypted{ - SecureVariableMetadata: sv.SecureVariableMetadata, - SecureVariableData: sv.SecureVariableData.Copy(), +func (sv VariableEncrypted) Copy() VariableEncrypted { + return VariableEncrypted{ + VariableMetadata: sv.VariableMetadata, + VariableData: sv.VariableData.Copy(), } } -func (sv SecureVariableData) Copy() SecureVariableData { +func (sv VariableData) Copy() VariableData { out := make([]byte, len(sv.Data)) copy(out, sv.Data) - return SecureVariableData{ + return VariableData{ Data: out, KeyID: sv.KeyID, } } -func (sv SecureVariableDecrypted) Validate() error { +func (sv VariableDecrypted) Validate() error { if len(sv.Path) == 0 { return fmt.Errorf("variable requires path") @@ -181,50 +178,50 @@ func (sv SecureVariableDecrypted) Validate() error { return nil } -func (sv *SecureVariableDecrypted) Canonicalize() { +func (sv *VariableDecrypted) Canonicalize() { if sv.Namespace == "" { sv.Namespace = DefaultNamespace } } -// GetNamespace returns the secure variable's namespace. Used for pagination. -func (sv *SecureVariableMetadata) Copy() *SecureVariableMetadata { - var out SecureVariableMetadata = *sv +// GetNamespace returns the variable's namespace. Used for pagination. +func (sv *VariableMetadata) Copy() *VariableMetadata { + var out VariableMetadata = *sv return &out } -// GetNamespace returns the secure variable's namespace. Used for pagination. -func (sv SecureVariableMetadata) GetNamespace() string { +// GetNamespace returns the variable's namespace. Used for pagination. +func (sv VariableMetadata) GetNamespace() string { return sv.Namespace } -// GetID returns the secure variable's path. Used for pagination. -func (sv SecureVariableMetadata) GetID() string { +// GetID returns the variable's path. Used for pagination. +func (sv VariableMetadata) GetID() string { return sv.Path } -// GetCreateIndex returns the secure variable's create index. Used for pagination. -func (sv SecureVariableMetadata) GetCreateIndex() uint64 { +// GetCreateIndex returns the variable's create index. Used for pagination. +func (sv VariableMetadata) GetCreateIndex() uint64 { return sv.CreateIndex } -// SecureVariablesQuota is used to track the total size of secure variables -// entries per namespace. The total length of SecureVariable.EncryptedData in -// bytes will be added to the SecureVariablesQuota table in the same transaction -// as a write, update, or delete. This tracking effectively caps the maximum -// size of secure variables in a given namespace to MaxInt64 bytes. -type SecureVariablesQuota struct { +// VariablesQuota is used to track the total size of variables entries per +// namespace. The total length of Variable.EncryptedData in bytes will be added +// to the VariablesQuota table in the same transaction as a write, update, or +// delete. This tracking effectively caps the maximum size of variables in a +// given namespace to MaxInt64 bytes. +type VariablesQuota struct { Namespace string Size int64 CreateIndex uint64 ModifyIndex uint64 } -func (svq *SecureVariablesQuota) Copy() *SecureVariablesQuota { +func (svq *VariablesQuota) Copy() *VariablesQuota { if svq == nil { return nil } - nq := new(SecureVariablesQuota) + nq := new(VariablesQuota) *nq = *svq return nq } @@ -232,148 +229,147 @@ func (svq *SecureVariablesQuota) Copy() *SecureVariablesQuota { // --------------------------------------- // RPC and FSM request/response objects -// SVOp constants give possible operations available in a transaction. -type SVOp string +// VarOp constants give possible operations available in a transaction. +type VarOp string const ( - SVOpSet SVOp = "set" - SVOpDelete SVOp = "delete" - SVOpDeleteCAS SVOp = "delete-cas" - SVOpCAS SVOp = "cas" + VarOpSet VarOp = "set" + VarOpDelete VarOp = "delete" + VarOpDeleteCAS VarOp = "delete-cas" + VarOpCAS VarOp = "cas" ) -// SVOpResult constants give possible operations results from a transaction. -type SVOpResult string +// VarOpResult constants give possible operations results from a transaction. +type VarOpResult string const ( - SVOpResultOk SVOpResult = "ok" - SVOpResultConflict SVOpResult = "conflict" - SVOpResultRedacted SVOpResult = "conflict-redacted" - SVOpResultError SVOpResult = "error" + VarOpResultOk VarOpResult = "ok" + VarOpResultConflict VarOpResult = "conflict" + VarOpResultRedacted VarOpResult = "conflict-redacted" + VarOpResultError VarOpResult = "error" ) -// SecureVariablesApplyRequest is used by users to operate on the secure variable store -type SecureVariablesApplyRequest struct { - Op SVOp // Operation to be performed during apply - Var *SecureVariableDecrypted // Variable-shaped request data +// VariablesApplyRequest is used by users to operate on the variable store +type VariablesApplyRequest struct { + Op VarOp // Operation to be performed during apply + Var *VariableDecrypted // Variable-shaped request data WriteRequest } -// SecureVariablesApplyResponse is sent back to the user to inform them of success or failure -type SecureVariablesApplyResponse struct { - Op SVOp // Operation performed - Input *SecureVariableDecrypted // Input supplied - Result SVOpResult // Return status from operation - Error error // Error if any - Conflict *SecureVariableDecrypted // Conflicting value if applicable - Output *SecureVariableDecrypted // Operation Result if successful; nil for successful deletes +// VariablesApplyResponse is sent back to the user to inform them of success or failure +type VariablesApplyResponse struct { + Op VarOp // Operation performed + Input *VariableDecrypted // Input supplied + Result VarOpResult // Return status from operation + Error error // Error if any + Conflict *VariableDecrypted // Conflicting value if applicable + Output *VariableDecrypted // Operation Result if successful; nil for successful deletes WriteMeta } -func (r *SecureVariablesApplyResponse) IsOk() bool { - return r.Result == SVOpResultOk +func (r *VariablesApplyResponse) IsOk() bool { + return r.Result == VarOpResultOk } -func (r *SecureVariablesApplyResponse) IsConflict() bool { - return r.Result == SVOpResultConflict || r.Result == SVOpResultRedacted +func (r *VariablesApplyResponse) IsConflict() bool { + return r.Result == VarOpResultConflict || r.Result == VarOpResultRedacted } -func (r *SecureVariablesApplyResponse) IsError() bool { - return r.Result == SVOpResultError +func (r *VariablesApplyResponse) IsError() bool { + return r.Result == VarOpResultError } -func (r *SecureVariablesApplyResponse) IsRedacted() bool { - return r.Result == SVOpResultRedacted +func (r *VariablesApplyResponse) IsRedacted() bool { + return r.Result == VarOpResultRedacted } -// SVApplyStateRequest is used by the FSM to modify the secure variable store -type SVApplyStateRequest struct { - Op SVOp // Which operation are we performing - Var *SecureVariableEncrypted // Which directory entry +// VarApplyStateRequest is used by the FSM to modify the variable store +type VarApplyStateRequest struct { + Op VarOp // Which operation are we performing + Var *VariableEncrypted // Which directory entry WriteRequest } -// SVApplyStateResponse is used by the FSM to inform the RPC layer of success or failure -type SVApplyStateResponse struct { - Op SVOp // Which operation were we performing - Result SVOpResult // What happened (ok, conflict, error) - Error error // error if any - Conflict *SecureVariableEncrypted // conflicting secure variable if applies - WrittenSVMeta *SecureVariableMetadata // for making the SecureVariablesApplyResponse +// VarApplyStateResponse is used by the FSM to inform the RPC layer of success or failure +type VarApplyStateResponse struct { + Op VarOp // Which operation were we performing + Result VarOpResult // What happened (ok, conflict, error) + Error error // error if any + Conflict *VariableEncrypted // conflicting variable if applies + WrittenSVMeta *VariableMetadata // for making the VariablesApplyResponse WriteMeta } -func (r *SVApplyStateRequest) ErrorResponse(raftIndex uint64, err error) *SVApplyStateResponse { - return &SVApplyStateResponse{ +func (r *VarApplyStateRequest) ErrorResponse(raftIndex uint64, err error) *VarApplyStateResponse { + return &VarApplyStateResponse{ Op: r.Op, - Result: SVOpResultError, + Result: VarOpResultError, Error: err, WriteMeta: WriteMeta{Index: raftIndex}, } } -func (r *SVApplyStateRequest) SuccessResponse(raftIndex uint64, meta *SecureVariableMetadata) *SVApplyStateResponse { - return &SVApplyStateResponse{ +func (r *VarApplyStateRequest) SuccessResponse(raftIndex uint64, meta *VariableMetadata) *VarApplyStateResponse { + return &VarApplyStateResponse{ Op: r.Op, - Result: SVOpResultOk, + Result: VarOpResultOk, WrittenSVMeta: meta, WriteMeta: WriteMeta{Index: raftIndex}, } } -func (r *SVApplyStateRequest) ConflictResponse(raftIndex uint64, cv *SecureVariableEncrypted) *SVApplyStateResponse { - var cvCopy SecureVariableEncrypted +func (r *VarApplyStateRequest) ConflictResponse(raftIndex uint64, cv *VariableEncrypted) *VarApplyStateResponse { + var cvCopy VariableEncrypted if cv != nil { // make a copy so that we aren't sending // the live state store version cvCopy = cv.Copy() } - return &SVApplyStateResponse{ + return &VarApplyStateResponse{ Op: r.Op, - Result: SVOpResultConflict, + Result: VarOpResultConflict, Conflict: &cvCopy, WriteMeta: WriteMeta{Index: raftIndex}, } } -func (r *SVApplyStateResponse) IsOk() bool { - return r.Result == SVOpResultOk +func (r *VarApplyStateResponse) IsOk() bool { + return r.Result == VarOpResultOk } -func (r *SVApplyStateResponse) IsConflict() bool { - return r.Result == SVOpResultConflict +func (r *VarApplyStateResponse) IsConflict() bool { + return r.Result == VarOpResultConflict } -func (r *SVApplyStateResponse) IsError() bool { +func (r *VarApplyStateResponse) IsError() bool { // FIXME: This is brittle and requires immense faith that // the response is properly managed. - return r.Result == SVOpResultError + return r.Result == VarOpResultError } -type SecureVariablesListRequest struct { +type VariablesListRequest struct { QueryOptions } -type SecureVariablesListResponse struct { - Data []*SecureVariableMetadata +type VariablesListResponse struct { + Data []*VariableMetadata QueryMeta } -type SecureVariablesReadRequest struct { +type VariablesReadRequest struct { Path string QueryOptions } -type SecureVariablesReadResponse struct { - Data *SecureVariableDecrypted +type VariablesReadResponse struct { + Data *VariableDecrypted QueryMeta } // --------------------------------------- // Keyring state and RPC objects -// RootKey is used to encrypt and decrypt secure variables. It is -// never stored in raft. +// RootKey is used to encrypt and decrypt variables. It is never stored in raft. type RootKey struct { Meta *RootKeyMeta Key []byte // serialized to keystore as base64 blob diff --git a/nomad/structs/variables_test.go b/nomad/structs/variables_test.go index 448e9c575..20eb1cd04 100644 --- a/nomad/structs/variables_test.go +++ b/nomad/structs/variables_test.go @@ -8,10 +8,10 @@ import ( "github.com/stretchr/testify/require" ) -func TestStructs_SecureVariableDecrypted_Copy(t *testing.T) { +func TestStructs_VariableDecrypted_Copy(t *testing.T) { ci.Parallel(t) n := time.Now() - a := SecureVariableMetadata{ + a := VariableMetadata{ Namespace: "a", Path: "a/b/c", CreateIndex: 1, @@ -19,9 +19,9 @@ func TestStructs_SecureVariableDecrypted_Copy(t *testing.T) { ModifyIndex: 2, ModifyTime: n.Add(48 * time.Hour).UnixNano(), } - sv := SecureVariableDecrypted{ - SecureVariableMetadata: a, - Items: SecureVariableItems{ + sv := VariableDecrypted{ + VariableMetadata: a, + Items: VariableItems{ "foo": "bar", "k1": "v1", }, @@ -32,12 +32,12 @@ func TestStructs_SecureVariableDecrypted_Copy(t *testing.T) { require.False(t, sv.Equals(sv2), "sv and sv2 should not be equal") } -func TestStructs_SecureVariableDecrypted_Validate(t *testing.T) { +func TestStructs_VariableDecrypted_Validate(t *testing.T) { ci.Parallel(t) - sv := SecureVariableDecrypted{ - SecureVariableMetadata: SecureVariableMetadata{Namespace: "a"}, - Items: SecureVariableItems{"foo": "bar"}, + sv := VariableDecrypted{ + VariableMetadata: VariableMetadata{Namespace: "a"}, + Items: VariableItems{"foo": "bar"}, } testCases := []struct { diff --git a/nomad/variables_endpoint.go b/nomad/variables_endpoint.go index c1b15446b..3217d30b8 100644 --- a/nomad/variables_endpoint.go +++ b/nomad/variables_endpoint.go @@ -18,24 +18,24 @@ import ( "github.com/hashicorp/nomad/nomad/structs" ) -// SecureVariables encapsulates the secure variables RPC endpoint which is -// callable via the SecureVariables RPCs and externally via the "/v1/var{s}" +// Variables encapsulates the variables RPC endpoint which is +// callable via the Variables RPCs and externally via the "/v1/var{s}" // HTTP API. -type SecureVariables struct { +type Variables struct { srv *Server logger hclog.Logger encrypter *Encrypter } // Apply is used to apply a SV update request to the data store. -func (sv *SecureVariables) Apply(args *structs.SecureVariablesApplyRequest, reply *structs.SecureVariablesApplyResponse) error { - if done, err := sv.srv.forward(structs.SecureVariablesApplyRPCMethod, args, args, reply); done { +func (sv *Variables) Apply(args *structs.VariablesApplyRequest, reply *structs.VariablesApplyResponse) error { + if done, err := sv.srv.forward(structs.VariablesApplyRPCMethod, args, args, reply); done { return err } defer metrics.MeasureSince([]string{ - "nomad", "secure_variables", "apply", string(args.Op)}, time.Now()) + "nomad", "variables", "apply", string(args.Op)}, time.Now()) - // Check if the Namespace is explicitly set on the secure variable. If + // Check if the Namespace is explicitly set on the variable. If // not, use the RequestNamespace if args.Var == nil { return fmt.Errorf("variable must not be nil") @@ -51,20 +51,20 @@ func (sv *SecureVariables) Apply(args *structs.SecureVariablesApplyRequest, repl return err } - var ev *structs.SecureVariableEncrypted + var ev *structs.VariableEncrypted switch args.Op { - case structs.SVOpSet, structs.SVOpCAS: + case structs.VarOpSet, structs.VarOpCAS: ev, err = sv.encrypt(args.Var) if err != nil { - return fmt.Errorf("secure variable error: encrypt: %w", err) + return fmt.Errorf("variable error: encrypt: %w", err) } now := time.Now().UnixNano() ev.CreateTime = now // existing will override if it exists ev.ModifyTime = now - case structs.SVOpDelete, structs.SVOpDeleteCAS: - ev = &structs.SecureVariableEncrypted{ - SecureVariableMetadata: structs.SecureVariableMetadata{ + case structs.VarOpDelete, structs.VarOpDeleteCAS: + ev = &structs.VariableEncrypted{ + VariableMetadata: structs.VariableMetadata{ Namespace: args.Var.Namespace, Path: args.Var.Path, ModifyIndex: args.Var.ModifyIndex, @@ -73,18 +73,18 @@ func (sv *SecureVariables) Apply(args *structs.SecureVariablesApplyRequest, repl } // Make a SVEArgs - sveArgs := structs.SVApplyStateRequest{ + sveArgs := structs.VarApplyStateRequest{ Op: args.Op, Var: ev, WriteRequest: args.WriteRequest, } // Apply the update. - out, index, err := sv.srv.raftApply(structs.SVApplyStateRequestType, sveArgs) + out, index, err := sv.srv.raftApply(structs.VarApplyStateRequestType, sveArgs) if err != nil { return fmt.Errorf("raft apply failed: %w", err) } - r, err := sv.makeSecureVariablesApplyResponse(args, out.(*structs.SVApplyStateResponse), canRead) + r, err := sv.makeVariablesApplyResponse(args, out.(*structs.VarApplyStateResponse), canRead) if err != nil { return err } @@ -93,7 +93,7 @@ func (sv *SecureVariables) Apply(args *structs.SecureVariablesApplyRequest, repl return nil } -func svePreApply(sv *SecureVariables, args *structs.SecureVariablesApplyRequest, vd *structs.SecureVariableDecrypted) (canRead bool, err error) { +func svePreApply(sv *Variables, args *structs.VariablesApplyRequest, vd *structs.VariableDecrypted) (canRead bool, err error) { canRead = false var aclObj *acl.ACL @@ -103,24 +103,24 @@ func svePreApply(sv *SecureVariables, args *structs.SecureVariablesApplyRequest, return } else if aclObj != nil { hasPerm := func(perm string) bool { - return aclObj.AllowSecureVariableOperation(args.Var.Namespace, + return aclObj.AllowVariableOperation(args.Var.Namespace, args.Var.Path, perm) } - canRead = hasPerm(acl.SecureVariablesCapabilityRead) + canRead = hasPerm(acl.VariablesCapabilityRead) switch args.Op { - case structs.SVOpSet, structs.SVOpCAS: - if !hasPerm(acl.SecureVariablesCapabilityWrite) { + case structs.VarOpSet, structs.VarOpCAS: + if !hasPerm(acl.VariablesCapabilityWrite) { err = structs.ErrPermissionDenied return } - case structs.SVOpDelete, structs.SVOpDeleteCAS: - if !hasPerm(acl.SecureVariablesCapabilityDestroy) { + case structs.VarOpDelete, structs.VarOpDeleteCAS: + if !hasPerm(acl.VariablesCapabilityDestroy) { err = structs.ErrPermissionDenied return } default: - err = fmt.Errorf("svPreApply: unexpected SVOp received: %q", args.Op) + err = fmt.Errorf("svPreApply: unexpected VarOp received: %q", args.Op) return } } else { @@ -129,13 +129,13 @@ func svePreApply(sv *SecureVariables, args *structs.SecureVariablesApplyRequest, } switch args.Op { - case structs.SVOpSet, structs.SVOpCAS: + case structs.VarOpSet, structs.VarOpCAS: args.Var.Canonicalize() if err = args.Var.Validate(); err != nil { return } - case structs.SVOpDelete, structs.SVOpDeleteCAS: + case structs.VarOpDelete, structs.VarOpDeleteCAS: if args.Var == nil || args.Var.Path == "" { err = fmt.Errorf("delete requires a Path") return @@ -145,13 +145,13 @@ func svePreApply(sv *SecureVariables, args *structs.SecureVariablesApplyRequest, return } -// MakeSecureVariablesApplyResponse merges the output of this SVApplyStateResponse with the -// SecureVariableDataItems -func (sv *SecureVariables) makeSecureVariablesApplyResponse( - req *structs.SecureVariablesApplyRequest, eResp *structs.SVApplyStateResponse, - canRead bool) (*structs.SecureVariablesApplyResponse, error) { +// MakeVariablesApplyResponse merges the output of this VarApplyStateResponse with the +// VariableDataItems +func (sv *Variables) makeVariablesApplyResponse( + req *structs.VariablesApplyRequest, eResp *structs.VarApplyStateResponse, + canRead bool) (*structs.VariablesApplyResponse, error) { - out := structs.SecureVariablesApplyResponse{ + out := structs.VariablesApplyResponse{ Op: eResp.Op, Input: req.Var, Result: eResp.Result, @@ -162,9 +162,9 @@ func (sv *SecureVariables) makeSecureVariablesApplyResponse( if eResp.IsOk() { if eResp.WrittenSVMeta != nil { // The writer is allowed to read their own write - out.Output = &structs.SecureVariableDecrypted{ - SecureVariableMetadata: *eResp.WrittenSVMeta, - Items: req.Var.Items.Copy(), + out.Output = &structs.VariableDecrypted{ + VariableMetadata: *eResp.WrittenSVMeta, + Items: req.Var.Items.Copy(), } } return &out, nil @@ -172,21 +172,21 @@ func (sv *SecureVariables) makeSecureVariablesApplyResponse( // At this point, the response is necessarily a conflict. // Prime output from the encrypted responses metadata - out.Conflict = &structs.SecureVariableDecrypted{ - SecureVariableMetadata: eResp.Conflict.SecureVariableMetadata, - Items: nil, + out.Conflict = &structs.VariableDecrypted{ + VariableMetadata: eResp.Conflict.VariableMetadata, + Items: nil, } // If the caller can't read the conflicting value, return the // metadata, but no items and flag it as redacted if !canRead { - out.Result = structs.SVOpResultRedacted + out.Result = structs.VarOpResultRedacted return &out, nil } if eResp.Conflict == nil || eResp.Conflict.KeyID == "" { // zero-value conflicts can be returned for delete-if-set - dv := &structs.SecureVariableDecrypted{} + dv := &structs.VariableDecrypted{} dv.Namespace = eResp.Conflict.Namespace dv.Path = eResp.Conflict.Path out.Conflict = dv @@ -203,12 +203,12 @@ func (sv *SecureVariables) makeSecureVariablesApplyResponse( return &out, nil } -// Read is used to get a specific secure variable -func (sv *SecureVariables) Read(args *structs.SecureVariablesReadRequest, reply *structs.SecureVariablesReadResponse) error { - if done, err := sv.srv.forward(structs.SecureVariablesReadRPCMethod, args, args, reply); done { +// Read is used to get a specific variable +func (sv *Variables) Read(args *structs.VariablesReadRequest, reply *structs.VariablesReadResponse) error { + if done, err := sv.srv.forward(structs.VariablesReadRPCMethod, args, args, reply); done { return err } - defer metrics.MeasureSince([]string{"nomad", "secure_variables", "read"}, time.Now()) + defer metrics.MeasureSince([]string{"nomad", "variables", "read"}, time.Now()) _, err := sv.handleMixedAuthEndpoint(args.QueryOptions, acl.PolicyRead, args.Path) @@ -221,7 +221,7 @@ func (sv *SecureVariables) Read(args *structs.SecureVariablesReadRequest, reply queryOpts: &args.QueryOptions, queryMeta: &reply.QueryMeta, run: func(ws memdb.WatchSet, s *state.StateStore) error { - out, err := s.GetSecureVariable(ws, args.RequestNamespace(), args.Path) + out, err := s.GetVariable(ws, args.RequestNamespace(), args.Path) if err != nil { return err } @@ -237,28 +237,28 @@ func (sv *SecureVariables) Read(args *structs.SecureVariablesReadRequest, reply reply.Data = &ov reply.Index = out.ModifyIndex } else { - sv.srv.replySetIndex(state.TableSecureVariables, &reply.QueryMeta) + sv.srv.replySetIndex(state.TableVariables, &reply.QueryMeta) } return nil }} return sv.srv.blockingRPC(&opts) } -// List is used to list secure variables held within state. It supports single +// List is used to list variables held within state. It supports single // and wildcard namespace listings. -func (sv *SecureVariables) List( - args *structs.SecureVariablesListRequest, - reply *structs.SecureVariablesListResponse) error { +func (sv *Variables) List( + args *structs.VariablesListRequest, + reply *structs.VariablesListResponse) error { - if done, err := sv.srv.forward(structs.SecureVariablesListRPCMethod, args, args, reply); done { + if done, err := sv.srv.forward(structs.VariablesListRPCMethod, args, args, reply); done { return err } - defer metrics.MeasureSince([]string{"nomad", "secure_variables", "list"}, time.Now()) + defer metrics.MeasureSince([]string{"nomad", "variables", "list"}, time.Now()) - // If the caller has requested to list secure variables across all namespaces, use + // If the caller has requested to list variables across all namespaces, use // the custom function to perform this. if args.RequestNamespace() == structs.AllNamespacesSentinel { - return sv.listAllSecureVariables(args, reply) + return sv.listAllVariables(args, reply) } aclObj, err := sv.handleMixedAuthEndpoint(args.QueryOptions, @@ -277,7 +277,7 @@ func (sv *SecureVariables) List( run: func(ws memdb.WatchSet, stateStore *state.StateStore) error { // Perform the state query to get an iterator. - iter, err := stateStore.GetSecureVariablesByNamespaceAndPrefix(ws, args.RequestNamespace(), args.Prefix) + iter, err := stateStore.GetVariablesByNamespaceAndPrefix(ws, args.RequestNamespace(), args.Prefix) if err != nil { return err } @@ -294,23 +294,23 @@ func (sv *SecureVariables) List( filters := []paginator.Filter{ paginator.GenericFilter{ Allow: func(raw interface{}) (bool, error) { - sv := raw.(*structs.SecureVariableEncrypted) + sv := raw.(*structs.VariableEncrypted) return strings.HasPrefix(sv.Path, args.Prefix) && - (aclObj == nil || aclObj.AllowSecureVariableOperation(sv.Namespace, sv.Path, acl.PolicyList)), nil + (aclObj == nil || aclObj.AllowVariableOperation(sv.Namespace, sv.Path, acl.PolicyList)), nil }, }, } // Set up our output after we have checked the error. - var svs []*structs.SecureVariableMetadata + var svs []*structs.VariableMetadata // Build the paginator. This includes the function that is - // responsible for appending a variable to the secure variables + // responsible for appending a variable to the variables // stubs slice. paginatorImpl, err := paginator.NewPaginator(iter, tokenizer, filters, args.QueryOptions, func(raw interface{}) error { - sv := raw.(*structs.SecureVariableEncrypted) - svStub := sv.SecureVariableMetadata + sv := raw.(*structs.VariableEncrypted) + svStub := sv.VariableMetadata svs = append(svs, &svStub) return nil }) @@ -333,16 +333,16 @@ func (sv *SecureVariables) List( // Use the index table to populate the query meta as we have no way // of tracking the max index on deletes. - return sv.srv.setReplyQueryMeta(stateStore, state.TableSecureVariables, &reply.QueryMeta) + return sv.srv.setReplyQueryMeta(stateStore, state.TableVariables, &reply.QueryMeta) }, }) } -// listAllSecureVariables is used to list secure variables held within +// listAllVariables is used to list variables held within // state where the caller has used the namespace wildcard identifier. -func (s *SecureVariables) listAllSecureVariables( - args *structs.SecureVariablesListRequest, - reply *structs.SecureVariablesListResponse) error { +func (s *Variables) listAllVariables( + args *structs.VariablesListRequest, + reply *structs.VariablesListResponse) error { // Perform token resolution. The request already goes through forwarding // and metrics setup before being called. @@ -354,7 +354,7 @@ func (s *SecureVariables) listAllSecureVariables( // allowFunc checks whether the caller has the read-job capability on the // passed namespace. allowFunc := func(ns string) bool { - return aclObj.AllowSecureVariableOperation(ns, "", acl.PolicyList) + return aclObj.AllowVariableOperation(ns, "", acl.PolicyList) } // Set up and return the blocking query. @@ -369,7 +369,7 @@ func (s *SecureVariables) listAllSecureVariables( _, err := allowedNSes(aclObj, stateStore, allowFunc) switch err { case structs.ErrPermissionDenied: - reply.Data = make([]*structs.SecureVariableMetadata, 0) + reply.Data = make([]*structs.VariableMetadata, 0) return nil case nil: // Fallthrough. @@ -377,13 +377,13 @@ func (s *SecureVariables) listAllSecureVariables( return err } - // Get all the secure variables stored within state. - iter, err := stateStore.SecureVariables(ws) + // Get all the variables stored within state. + iter, err := stateStore.Variables(ws) if err != nil { return err } - var svs []*structs.SecureVariableMetadata + var svs []*structs.VariableMetadata // Generate the tokenizer to use for pagination using namespace and // ID to ensure complete uniqueness. @@ -397,9 +397,9 @@ func (s *SecureVariables) listAllSecureVariables( filters := []paginator.Filter{ paginator.GenericFilter{ Allow: func(raw interface{}) (bool, error) { - sv := raw.(*structs.SecureVariableEncrypted) + sv := raw.(*structs.VariableEncrypted) return strings.HasPrefix(sv.Path, args.Prefix) && - (aclObj == nil || aclObj.AllowSecureVariableOperation(sv.Namespace, sv.Path, acl.PolicyList)), nil + (aclObj == nil || aclObj.AllowVariableOperation(sv.Namespace, sv.Path, acl.PolicyList)), nil }, }, } @@ -408,8 +408,8 @@ func (s *SecureVariables) listAllSecureVariables( // responsible for appending a variable to the stubs array. paginatorImpl, err := paginator.NewPaginator(iter, tokenizer, filters, args.QueryOptions, func(raw interface{}) error { - sv := raw.(*structs.SecureVariableEncrypted) - svStub := sv.SecureVariableMetadata + sv := raw.(*structs.VariableEncrypted) + svStub := sv.VariableMetadata svs = append(svs, &svStub) return nil }) @@ -432,18 +432,18 @@ func (s *SecureVariables) listAllSecureVariables( // Use the index table to populate the query meta as we have no way // of tracking the max index on deletes. - return s.srv.setReplyQueryMeta(stateStore, state.TableSecureVariables, &reply.QueryMeta) + return s.srv.setReplyQueryMeta(stateStore, state.TableVariables, &reply.QueryMeta) }, }) } -func (sv *SecureVariables) encrypt(v *structs.SecureVariableDecrypted) (*structs.SecureVariableEncrypted, error) { +func (sv *Variables) encrypt(v *structs.VariableDecrypted) (*structs.VariableEncrypted, error) { b, err := json.Marshal(v.Items) if err != nil { return nil, err } - ev := structs.SecureVariableEncrypted{ - SecureVariableMetadata: v.SecureVariableMetadata, + ev := structs.VariableEncrypted{ + VariableMetadata: v.VariableMetadata, } ev.Data, ev.KeyID, err = sv.encrypter.Encrypt(b) if err != nil { @@ -452,13 +452,13 @@ func (sv *SecureVariables) encrypt(v *structs.SecureVariableDecrypted) (*structs return &ev, nil } -func (sv *SecureVariables) decrypt(v *structs.SecureVariableEncrypted) (*structs.SecureVariableDecrypted, error) { +func (sv *Variables) decrypt(v *structs.VariableEncrypted) (*structs.VariableDecrypted, error) { b, err := sv.encrypter.Decrypt(v.Data, v.KeyID) if err != nil { return nil, err } - dv := structs.SecureVariableDecrypted{ - SecureVariableMetadata: v.SecureVariableMetadata, + dv := structs.VariableDecrypted{ + VariableMetadata: v.VariableMetadata, } dv.Items = make(map[string]string) err = json.Unmarshal(b, &dv.Items) @@ -470,7 +470,7 @@ func (sv *SecureVariables) decrypt(v *structs.SecureVariableEncrypted) (*structs // handleMixedAuthEndpoint is a helper to handle auth on RPC endpoints that can // either be called by external clients or by workload identity -func (sv *SecureVariables) handleMixedAuthEndpoint(args structs.QueryOptions, cap, pathOrPrefix string) (*acl.ACL, error) { +func (sv *Variables) handleMixedAuthEndpoint(args structs.QueryOptions, cap, pathOrPrefix string) (*acl.ACL, error) { // Perform the initial token resolution. aclObj, err := sv.srv.ResolveToken(args.AuthToken) @@ -478,7 +478,7 @@ func (sv *SecureVariables) handleMixedAuthEndpoint(args structs.QueryOptions, ca // Perform our ACL validation. If the object is nil, this means ACLs // are not enabled, otherwise trigger the allowed namespace function. if aclObj != nil { - if !aclObj.AllowSecureVariableOperation(args.RequestNamespace(), pathOrPrefix, cap) { + if !aclObj.AllowVariableOperation(args.RequestNamespace(), pathOrPrefix, cap) { return nil, structs.ErrPermissionDenied } } @@ -495,7 +495,7 @@ func (sv *SecureVariables) handleMixedAuthEndpoint(args structs.QueryOptions, ca claims, err := sv.srv.VerifyClaim(args.AuthToken) if err != nil { metrics.IncrCounter([]string{ - "nomad", "secure_variables", "invalid_allocation_identity"}, 1) + "nomad", "variables", "invalid_allocation_identity"}, 1) sv.logger.Trace("allocation identity was not valid", "error", err) return nil, structs.ErrPermissionDenied } @@ -513,7 +513,7 @@ func (sv *SecureVariables) handleMixedAuthEndpoint(args structs.QueryOptions, ca if err != nil { return nil, err // this only returns an error when the state store has gone wrong } - if aclObj != nil && aclObj.AllowSecureVariableOperation( + if aclObj != nil && aclObj.AllowVariableOperation( args.RequestNamespace(), pathOrPrefix, cap) { return aclObj, nil } @@ -522,7 +522,7 @@ func (sv *SecureVariables) handleMixedAuthEndpoint(args structs.QueryOptions, ca // authValidatePrefix asserts that the requested path is valid for // this allocation -func (sv *SecureVariables) authValidatePrefix(claims *structs.IdentityClaims, ns, pathOrPrefix string) error { +func (sv *Variables) authValidatePrefix(claims *structs.IdentityClaims, ns, pathOrPrefix string) error { store, err := sv.srv.fsm.State().Snapshot() if err != nil { diff --git a/nomad/variables_endpoint_test.go b/nomad/variables_endpoint_test.go index a9779ee2c..39c2ae15e 100644 --- a/nomad/variables_endpoint_test.go +++ b/nomad/variables_endpoint_test.go @@ -19,7 +19,7 @@ import ( "github.com/hashicorp/nomad/testutil" ) -func TestSecureVariablesEndpoint_auth(t *testing.T) { +func TestVariablesEndpoint_auth(t *testing.T) { ci.Parallel(t) srv, _, shutdown := TestACLServer(t, func(c *Config) { @@ -36,7 +36,7 @@ func TestSecureVariablesEndpoint_auth(t *testing.T) { alloc1.Namespace = ns jobID := alloc1.JobID - // create an alloc that will have no access to secure variables we create + // create an alloc that will have no access to variables we create alloc2 := mock.Alloc() alloc2.Job.TaskGroups[0].Name = "other-no-permissions" alloc2.TaskGroup = "other-no-permissions" @@ -79,7 +79,7 @@ func TestSecureVariablesEndpoint_auth(t *testing.T) { policy := mock.ACLPolicy() policy.Rules = `namespace "nondefault-namespace" { - secure_variables { + variables { path "nomad/jobs/*" { capabilities = ["list"] } path "other/path" { capabilities = ["read"] } }}` @@ -98,7 +98,7 @@ func TestSecureVariablesEndpoint_auth(t *testing.T) { must.NoError(t, err) t.Run("terminal alloc should be denied", func(t *testing.T) { - _, err = srv.staticEndpoints.SecureVariables.handleMixedAuthEndpoint( + _, err = srv.staticEndpoints.Variables.handleMixedAuthEndpoint( structs.QueryOptions{AuthToken: idToken, Namespace: ns}, "n/a", fmt.Sprintf("nomad/jobs/%s/web/web", jobID)) must.EqError(t, err, structs.ErrPermissionDenied.Error()) @@ -110,7 +110,7 @@ func TestSecureVariablesEndpoint_auth(t *testing.T) { structs.MsgTypeTestSetup, 1200, []*structs.Allocation{alloc1})) t.Run("wrong namespace should be denied", func(t *testing.T) { - _, err = srv.staticEndpoints.SecureVariables.handleMixedAuthEndpoint( + _, err = srv.staticEndpoints.Variables.handleMixedAuthEndpoint( structs.QueryOptions{AuthToken: idToken, Namespace: structs.DefaultNamespace}, "n/a", fmt.Sprintf("nomad/jobs/%s/web/web", jobID)) must.EqError(t, err, structs.ErrPermissionDenied.Error()) @@ -260,7 +260,7 @@ func TestSecureVariablesEndpoint_auth(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.name, func(t *testing.T) { - _, err := srv.staticEndpoints.SecureVariables.handleMixedAuthEndpoint( + _, err := srv.staticEndpoints.Variables.handleMixedAuthEndpoint( structs.QueryOptions{AuthToken: tc.token, Namespace: ns}, tc.cap, tc.path) if tc.expectedErr == nil { must.NoError(t, err) @@ -272,7 +272,7 @@ func TestSecureVariablesEndpoint_auth(t *testing.T) { } -func TestSecureVariablesEndpoint_Apply_ACL(t *testing.T) { +func TestVariablesEndpoint_Apply_ACL(t *testing.T) { ci.Parallel(t) srv, rootToken, shutdown := TestACLServer(t, func(c *Config) { c.NumSchedulers = 0 // Prevent automatic dequeue @@ -282,52 +282,52 @@ func TestSecureVariablesEndpoint_Apply_ACL(t *testing.T) { codec := rpcClient(t, srv) state := srv.fsm.State() - pol := mock.NamespacePolicyWithSecureVariables( + pol := mock.NamespacePolicyWithVariables( structs.DefaultNamespace, "", []string{"list-jobs"}, map[string][]string{ "dropbox/*": {"write"}, }) writeToken := mock.CreatePolicyAndToken(t, state, 1003, "test-invalid", pol) - sv1 := mock.SecureVariable() + sv1 := mock.Variable() sv1.ModifyIndex = 0 - var svHold *structs.SecureVariableDecrypted + var svHold *structs.VariableDecrypted - opMap := map[string]structs.SVOp{ - "set": structs.SVOpSet, - "cas": structs.SVOpCAS, - "delete": structs.SVOpDelete, - "delete-cas": structs.SVOpDeleteCAS, + opMap := map[string]structs.VarOp{ + "set": structs.VarOpSet, + "cas": structs.VarOpCAS, + "delete": structs.VarOpDelete, + "delete-cas": structs.VarOpDeleteCAS, } for name, op := range opMap { t.Run(name+"/no token", func(t *testing.T) { sv1 := sv1 - applyReq := structs.SecureVariablesApplyRequest{ + applyReq := structs.VariablesApplyRequest{ Op: op, Var: sv1, WriteRequest: structs.WriteRequest{Region: "global"}, } - applyResp := new(structs.SecureVariablesApplyResponse) - err := msgpackrpc.CallWithCodec(codec, structs.SecureVariablesApplyRPCMethod, &applyReq, applyResp) + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, applyResp) must.EqError(t, err, structs.ErrPermissionDenied.Error()) }) } t.Run("cas/management token/new", func(t *testing.T) { - applyReq := structs.SecureVariablesApplyRequest{ - Op: structs.SVOpCAS, + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpCAS, Var: sv1, WriteRequest: structs.WriteRequest{ Region: "global", AuthToken: rootToken.SecretID, }, } - applyResp := new(structs.SecureVariablesApplyResponse) - err := msgpackrpc.CallWithCodec(codec, structs.SecureVariablesApplyRPCMethod, &applyReq, applyResp) + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, applyResp) must.NoError(t, err) - must.Eq(t, structs.SVOpResultOk, applyResp.Result) + must.Eq(t, structs.VarOpResultOk, applyResp.Result) must.Equals(t, sv1.Items, applyResp.Output.Items) svHold = applyResp.Output @@ -338,21 +338,21 @@ func TestSecureVariablesEndpoint_Apply_ACL(t *testing.T) { sv := svHold sv.Items["new"] = "newVal" - applyReq := structs.SecureVariablesApplyRequest{ - Op: structs.SVOpCAS, + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpCAS, Var: sv, WriteRequest: structs.WriteRequest{ Region: "global", AuthToken: rootToken.SecretID, }, } - applyResp := new(structs.SecureVariablesApplyResponse) + applyResp := new(structs.VariablesApplyResponse) applyReq.AuthToken = rootToken.SecretID - err := msgpackrpc.CallWithCodec(codec, structs.SecureVariablesApplyRPCMethod, &applyReq, &applyResp) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, &applyResp) must.NoError(t, err) - must.Eq(t, structs.SVOpResultOk, applyResp.Result) + must.Eq(t, structs.VarOpResultOk, applyResp.Result) must.Equals(t, sv.Items, applyResp.Output.Items) svHold = applyResp.Output @@ -365,45 +365,45 @@ func TestSecureVariablesEndpoint_Apply_ACL(t *testing.T) { sv1 := sv1 svHold := svHold - applyReq := structs.SecureVariablesApplyRequest{ - Op: structs.SVOpCAS, + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpCAS, Var: sv1, WriteRequest: structs.WriteRequest{ Region: "global", AuthToken: rootToken.SecretID, }, } - applyResp := new(structs.SecureVariablesApplyResponse) + applyResp := new(structs.VariablesApplyResponse) applyReq.AuthToken = rootToken.SecretID - err := msgpackrpc.CallWithCodec(codec, structs.SecureVariablesApplyRPCMethod, &applyReq, &applyResp) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, &applyResp) must.NoError(t, err) - must.Eq(t, structs.SVOpResultConflict, applyResp.Result) - must.Equals(t, svHold.SecureVariableMetadata, applyResp.Conflict.SecureVariableMetadata) + must.Eq(t, structs.VarOpResultConflict, applyResp.Result) + must.Equals(t, svHold.VariableMetadata, applyResp.Conflict.VariableMetadata) must.Equals(t, svHold.Items, applyResp.Conflict.Items) }) - sv3 := mock.SecureVariable() + sv3 := mock.Variable() sv3.Path = "dropbox/a" sv3.ModifyIndex = 0 t.Run("cas/write-only/read own new", func(t *testing.T) { sv3 := sv3 - applyReq := structs.SecureVariablesApplyRequest{ - Op: structs.SVOpCAS, + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpCAS, Var: sv3, WriteRequest: structs.WriteRequest{ Region: "global", AuthToken: writeToken.SecretID, }, } - applyResp := new(structs.SecureVariablesApplyResponse) + applyResp := new(structs.VariablesApplyResponse) - err := msgpackrpc.CallWithCodec(codec, structs.SecureVariablesApplyRPCMethod, &applyReq, &applyResp) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, &applyResp) must.NoError(t, err) - must.Eq(t, structs.SVOpResultOk, applyResp.Result) + must.Eq(t, structs.VarOpResultOk, applyResp.Result) must.Equals(t, sv3.Items, applyResp.Output.Items) svHold = applyResp.Output }) @@ -414,20 +414,20 @@ func TestSecureVariablesEndpoint_Apply_ACL(t *testing.T) { sv3 := sv3 svHold := svHold - applyReq := structs.SecureVariablesApplyRequest{ - Op: structs.SVOpCAS, + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpCAS, Var: sv3, WriteRequest: structs.WriteRequest{ Region: "global", AuthToken: writeToken.SecretID, }, } - applyResp := new(structs.SecureVariablesApplyResponse) - err := msgpackrpc.CallWithCodec(codec, structs.SecureVariablesApplyRPCMethod, &applyReq, &applyResp) + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, &applyResp) must.NoError(t, err) - must.Eq(t, structs.SVOpResultRedacted, applyResp.Result) - must.Eq(t, svHold.SecureVariableMetadata, applyResp.Conflict.SecureVariableMetadata) + must.Eq(t, structs.VarOpResultRedacted, applyResp.Result) + must.Eq(t, svHold.VariableMetadata, applyResp.Conflict.VariableMetadata) must.Nil(t, applyResp.Conflict.Items) }) @@ -436,24 +436,24 @@ func TestSecureVariablesEndpoint_Apply_ACL(t *testing.T) { sv := svHold sv.Items["upsert"] = "read" - applyReq := structs.SecureVariablesApplyRequest{ - Op: structs.SVOpCAS, + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpCAS, Var: sv, WriteRequest: structs.WriteRequest{ Region: "global", AuthToken: writeToken.SecretID, }, } - applyResp := new(structs.SecureVariablesApplyResponse) - err := msgpackrpc.CallWithCodec(codec, structs.SecureVariablesApplyRPCMethod, &applyReq, &applyResp) + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, &applyResp) must.NoError(t, err) - must.Eq(t, structs.SVOpResultOk, applyResp.Result) + must.Eq(t, structs.VarOpResultOk, applyResp.Result) must.Equals(t, sv.Items, applyResp.Output.Items) }) } -func TestSecureVariablesEndpoint_ComplexACLPolicies(t *testing.T) { +func TestVariablesEndpoint_ComplexACLPolicies(t *testing.T) { ci.Parallel(t) srv, _, shutdown := TestACLServer(t, func(c *Config) { @@ -467,7 +467,7 @@ func TestSecureVariablesEndpoint_ComplexACLPolicies(t *testing.T) { policyRules := ` namespace "dev" { - secure_variables { + variables { path "*" { capabilities = ["list", "read"] } path "system/*" { capabilities = ["deny"] } path "config/system/*" { capabilities = ["deny"] } @@ -475,7 +475,7 @@ namespace "dev" { } namespace "prod" { - secure_variables { + variables { path "*" { capabilities = ["list"] } @@ -495,11 +495,11 @@ namespace "*" {} writeVar := func(ns, path string) { idx++ - sv := mock.SecureVariableEncrypted() + sv := mock.VariableEncrypted() sv.Namespace = ns sv.Path = path - resp := store.SVESet(idx, &structs.SVApplyStateRequest{ - Op: structs.SVOpSet, + resp := store.VarSet(idx, &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, Var: sv, }) must.NoError(t, resp.Error) @@ -522,7 +522,7 @@ namespace "*" {} testListPrefix := func(ns, prefix string, expectedCount int, expectErr error) { t.Run(fmt.Sprintf("ns=%s-prefix=%s", ns, prefix), func(t *testing.T) { - req := &structs.SecureVariablesListRequest{ + req := &structs.VariablesListRequest{ QueryOptions: structs.QueryOptions{ Namespace: ns, Prefix: prefix, @@ -530,15 +530,15 @@ namespace "*" {} Region: "global", }, } - var resp structs.SecureVariablesListResponse + var resp structs.VariablesListResponse if expectErr != nil { must.EqError(t, - msgpackrpc.CallWithCodec(codec, "SecureVariables.List", req, &resp), + msgpackrpc.CallWithCodec(codec, "Variables.List", req, &resp), expectErr.Error()) return } - must.NoError(t, msgpackrpc.CallWithCodec(codec, "SecureVariables.List", req, &resp)) + must.NoError(t, msgpackrpc.CallWithCodec(codec, "Variables.List", req, &resp)) found := "found:\n" for _, sv := range resp.Data { @@ -574,7 +574,7 @@ namespace "*" {} } -func TestSecureVariablesEndpoint_GetSecureVariable_Blocking(t *testing.T) { +func TestVariablesEndpoint_GetVariable_Blocking(t *testing.T) { ci.Parallel(t) s1, cleanupS1 := TestServer(t, nil) @@ -596,7 +596,7 @@ func TestSecureVariablesEndpoint_GetSecureVariable_Blocking(t *testing.T) { }) // Lookup the variable - req := &structs.SecureVariablesReadRequest{ + req := &structs.VariablesReadRequest{ Path: "bbb", QueryOptions: structs.QueryOptions{ Region: "global", @@ -604,9 +604,9 @@ func TestSecureVariablesEndpoint_GetSecureVariable_Blocking(t *testing.T) { MaxQueryTime: 500 * time.Millisecond, }, } - var resp structs.SecureVariablesReadResponse + var resp structs.VariablesReadResponse start := time.Now() - if err := msgpackrpc.CallWithCodec(codec, "SecureVariables.Read", req, &resp); err != nil { + if err := msgpackrpc.CallWithCodec(codec, "Variables.Read", req, &resp); err != nil { t.Fatalf("err: %v", err) } elapsed := time.Since(start) @@ -632,9 +632,9 @@ func TestSecureVariablesEndpoint_GetSecureVariable_Blocking(t *testing.T) { }) req.QueryOptions.MinQueryIndex = 250 - var resp2 structs.SecureVariablesReadResponse + var resp2 structs.VariablesReadResponse start = time.Now() - if err := msgpackrpc.CallWithCodec(codec, "SecureVariables.Read", req, &resp2); err != nil { + if err := msgpackrpc.CallWithCodec(codec, "Variables.Read", req, &resp2); err != nil { t.Fatalf("err: %v", err) } elapsed = time.Since(start) @@ -655,17 +655,17 @@ func TestSecureVariablesEndpoint_GetSecureVariable_Blocking(t *testing.T) { // Variable delete triggers watches delay = 100 * time.Millisecond time.AfterFunc(delay, func() { - sv := mock.SecureVariableEncrypted() + sv := mock.VariableEncrypted() sv.Path = "bbb" - if resp := state.SVEDelete(400, &structs.SVApplyStateRequest{Op: structs.SVOpDelete, Var: sv}); !resp.IsOk() { + if resp := state.VarDelete(400, &structs.VarApplyStateRequest{Op: structs.VarOpDelete, Var: sv}); !resp.IsOk() { t.Fatalf("err: %v", resp.Error) } }) req.QueryOptions.MinQueryIndex = 350 - var resp3 structs.SecureVariablesReadResponse + var resp3 structs.VariablesReadResponse start = time.Now() - if err := msgpackrpc.CallWithCodec(codec, "SecureVariables.Read", req, &resp3); err != nil { + if err := msgpackrpc.CallWithCodec(codec, "Variables.Read", req, &resp3); err != nil { t.Fatalf("err: %v", err) } elapsed = time.Since(start) @@ -686,22 +686,22 @@ func TestSecureVariablesEndpoint_GetSecureVariable_Blocking(t *testing.T) { func writeVar(t *testing.T, s *Server, idx uint64, ns, path string) { store := s.fsm.State() - sv := mock.SecureVariable() + sv := mock.Variable() sv.Namespace = ns sv.Path = path bPlain, err := json.Marshal(sv.Items) must.NoError(t, err) bEnc, kID, err := s.encrypter.Encrypt(bPlain) must.NoError(t, err) - sve := &structs.SecureVariableEncrypted{ - SecureVariableMetadata: sv.SecureVariableMetadata, - SecureVariableData: structs.SecureVariableData{ + sve := &structs.VariableEncrypted{ + VariableMetadata: sv.VariableMetadata, + VariableData: structs.VariableData{ Data: bEnc, KeyID: kID, }, } - resp := store.SVESet(idx, &structs.SVApplyStateRequest{ - Op: structs.SVOpSet, + resp := store.VarSet(idx, &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, Var: sve, }) must.NoError(t, resp.Error)