blob: 778a1f2a2887c9c179a5387483afec75e67cb0fb [file] [log] [blame]
// Copyright Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package model
import (
"testing"
)
import (
rbacpb "github.com/envoyproxy/go-control-plane/envoy/config/rbac/v3"
"github.com/google/go-cmp/cmp"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/testing/protocmp"
)
import (
"github.com/apache/dubbo-go-pixiu/pkg/util/protomarshal"
)
func TestGenerator(t *testing.T) {
cases := []struct {
name string
g generator
key string
value string
forTCP bool
want interface{}
}{
{
name: "destIPGenerator",
g: destIPGenerator{},
value: "1.2.3.4",
want: yamlPermission(t, `
destinationIp:
addressPrefix: 1.2.3.4
prefixLen: 32`),
},
{
name: "destPortGenerator",
g: destPortGenerator{},
value: "80",
want: yamlPermission(t, `
destinationPort: 80`),
},
{
name: "connSNIGenerator",
g: connSNIGenerator{},
value: "exact.com",
want: yamlPermission(t, `
requestedServerName:
exact: exact.com`),
},
{
name: "envoyFilterGenerator-string",
g: envoyFilterGenerator{},
key: "experimental.a.b.c[d]",
value: "val",
want: yamlPermission(t, `
metadata:
filter: a.b.c
path:
- key: d
value:
stringMatch:
exact: val`),
},
{
name: "envoyFilterGenerator-invalid",
g: envoyFilterGenerator{},
key: "experimental.a.b.c]",
value: "val",
},
{
name: "envoyFilterGenerator-list",
g: envoyFilterGenerator{},
key: "experimental.a.b.c[d]",
value: "[v1, v2]",
want: yamlPermission(t, `
metadata:
filter: a.b.c
path:
- key: d
value:
listMatch:
oneOf:
stringMatch:
exact: v1, v2`),
},
{
name: "srcIPGenerator",
g: srcIPGenerator{},
value: "1.2.3.4",
want: yamlPrincipal(t, `
directRemoteIp:
addressPrefix: 1.2.3.4
prefixLen: 32`),
},
{
name: "remoteIPGenerator",
g: remoteIPGenerator{},
value: "1.2.3.4",
want: yamlPrincipal(t, `
remoteIp:
addressPrefix: 1.2.3.4
prefixLen: 32`),
},
{
name: "srcNamespaceGenerator-http",
g: srcNamespaceGenerator{},
value: "foo",
want: yamlPrincipal(t, `
authenticated:
principalName:
safeRegex:
googleRe2: {}
regex: .*/ns/foo/.*`),
},
{
name: "srcNamespaceGenerator-tcp",
g: srcNamespaceGenerator{},
value: "foo",
forTCP: true,
want: yamlPrincipal(t, `
authenticated:
principalName:
safeRegex:
googleRe2: {}
regex: .*/ns/foo/.*`),
},
{
name: "srcPrincipalGenerator-http",
g: srcPrincipalGenerator{},
key: "source.principal",
value: "foo",
want: yamlPrincipal(t, `
authenticated:
principalName:
exact: spiffe://foo`),
},
{
name: "srcPrincipalGenerator-tcp",
g: srcPrincipalGenerator{},
key: "source.principal",
value: "foo",
forTCP: true,
want: yamlPrincipal(t, `
authenticated:
principalName:
exact: spiffe://foo`),
},
{
name: "requestPrincipalGenerator",
g: requestPrincipalGenerator{},
key: "request.auth.principal",
value: "foo",
want: yamlPrincipal(t, `
metadata:
filter: istio_authn
path:
- key: request.auth.principal
value:
stringMatch:
exact: foo`),
},
{
name: "requestAudiencesGenerator",
g: requestAudiencesGenerator{},
key: "request.auth.audiences",
value: "foo",
want: yamlPrincipal(t, `
metadata:
filter: istio_authn
path:
- key: request.auth.audiences
value:
stringMatch:
exact: foo`),
},
{
name: "requestPresenterGenerator",
g: requestPresenterGenerator{},
key: "request.auth.presenter",
value: "foo",
want: yamlPrincipal(t, `
metadata:
filter: istio_authn
path:
- key: request.auth.presenter
value:
stringMatch:
exact: foo`),
},
{
name: "requestHeaderGenerator",
g: requestHeaderGenerator{},
key: "request.headers[x-foo]",
value: "foo",
want: yamlPrincipal(t, `
header:
exactMatch: foo
name: x-foo`),
},
{
name: "requestClaimGenerator",
g: requestClaimGenerator{},
key: "request.auth.claims[bar]",
value: "foo",
want: yamlPrincipal(t, `
metadata:
filter: istio_authn
path:
- key: request.auth.claims
- key: bar
value:
listMatch:
oneOf:
stringMatch:
exact: foo`),
},
{
name: "requestNestedClaimsGenerator",
g: requestClaimGenerator{},
key: "request.auth.claims[bar][baz]",
value: "foo",
want: yamlPrincipal(t, `
metadata:
filter: istio_authn
path:
- key: request.auth.claims
- key: bar
- key: baz
value:
listMatch:
oneOf:
stringMatch:
exact: foo`),
},
{
name: "hostGenerator",
g: hostGenerator{},
value: "foo",
want: yamlPermission(t, `
header:
stringMatch:
exact: foo
ignoreCase: true
name: :authority`),
},
{
name: "pathGenerator",
g: pathGenerator{},
value: "/abc",
want: yamlPermission(t, `
urlPath:
path:
exact: /abc`),
},
{
name: "methodGenerator",
g: methodGenerator{},
value: "GET",
want: yamlPermission(t, `
header:
exactMatch: GET
name: :method`),
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
var got interface{}
var err error
// nolint: gocritic
if _, ok := tc.want.(*rbacpb.Permission); ok {
got, err = tc.g.permission(tc.key, tc.value, tc.forTCP)
if err != nil {
t.Errorf("both permission and principal returned error")
}
} else if _, ok := tc.want.(*rbacpb.Principal); ok {
got, err = tc.g.principal(tc.key, tc.value, tc.forTCP)
if err != nil {
t.Errorf("both permission and principal returned error")
}
} else {
_, err1 := tc.g.principal(tc.key, tc.value, tc.forTCP)
_, err2 := tc.g.permission(tc.key, tc.value, tc.forTCP)
if err1 == nil || err2 == nil {
t.Fatalf("wanted error")
}
return
}
if diff := cmp.Diff(got, tc.want, protocmp.Transform()); diff != "" {
var gotYaml string
gotProto, ok := got.(proto.Message)
if !ok {
t.Fatal("failed to extract proto")
}
if gotYaml, err = protomarshal.ToYAML(gotProto); err != nil {
t.Fatalf("%s: failed to parse yaml: %s", tc.name, err)
}
t.Errorf("got:\n %v\n but want:\n %v", gotYaml, tc.want)
}
})
}
}
func yamlPermission(t *testing.T, yaml string) *rbacpb.Permission {
t.Helper()
p := &rbacpb.Permission{}
if err := protomarshal.ApplyYAML(yaml, p); err != nil {
t.Fatalf("failed to parse yaml: %s", err)
}
return p
}
func yamlPrincipal(t *testing.T, yaml string) *rbacpb.Principal {
t.Helper()
p := &rbacpb.Principal{}
if err := protomarshal.ApplyYAML(yaml, p); err != nil {
t.Fatalf("failed to parse yaml: %s", err)
}
return p
}