diff --git a/acl/policy.go b/acl/policy.go index b8fc498b67..0796a1aece 100644 --- a/acl/policy.go +++ b/acl/policy.go @@ -73,6 +73,11 @@ type ServicePolicy struct { Name string `hcl:",key"` Policy string Sentinel Sentinel + + // Intentions is the policy for intentions where this service is the + // destination. This may be empty, in which case the Policy determines + // the intentions policy. + Intentions string } func (s *ServicePolicy) GoString() string { @@ -197,6 +202,9 @@ func Parse(rules string, sentinel sentinel.Evaluator) (*Policy, error) { if !isPolicyValid(sp.Policy) { return nil, fmt.Errorf("Invalid service policy: %#v", sp) } + if sp.Intentions != "" && !isPolicyValid(sp.Intentions) { + return nil, fmt.Errorf("Invalid service intentions policy: %#v", sp) + } if err := isSentinelValid(sentinel, sp.Policy, sp.Sentinel); err != nil { return nil, fmt.Errorf("Invalid service Sentinel policy: %#v, got error:%v", sp, err) } diff --git a/acl/policy_test.go b/acl/policy_test.go index 37b8216f5e..9d3ae8f69c 100644 --- a/acl/policy_test.go +++ b/acl/policy_test.go @@ -6,6 +6,88 @@ import ( "testing" ) +func TestParse_table(t *testing.T) { + // Note that the table tests are newer than other tests. Many of the + // other aspects of policy parsing are tested in older tests below. New + // parsing tests should be added to this table as its easier to maintain. + cases := []struct { + Name string + Input string + Expected *Policy + Err string + }{ + { + "service no intentions", + ` +service "foo" { + policy = "write" +} + `, + &Policy{ + Services: []*ServicePolicy{ + { + Name: "foo", + Policy: "write", + }, + }, + }, + "", + }, + + { + "service intentions", + ` +service "foo" { + policy = "write" + intentions = "read" +} + `, + &Policy{ + Services: []*ServicePolicy{ + { + Name: "foo", + Policy: "write", + Intentions: "read", + }, + }, + }, + "", + }, + + { + "service intention: invalid value", + ` +service "foo" { + policy = "write" + intentions = "foo" +} + `, + nil, + "service intentions", + }, + } + + for _, tc := range cases { + t.Run(tc.Name, func(t *testing.T) { + actual, err := Parse(tc.Input, nil) + if (err != nil) != (tc.Err != "") { + t.Fatalf("err: %s", err) + } + if err != nil { + if !strings.Contains(err.Error(), tc.Err) { + t.Fatalf("err: %s", err) + } + + return + } + + if !reflect.DeepEqual(actual, tc.Expected) { + t.Fatalf("bad: %#v", actual) + } + }) + } +} + func TestACLPolicy_Parse_HCL(t *testing.T) { inp := ` agent "foo" {