Skip to content

Commit

Permalink
added changelog
Browse files Browse the repository at this point in the history
  • Loading branch information
roncodingenthusiast committed Nov 17, 2023
1 parent 191f66b commit 1a64a00
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 44 deletions.
3 changes: 3 additions & 0 deletions .changelog/19499.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:feature
acl: add policy bindtype to binding rules.
```
33 changes: 32 additions & 1 deletion agent/consul/acl_endpoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3663,6 +3663,37 @@ func TestACLEndpoint_BindingRuleSet(t *testing.T) {
require.Equal(t, "test-node", rule.BindName)
})

t.Run("Bind Policy", func(t *testing.T) {
req := structs.ACLBindingRuleSetRequest{
Datacenter: "dc1",
BindingRule: structs.ACLBindingRule{
Description: "foobar policy",
AuthMethod: testAuthMethod.Name,
Selector: "serviceaccount.name==abc",
BindType: structs.BindingRuleBindTypePolicy,
BindName: "test-policy",
},
WriteRequest: structs.WriteRequest{Token: TestDefaultInitialManagementToken},
}
var resp structs.ACLBindingRule

err := aclEp.BindingRuleSet(&req, &resp)
require.NoError(t, err)
require.NotNil(t, resp.ID)

// Get the rule directly to validate that it exists
ruleResp, err := retrieveTestBindingRule(codec, TestDefaultInitialManagementToken, "dc1", resp.ID)
require.NoError(t, err)
rule := ruleResp.BindingRule

require.NotEmpty(t, rule.ID)
require.Equal(t, rule.Description, "foobar policy")
require.Equal(t, rule.AuthMethod, testAuthMethod.Name)
require.Equal(t, "serviceaccount.name==abc", rule.Selector)
require.Equal(t, structs.BindingRuleBindTypePolicy, rule.BindType)
require.Equal(t, "test-policy", rule.BindName)
})

t.Run("templated policy", func(t *testing.T) {
req := structs.ACLBindingRuleSetRequest{
Datacenter: "dc1",
Expand Down Expand Up @@ -3841,7 +3872,7 @@ func TestACLEndpoint_BindingRuleSet(t *testing.T) {
t.Run("Create fails; invalid bind type", func(t *testing.T) {
reqRule := newRule()
reqRule.BindType = "invalid"
requireSetErrors(t, reqRule, "Invalid Binding Rule: unknown BindType")
requireSetErrors(t, reqRule, "invalid Binding Rule: unknown BindType")
})

t.Run("Create fails; bind name with unknown vars", func(t *testing.T) {
Expand Down
8 changes: 4 additions & 4 deletions agent/consul/auth/binder.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ type BinderStateStore interface {
ACLPolicyGetByName(ws memdb.WatchSet, policyName string, entMeta *acl.EnterpriseMeta) (uint64, *structs.ACLPolicy, error)
}

// Bindings contains the ACL roles, service identities, node identities,
// Bindings contains the ACL roles, service identities, node identities, policies,
// templated policies, and enterprise meta to be assigned to the created token.
type Bindings struct {
Roles []structs.ACLTokenRoleLink
ServiceIdentities []*structs.ACLServiceIdentity
NodeIdentities []*structs.ACLNodeIdentity
Policies []structs.ACLTokenPolicyLink
Policies []structs.ACLTokenPolicyLink
TemplatedPolicies structs.ACLTemplatedPolicies
EnterpriseMeta acl.EnterpriseMeta
}
Expand Down Expand Up @@ -135,7 +135,7 @@ func (b *Binder) Bind(authMethod *structs.ACLAuthMethod, verifiedIdentity *authm

if policy != nil {
bindings.Policies = append(bindings.Policies, structs.ACLTokenPolicyLink{
ID: policy.ID,
ID: policy.ID,
Name: policy.Name,
})
}
Expand Down Expand Up @@ -204,7 +204,7 @@ func IsValidBindingRule(bindType, bindName string, bindVars *structs.ACLTemplate
return fmt.Errorf("failed to validate bindType %q: %w", bindType, err)
}
default:
return fmt.Errorf("Invalid Binding Rule: unknown BindType %q", bindType)
return fmt.Errorf("invalid Binding Rule: unknown BindType %q", bindType)
}

return nil
Expand Down
49 changes: 30 additions & 19 deletions agent/consul/auth/binder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/hashicorp/consul/agent/consul/authmethod"
"github.com/hashicorp/consul/agent/consul/state"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/api"
)

func TestBindings_None(t *testing.T) {
Expand All @@ -27,11 +28,17 @@ func TestBindings_None(t *testing.T) {
b = &Bindings{Roles: []structs.ACLTokenRoleLink{{ID: generateID(t)}}}
require.False(t, b.None())

b = &Bindings{Policies: []structs.ACLTokenPolicyLink{{ID: generateID(t)}}}
require.False(t, b.None())

b = &Bindings{ServiceIdentities: []*structs.ACLServiceIdentity{{ServiceName: "web"}}}
require.False(t, b.None())

b = &Bindings{NodeIdentities: []*structs.ACLNodeIdentity{{NodeName: "node-123"}}}
require.False(t, b.None())

b = &Bindings{TemplatedPolicies: []*structs.ACLTemplatedPolicy{{TemplateName: api.ACLTemplatedPolicyDNSName}}}
require.False(t, b.None())
}

func TestBinder_Policy_Success(t *testing.T) {
Expand Down Expand Up @@ -363,16 +370,16 @@ func Test_IsValidBindingRule(t *testing.T) {
"invalid", "blah", nil, "", true},
// valid HIL, invalid name
{"empty",
"both", "", nil, "", true},
"all", "", nil, "", true},
{"just end",
"both", "}", nil, "", true},
"all", "}", nil, "", true},
{"var without start",
"both", " item }", nil, "item", true},
"all", " item }", nil, "item", true},
{"two vars missing second start",
"both", "before-${ item }after--more }", nil, "item,more", true},
"all", "before-${ item }after--more }", nil, "item,more", true},
// names for the two types are validated differently
{"@ is disallowed",
"both", "bad@name", nil, "", true},
"all", "bad@name", nil, "", true},
{"leading dash",
"role", "-name", nil, "", false},
{"leading dash",
Expand All @@ -386,7 +393,7 @@ func Test_IsValidBindingRule(t *testing.T) {
{"trailing dash",
"service", "name-", nil, "", true},
{"inner dash",
"both", "name-end", nil, "", false},
"all", "name-end", nil, "", false},
{"upper case",
"role", "NAME", nil, "", false},
{"upper case",
Expand All @@ -395,28 +402,28 @@ func Test_IsValidBindingRule(t *testing.T) {
"service", "NAME", nil, "", true},
// valid HIL, valid name
{"no vars",
"both", "nothing", nil, "", false},
"all", "nothing", nil, "", false},
{"just var",
"both", "${item}", nil, "item", false},
"all", "${item}", nil, "item", false},
{"var in middle",
"both", "before-${item}after", nil, "item", false},
"all", "before-${item}after", nil, "item", false},
{"two vars",
"both", "before-${item}after-${more}", nil, "item,more", false},
"all", "before-${item}after-${more}", nil, "item,more", false},
// bad
{"no bind name",
"both", "", nil, "", true},
"all", "", nil, "", true},
{"just start",
"both", "${", nil, "", true},
"all", "${", nil, "", true},
{"backwards",
"both", "}${", nil, "", true},
"all", "}${", nil, "", true},
{"no varname",
"both", "${}", nil, "", true},
"all", "${}", nil, "", true},
{"missing map key",
"both", "${item}", nil, "", true},
"all", "${item}", nil, "", true},
{"var without end",
"both", "${ item ", nil, "item", true},
"all", "${ item ", nil, "item", true},
{"two vars missing first end",
"both", "before-${ item after-${ more }", nil, "item,more", true},
"all", "before-${ item after-${ more }", nil, "item,more", true},

// bind type: templated policy - bad input
{"templated-policy missing bindvars", "templated-policy", "builtin/service", nil, "", true},
Expand All @@ -432,12 +439,16 @@ func Test_IsValidBindingRule(t *testing.T) {
"templated-policy", "builtin/service", &structs.ACLTemplatedPolicyVariables{Name: "before-${item}after-${more}"}, "item,more", false},
} {
var cases []testcase
if test.bindType == "both" {
if test.bindType == "all" {
test1 := test
test1.bindType = "role"
test2 := test
test2.bindType = "service"
cases = []testcase{test1, test2}
test3 := test
test3.bindType = "policy"
test4 := test
test4.bindType = "node"
cases = []testcase{test1, test2, test3, test4}
} else {
cases = []testcase{test}
}
Expand Down
2 changes: 1 addition & 1 deletion api/acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ const (
// BindingRuleBindTypeNode binds to a node identity with given name.
BindingRuleBindTypeNode BindingRuleBindType = "node"

// BindingRuleBindTypeNode binds to a specific policy with given name.
// BindingRuleBindTypePolicy binds to a specific policy with given name.
BindingRuleBindTypePolicy BindingRuleBindType = "policy"

// BindingRuleBindTypeTemplatedPolicy binds to a templated policy with given template name and variables.
Expand Down
20 changes: 2 additions & 18 deletions website/content/commands/acl/binding-rule/create.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Usage: `consul acl binding-rule create [options] [args]`
- `-bind-name=<string>` - Name to bind on match. Can use `${var}`
interpolation. This flag is required.

- `-bind-type=<string>` - Type of binding to perform (`"service"`, `"policy"`, or `"role"`).
- `-bind-type=<string>` - Type of binding to perform (`"service"` or `"role"`).

- `-description=<string>` - A description of the binding rule.

Expand Down Expand Up @@ -89,20 +89,4 @@ Description: just vault role
BindType: role
BindName: vault
Selector: serviceaccount.namespace==default and serviceaccount.name==vault
```

Create a new binding rule that binds to a service:

```shell-session
$ consul acl binding-rule create -method 'nomad' \
-description 'gets policy for nomad job' \
-bind-type 'policy' \
-bind-name 'nomad-${nomad.jobname}' \
-selector 'nomad.jobname==billing-app'
ID: e21ae868-7b13-a230-0235-f8e83510642c
AuthMethod: nomad
Description: gets policy for nomad job
BindType: role
BindName: nomad-billing-app
Selector: serviceaccount.namespace==default and serviceaccount.name==vault
```
```
2 changes: 1 addition & 1 deletion website/content/commands/acl/binding-rule/update.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Usage: `consul acl binding-rule update [options] [args]`
- `-bind-name=<string>` - Name to bind on match. Can use `${var}`
interpolation. This flag is required.

- `-bind-type=<string>` - Type of binding to perform (`"service"`, `"policy"`, or `"role"`).
- `-bind-type=<string>` - Type of binding to perform (`"service"` or `"role"`).

- `-description=<string>` - A description of the binding rule.

Expand Down

0 comments on commit 1a64a00

Please sign in to comment.