blob: d8e38a12b3f800049f0469fca9f1e556fdd99eed [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 trustdomain
import (
"reflect"
"testing"
)
func TestReplaceTrustDomainAliases(t *testing.T) {
testCases := []struct {
name string
trustDomainBundle Bundle
principals []string
expect []string
}{
{
name: "No trust domain aliases (no change in trust domain)",
trustDomainBundle: NewBundle("cluster.local", nil),
principals: []string{"cluster.local/ns/foo/sa/bar"},
expect: []string{"cluster.local/ns/foo/sa/bar"},
},
{
name: "Principal with *",
trustDomainBundle: NewBundle("cluster.local", nil),
principals: []string{"*"},
expect: []string{"*"},
},
{
name: "Principal with * prefix",
trustDomainBundle: NewBundle("cluster.local", nil),
principals: []string{"*/ns/foo/sa/bar"},
expect: []string{"*/ns/foo/sa/bar"},
},
{
name: "One trust domain alias, one principal",
trustDomainBundle: NewBundle("td2", []string{"td1"}),
principals: []string{"td1/ns/foo/sa/bar"},
expect: []string{"td2/ns/foo/sa/bar", "td1/ns/foo/sa/bar"},
},
{
name: "One trust domain alias, two principals",
trustDomainBundle: NewBundle("td1", []string{"cluster.local"}),
principals: []string{"cluster.local/ns/foo/sa/bar", "cluster.local/ns/yyy/sa/zzz"},
expect: []string{"td1/ns/foo/sa/bar", "cluster.local/ns/foo/sa/bar", "td1/ns/yyy/sa/zzz", "cluster.local/ns/yyy/sa/zzz"},
},
{
name: "One trust domain alias, principals with * as-is",
trustDomainBundle: NewBundle("td1", []string{"cluster.local"}),
principals: []string{"*/ns/foo/sa/bar", "*sa/zzz", "*"},
expect: []string{"*/ns/foo/sa/bar", "*sa/zzz", "*"},
},
{
name: "Two trust domain aliases, two principals",
trustDomainBundle: NewBundle("td2", []string{"td1", "cluster.local"}),
principals: []string{"cluster.local/ns/foo/sa/bar", "td1/ns/yyy/sa/zzz"},
expect: []string{
"td2/ns/foo/sa/bar", "td1/ns/foo/sa/bar", "cluster.local/ns/foo/sa/bar",
"td2/ns/yyy/sa/zzz", "td1/ns/yyy/sa/zzz", "cluster.local/ns/yyy/sa/zzz",
},
},
{
name: "Two trust domain aliases with * prefix in trust domain",
trustDomainBundle: NewBundle("td2", []string{"foo-td1", "cluster.local"}),
principals: []string{"*-td1/ns/foo/sa/bar"},
expect: []string{"td2/ns/foo/sa/bar", "*-td1/ns/foo/sa/bar", "cluster.local/ns/foo/sa/bar"},
},
{
name: "Principals not match any trust domains",
trustDomainBundle: NewBundle("td1", []string{"td2"}),
principals: []string{"some-td/ns/foo/sa/bar"},
expect: []string{"some-td/ns/foo/sa/bar"},
},
{
name: "Principals match one alias",
trustDomainBundle: NewBundle("td1", []string{"td2", "some-td"}),
principals: []string{"some-td/ns/foo/sa/bar"},
expect: []string{"td1/ns/foo/sa/bar", "td2/ns/foo/sa/bar", "some-td/ns/foo/sa/bar"},
},
{
name: "One principal match one alias",
trustDomainBundle: NewBundle("new-td", []string{"td2", "td3"}),
principals: []string{"td1/ns/some-ns/sa/some-sa", "td2/ns/foo/sa/bar"},
expect: []string{
"td1/ns/some-ns/sa/some-sa", "new-td/ns/foo/sa/bar",
"td2/ns/foo/sa/bar", "td3/ns/foo/sa/bar",
},
},
{
name: "Trust domain is empty string",
trustDomainBundle: NewBundle("new-td", []string{"td2", "td3"}),
principals: []string{"/ns/some-ns/sa/some-sa"},
expect: []string{"/ns/some-ns/sa/some-sa"},
},
{
name: "No duplicated principals for prefix",
trustDomainBundle: NewBundle("new-td", []string{"old-td"}),
principals: []string{"*-td/ns/some-ns/sa/some-sa"},
// Rather than output *-td/ns/some-ns/sa/some-sa once for each trust domain.
expect: []string{"*-td/ns/some-ns/sa/some-sa"},
},
}
for _, tc := range testCases {
got := tc.trustDomainBundle.ReplaceTrustDomainAliases(tc.principals)
if !reflect.DeepEqual(got, tc.expect) {
t.Errorf("%s failed. Expect: %s. Got: %s", tc.name, tc.expect, got)
}
}
}
func TestReplaceTrustDomainInPrincipal(t *testing.T) {
cases := []struct {
name string
trustDomainIn string
principal string
out string
expectedError string
}{
{
name: "Principal in wrong format with SPIFFE:// prefix",
principal: "spiffe://cluster.local/ns/foo/sa/bar",
out: "",
expectedError: "wrong SPIFFE format: spiffe://cluster.local/ns/foo/sa/bar",
},
{
name: "Principal in wrong format with less components",
principal: "sa/test-sa/ns/default",
out: "",
expectedError: "wrong SPIFFE format: sa/test-sa/ns/default",
},
{
name: "Replace td with domain name in principal",
trustDomainIn: "td",
principal: "cluster.local/ns/foo/sa/bar",
out: "td/ns/foo/sa/bar",
expectedError: "",
},
{
name: "Replace td without domain name in principal",
trustDomainIn: "abc",
principal: "xyz/ns/foo/sa/bar",
out: "abc/ns/foo/sa/bar",
expectedError: "",
},
}
for _, c := range cases {
got, err := replaceTrustDomainInPrincipal(c.trustDomainIn, c.principal)
if err != nil {
if c.expectedError == "" {
t.Errorf("%s: replace trust domain in principal error: %v", c.name, err)
}
if got != "" {
t.Errorf("%s: Expected empty SPIFFE ID but obtained a non-empty one: %s.", c.name, got)
}
if err.Error() != c.expectedError {
t.Errorf("%s: Expected error: %s but got error: %s.", c.name, c.expectedError, err.Error())
}
continue
}
if got != c.out {
t.Errorf("%s failed. Expect %s, but got %s", c.name, c.out, got)
}
}
}
func TestGetTrustDomainFromSpiffeIdentity(t *testing.T) {
cases := []struct {
principal string
out string
}{
{principal: "spiffe://cluster.local/ns/foo/sa/bar", out: ""},
{principal: "sa/test-sa/ns/default", out: ""},
{principal: "cluster.local/ns/foo/sa/bar", out: "cluster.local"},
{principal: "xyz/ns/foo/sa/bar", out: "xyz"},
}
for _, c := range cases {
got, _ := getTrustDomainFromSpiffeIdentity(c.principal)
if got != c.out {
t.Errorf("expect %s, but got %s", c.out, got)
}
}
}
func TestIsTrustDomainBeingEnforced(t *testing.T) {
cases := []struct {
principal string
want bool
}{
{principal: "cluster.local/ns/foo/sa/bar", want: true},
{principal: "*/ns/foo/sa/bar", want: false},
{principal: "*-td/ns/foo/sa/bar", want: true},
{principal: "*/sa/bar", want: false},
{principal: "*", want: false},
{principal: "/ns/foo/sa/bar", want: true},
}
for _, c := range cases {
got := isTrustDomainBeingEnforced(c.principal)
if got != c.want {
t.Errorf("expect %v, but got %v", c.want, got)
}
}
}