Skip to content

Commit

Permalink
Pathpol: Change policy in options (#2349)
Browse files Browse the repository at this point in the history
Change policy in pathpol.Options to ExtPolicy. This is required so an option can not only have anonymous policies, but also extend others.
  • Loading branch information
worxli authored Aug 29, 2019
1 parent 40c4563 commit 7b76f7a
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 80 deletions.
58 changes: 30 additions & 28 deletions doc/PathPolicy.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,6 @@ Examples:
- Match outbound IF _2_ of AS _1-ff00:0:133_: `1-ff00:0:133#0,2`
- Match inbound or outbound IF _2_ of AS _1-ff00:0:133_: `1-ff00:0:133#2`

## Operators

The path policy language has the following operators:

ACL:

- `+` (allow predicate)
- `-` (deny predicate)

Sequence:

- `?` (the preceding HP may appear at most once)
- `+` (the preceding **ISD-level** HP must appear at least once)
- `*` (the preceding **ISD-level** HP may appear zero or more times)
- `|` (logical OR)

Planned:

- `!` (logical NOT)
- `&` (logical AND)

## Policy

A policy is defined by a policy object. It can have the following attributes:
Expand All @@ -56,6 +35,7 @@ A policy is defined by a policy object. It can have the following attributes:
- [`sequence`](#Sequence) (space separated list of HPs, may contain operators)
- [`options`](#Options) (list of option policies)
- `weight` (importance level, only valid under `options`)
- `policy` (a policy object)

Planned:

Expand All @@ -74,6 +54,11 @@ Planned:

### ACL

#### Operators

- `+` (allow predicate)
- `-` (deny predicate)

The ACL can be used to deny (blacklist) or allow (whitelist) ISDs, ASes and IFs. A deny entry is of
the following form `- ISD-AS#IF`, where the second part is a [HP](#HP). If a deny entry matches any
hop on a path, the path is not allowed.
Expand Down Expand Up @@ -101,6 +86,18 @@ but denying all other ASes in ISD _1_. The last entry makes sure that any other
### Sequence
#### Operators
- `?` (the preceding HP may appear at most once)
- `+` (the preceding **ISD-level** HP must appear at least once)
- `*` (the preceding **ISD-level** HP may appear zero or more times)
- `|` (logical OR)

Planned:

- `!` (logical NOT)
- `&` (logical AND)

The sequence is a string of space separated HPs. The [operators](#Operators) can be used for
advanced interface sequences.

Expand Down Expand Up @@ -177,14 +174,19 @@ third option which denies only hops in AS _1-ff00:0:133_, is used.
- policy_with_options:
options:
- weight: 3
extends: option_3
policy:
extends:
- option_3
- weight: 2
acl:
- "- 1-ff00:0:130#0"
- "- 1-ff00:0:131#0"
- "- 1-ff00:0:132#0"
- "+"
- extends: option_1
policy:
acl:
- "- 1-ff00:0:130#0"
- "- 1-ff00:0:131#0"
- "- 1-ff00:0:132#0"
- "+"
- policy:
extends:
- option_1
- option_3:
acl:
Expand Down
1 change: 1 addition & 0 deletions go/lib/pathpol/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@ go_test(
"//go/lib/xtest/graph:go_default_library",
"@com_github_golang_mock//gomock:go_default_library",
"@com_github_stretchr_testify//assert:go_default_library",
"@com_github_stretchr_testify//require:go_default_library",
],
)
4 changes: 2 additions & 2 deletions go/lib/pathpol/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,6 @@ func (p *Policy) evalOptions(inputSet PathSet) PathSet {

// Option contains a weight and a policy and is used as a list item in Policy.Options
type Option struct {
Weight int
Policy *Policy
Weight int `json:"weight"`
Policy *ExtPolicy `json:"policy"`
}
135 changes: 85 additions & 50 deletions go/lib/pathpol/policy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@
package pathpol

import (
"encoding/json"
"fmt"
"strings"
"testing"

"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/scionproto/scion/go/lib/addr"
"github.com/scionproto/scion/go/lib/common"
Expand Down Expand Up @@ -441,12 +443,13 @@ func TestOptionsEval(t *testing.T) {
"one option, allow everything": {
Policy: NewPolicy("", nil, nil, []Option{
{
Policy: &Policy{
ACL: &ACL{Entries: []*ACLEntry{
{
Action: Allow,
Rule: mustHopPredicate(t, "0-0#0")},
denyEntry}}},
Policy: &ExtPolicy{
Policy: &Policy{
ACL: &ACL{Entries: []*ACLEntry{
{
Action: Allow,
Rule: mustHopPredicate(t, "0-0#0")},
denyEntry}}}},
Weight: 0},
}),
Src: xtest.MustParseIA("2-ff00:0:212"),
Expand All @@ -456,18 +459,20 @@ func TestOptionsEval(t *testing.T) {
"two options, deny everything": {
Policy: NewPolicy("", nil, nil, []Option{
{
Policy: &Policy{
ACL: &ACL{Entries: []*ACLEntry{{
Action: Allow,
Rule: mustHopPredicate(t, "0-0#0")},
denyEntry}}},
Policy: &ExtPolicy{
Policy: &Policy{
ACL: &ACL{Entries: []*ACLEntry{{
Action: Allow,
Rule: mustHopPredicate(t, "0-0#0")},
denyEntry}}}},
Weight: 0},
{
Policy: &Policy{
ACL: &ACL{Entries: []*ACLEntry{{
Action: Deny,
Rule: mustHopPredicate(t, "0-0#0")},
denyEntry}}},
Policy: &ExtPolicy{
Policy: &Policy{
ACL: &ACL{Entries: []*ACLEntry{{
Action: Deny,
Rule: mustHopPredicate(t, "0-0#0")},
denyEntry}}}},
Weight: 1},
}),
Src: xtest.MustParseIA("2-ff00:0:212"),
Expand All @@ -476,15 +481,17 @@ func TestOptionsEval(t *testing.T) {
},
"two options, first: allow everything, second: allow one path": {
Policy: NewPolicy("", nil, nil, []Option{
{Policy: &Policy{ACL: &ACL{Entries: []*ACLEntry{
{Action: Allow, Rule: mustHopPredicate(t, "0-0#0")},
denyEntry}}},
{Policy: &ExtPolicy{
Policy: &Policy{ACL: &ACL{Entries: []*ACLEntry{
{Action: Allow, Rule: mustHopPredicate(t, "0-0#0")},
denyEntry}}}},
Weight: 0},
{Policy: &Policy{ACL: &ACL{Entries: []*ACLEntry{
{Action: Deny, Rule: mustHopPredicate(t, "1-ff00:0:110#0")},
{Action: Deny, Rule: mustHopPredicate(t, "1-ff00:0:120#0")},
{Action: Deny, Rule: mustHopPredicate(t, "1-ff00:0:111#2823")},
allowEntry}}},
{Policy: &ExtPolicy{
Policy: &Policy{ACL: &ACL{Entries: []*ACLEntry{
{Action: Deny, Rule: mustHopPredicate(t, "1-ff00:0:110#0")},
{Action: Deny, Rule: mustHopPredicate(t, "1-ff00:0:120#0")},
{Action: Deny, Rule: mustHopPredicate(t, "1-ff00:0:111#2823")},
allowEntry}}}},
Weight: 1},
}),
Src: xtest.MustParseIA("1-ff00:0:122"),
Expand All @@ -493,13 +500,15 @@ func TestOptionsEval(t *testing.T) {
},
"two options, combined": {
Policy: NewPolicy("", nil, nil, []Option{
{Policy: &Policy{ACL: &ACL{Entries: []*ACLEntry{
{Action: Deny, Rule: mustHopPredicate(t, "1-ff00:0:120#0")},
allowEntry}}},
{Policy: &ExtPolicy{
Policy: &Policy{ACL: &ACL{Entries: []*ACLEntry{
{Action: Deny, Rule: mustHopPredicate(t, "1-ff00:0:120#0")},
allowEntry}}}},
Weight: 0},
{Policy: &Policy{ACL: &ACL{Entries: []*ACLEntry{
{Action: Deny, Rule: mustHopPredicate(t, "2-ff00:0:210#0")},
allowEntry}}},
{Policy: &ExtPolicy{
Policy: &Policy{ACL: &ACL{Entries: []*ACLEntry{
{Action: Deny, Rule: mustHopPredicate(t, "2-ff00:0:210#0")},
allowEntry}}}},
Weight: 0},
}),
Src: xtest.MustParseIA("1-ff00:0:110"),
Expand All @@ -508,13 +517,15 @@ func TestOptionsEval(t *testing.T) {
},
"two options, take first": {
Policy: NewPolicy("", nil, nil, []Option{
{Policy: &Policy{ACL: &ACL{Entries: []*ACLEntry{
{Action: Deny, Rule: mustHopPredicate(t, "1-ff00:0:120#0")},
allowEntry}}},
{Policy: &ExtPolicy{
Policy: &Policy{ACL: &ACL{Entries: []*ACLEntry{
{Action: Deny, Rule: mustHopPredicate(t, "1-ff00:0:120#0")},
allowEntry}}}},
Weight: 1},
{Policy: &Policy{ACL: &ACL{Entries: []*ACLEntry{
{Action: Deny, Rule: mustHopPredicate(t, "2-ff00:0:210#0")},
allowEntry}}},
{Policy: &ExtPolicy{
Policy: &Policy{ACL: &ACL{Entries: []*ACLEntry{
{Action: Deny, Rule: mustHopPredicate(t, "2-ff00:0:210#0")},
allowEntry}}}},
Weight: 0},
}),
Src: xtest.MustParseIA("1-ff00:0:110"),
Expand All @@ -523,13 +534,15 @@ func TestOptionsEval(t *testing.T) {
},
"two options, take second": {
Policy: NewPolicy("", nil, nil, []Option{
{Policy: &Policy{ACL: &ACL{Entries: []*ACLEntry{
{Action: Deny, Rule: mustHopPredicate(t, "1-ff00:0:120#0")},
allowEntry}}},
{Policy: &ExtPolicy{
Policy: &Policy{ACL: &ACL{Entries: []*ACLEntry{
{Action: Deny, Rule: mustHopPredicate(t, "1-ff00:0:120#0")},
allowEntry}}}},
Weight: 1},
{Policy: &Policy{ACL: &ACL{Entries: []*ACLEntry{
{Action: Deny, Rule: mustHopPredicate(t, "2-ff00:0:210#0")},
allowEntry}}},
{Policy: &ExtPolicy{
Policy: &Policy{ACL: &ACL{Entries: []*ACLEntry{
{Action: Deny, Rule: mustHopPredicate(t, "2-ff00:0:210#0")},
allowEntry}}}},
Weight: 10},
}),
Src: xtest.MustParseIA("1-ff00:0:110"),
Expand Down Expand Up @@ -580,20 +593,22 @@ func TestExtends(t *testing.T) {
Policy: &Policy{Name: "policy1", Options: []Option{
{
Weight: 1,
Policy: &Policy{ACL: &ACL{Entries: []*ACLEntry{{
Action: Allow,
Rule: mustHopPredicate(t, "0-0#0")},
denyEntry}}},
Policy: &ExtPolicy{
Policy: &Policy{ACL: &ACL{Entries: []*ACLEntry{{
Action: Allow,
Rule: mustHopPredicate(t, "0-0#0")},
denyEntry}}}},
},
}}},
},
ExtendedPolicy: &Policy{Options: []Option{
{
Weight: 1,
Policy: &Policy{ACL: &ACL{Entries: []*ACLEntry{{
Action: Allow,
Rule: mustHopPredicate(t, "0-0#0")},
denyEntry}},
Policy: &ExtPolicy{
Policy: &Policy{ACL: &ACL{Entries: []*ACLEntry{{
Action: Allow,
Rule: mustHopPredicate(t, "0-0#0")},
denyEntry}}},
},
},
},
Expand Down Expand Up @@ -824,3 +839,23 @@ func mustHopPredicate(t *testing.T, str string) *HopPredicate {
xtest.FailOnErr(t, err)
return hp
}

func TestPolicyJsonConversion(t *testing.T) {
policy := NewPolicy("", nil, nil, []Option{
{
Policy: &ExtPolicy{
Policy: &Policy{
ACL: &ACL{Entries: []*ACLEntry{
{
Action: Allow,
Rule: mustHopPredicate(t, "0-0#0")},
denyEntry}}}},
Weight: 0},
})
jsonPol, err := json.Marshal(policy)
require.NoError(t, err)
var pol Policy
err = json.Unmarshal(jsonPol, &pol)
assert.NoError(t, err)
assert.Equal(t, policy, &pol)
}

0 comments on commit 7b76f7a

Please sign in to comment.