Skip to content

Commit b6ed91a

Browse files
ingress-controller/gateway: fix missing source ppl (#1324)
Backport edf5320 from #1323 Co-authored-by: Caleb Doxsey <cdoxsey@pomerium.com>
1 parent d9e3e06 commit b6ed91a

5 files changed

Lines changed: 119 additions & 30 deletions

File tree

cspell.config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ words:
1717
- protobuf
1818
- protojson
1919
- readyz
20+
- rego
2021
- sharedkey
2122
- sslcert
2223
- sslkey

internal/policy/policy.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package policy
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
"github.com/open-policy-agent/opa/ast"
8+
"google.golang.org/protobuf/proto"
9+
10+
"github.com/pomerium/pomerium/pkg/policy"
11+
)
12+
13+
// Parse parses PPL into rego.
14+
func Parse(src string) (ppl *string, rego []string, err error) {
15+
regoSrc, err := policy.GenerateRegoFromReader(strings.NewReader(src))
16+
if err != nil {
17+
return nil, nil, fmt.Errorf("couldn't parse policy: %w", err)
18+
}
19+
20+
_, err = ast.ParseModule("policy.rego", regoSrc)
21+
if err != nil && strings.Contains(err.Error(), "package expected") {
22+
_, err = ast.ParseModule("policy.rego", "package pomerium.policy\n\n"+regoSrc)
23+
}
24+
if err != nil {
25+
return nil, nil, fmt.Errorf("internal error: %w", err)
26+
}
27+
28+
return proto.String(src), []string{regoSrc}, nil
29+
}

pomerium/gateway/filters.go

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,13 @@ package gateway
22

33
import (
44
"fmt"
5-
"strings"
65

7-
"github.com/open-policy-agent/opa/ast"
86
gateway_v1 "sigs.k8s.io/gateway-api/apis/v1"
97

108
icgv1alpha1 "github.com/pomerium/ingress-controller/apis/gateway/v1alpha1"
9+
"github.com/pomerium/ingress-controller/internal/policy"
1110
"github.com/pomerium/ingress-controller/model"
1211
pb "github.com/pomerium/pomerium/pkg/grpc/config"
13-
"github.com/pomerium/pomerium/pkg/policy"
1412
)
1513

1614
func applyFilters(
@@ -107,27 +105,25 @@ func applyExtensionFilter(
107105

108106
// PolicyFilter applies a Pomerium policy defined by the PolicyFilter CRD.
109107
type PolicyFilter struct {
110-
rego string
108+
ppl *string
109+
rego []string
111110
}
112111

113112
// NewPolicyFilter parses a PolicyFilter CRD object, returning an error if the object is not valid.
114113
func NewPolicyFilter(obj *icgv1alpha1.PolicyFilter) (*PolicyFilter, error) {
115-
src, err := policy.GenerateRegoFromReader(strings.NewReader(obj.Spec.PPL))
114+
var err error
115+
filter := new(PolicyFilter)
116+
filter.ppl, filter.rego, err = policy.Parse(obj.Spec.PPL)
116117
if err != nil {
117-
return nil, fmt.Errorf("couldn't parse policy: %w", err)
118+
return nil, err
118119
}
119-
120-
_, err = ast.ParseModule("policy.rego", src)
121-
if err != nil && strings.Contains(err.Error(), "package expected") {
122-
_, err = ast.ParseModule("policy.rego", "package pomerium.policy\n\n"+src)
123-
}
124-
if err != nil {
125-
return nil, fmt.Errorf("internal error: %w", err)
126-
}
127-
return &PolicyFilter{src}, nil
120+
return filter, nil
128121
}
129122

130123
// ApplyToRoute applies this policy filter to a Pomerium route proto.
131124
func (f *PolicyFilter) ApplyToRoute(r *pb.Route) {
132-
r.Policies = append(r.Policies, &pb.Policy{Rego: []string{f.rego}})
125+
r.Policies = append(r.Policies, &pb.Policy{
126+
Rego: f.rego,
127+
SourcePpl: f.ppl,
128+
})
133129
}

pomerium/gateway/translate_test.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package gateway_test
2+
3+
import (
4+
"encoding/json"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/require"
9+
v1 "sigs.k8s.io/gateway-api/apis/v1"
10+
11+
icgv1alpha1 "github.com/pomerium/ingress-controller/apis/gateway/v1alpha1"
12+
"github.com/pomerium/ingress-controller/model"
13+
"github.com/pomerium/ingress-controller/pomerium/gateway"
14+
)
15+
16+
func TestTranslate(t *testing.T) {
17+
t.Parallel()
18+
19+
t.Run("fills source ppl", func(t *testing.T) {
20+
t.Parallel()
21+
22+
var policy icgv1alpha1.PolicyFilter
23+
require.NoError(t, json.Unmarshal([]byte(`{
24+
"metadata": {
25+
"name": "example"
26+
},
27+
"spec": {
28+
"ppl": "allow:\n and:\n - email:\n is: user@example.com"
29+
}
30+
}`), &policy))
31+
policyFilter, err := gateway.NewPolicyFilter(&policy)
32+
require.NoError(t, err)
33+
34+
var route v1.HTTPRoute
35+
require.NoError(t, json.Unmarshal([]byte(`{
36+
"spec": {
37+
"hostnames": ["example.com"],
38+
"rules": [{
39+
"matches": [{
40+
"path": {
41+
"value": "/"
42+
}
43+
}],
44+
"filters": [{
45+
"type": "ExtensionRef",
46+
"extensionRef": {
47+
"group": "gateway.pomerium.io",
48+
"kind": "PolicyFilter",
49+
"name": "example"
50+
}
51+
}]
52+
}]
53+
}
54+
}`), &route))
55+
56+
result := gateway.TranslateRoutes(t.Context(),
57+
&model.GatewayConfig{
58+
ExtensionFilters: map[model.ExtensionFilterKey]model.ExtensionFilter{
59+
{Kind: "PolicyFilter", Namespace: "", Name: "example"}: policyFilter,
60+
},
61+
},
62+
&model.GatewayHTTPRouteConfig{
63+
HTTPRoute: &route,
64+
Hostnames: []v1.Hostname{"example.com"},
65+
})
66+
if assert.Len(t, result, 1) {
67+
if assert.Len(t, result[0].Policies, 1) {
68+
assert.Equal(t, policy.Spec.PPL, result[0].Policies[0].GetSourcePpl(),
69+
"should fill source ppl")
70+
}
71+
}
72+
})
73+
}

pomerium/ingress_annotations.go

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,13 @@ import (
66
"strconv"
77
"strings"
88

9-
"github.com/open-policy-agent/opa/ast"
109
"google.golang.org/protobuf/proto"
1110
corev1 "k8s.io/api/core/v1"
1211
"k8s.io/apimachinery/pkg/types"
1312

1413
pomerium "github.com/pomerium/pomerium/pkg/grpc/config"
15-
"github.com/pomerium/pomerium/pkg/policy"
1614

15+
"github.com/pomerium/ingress-controller/internal/policy"
1716
"github.com/pomerium/ingress-controller/model"
1817
"github.com/pomerium/ingress-controller/util"
1918
)
@@ -200,21 +199,12 @@ func unmarshalPolicyAnnotations(p *pomerium.Policy, kvs map[string]string) error
200199
return nil
201200
}
202201

203-
src, err := policy.GenerateRegoFromReader(strings.NewReader(ppl))
202+
var err error
203+
p.SourcePpl, p.Rego, err = policy.Parse(ppl)
204204
if err != nil {
205-
return fmt.Errorf("parsing policy: %w", err)
206-
}
207-
208-
_, err = ast.ParseModule("policy.rego", src)
209-
if err != nil && strings.Contains(err.Error(), "package expected") {
210-
_, err = ast.ParseModule("policy.rego", "package pomerium.policy\n\n"+src)
211-
}
212-
if err != nil {
213-
return fmt.Errorf("invalid custom rego: %w", err)
205+
return err
214206
}
215207

216-
p.SourcePpl = proto.String(ppl)
217-
p.Rego = []string{src}
218208
return nil
219209
}
220210

0 commit comments

Comments
 (0)