mirror of
https://github.com/pomerium/pomerium.git
synced 2025-05-06 13:56:04 +02:00
* initial core-zero import implementation * Update /config/import openapi description and use PUT instead of POST * update import ui tests * Add 413 as a possible response for /config/import * Options/Settings type conversion tests and related bugfixes * Fixes for proto type conversion and tests * Update core-zero import client * Update core-zero import client * Update import api and environment detection * update go.mod * remove old testdata * Remove usage of deleted setting after merge * remove extra newline from --version output
394 lines
11 KiB
Go
394 lines
11 KiB
Go
package importutil_test
|
|
|
|
import (
|
|
"crypto/x509"
|
|
"crypto/x509/pkix"
|
|
"fmt"
|
|
"slices"
|
|
"testing"
|
|
"time"
|
|
|
|
configpb "github.com/pomerium/pomerium/pkg/grpc/config"
|
|
"github.com/pomerium/pomerium/pkg/zero/importutil"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestGenerateCertName(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
input x509.Certificate
|
|
expected string
|
|
}{
|
|
{
|
|
name: "cert with common name",
|
|
input: x509.Certificate{
|
|
IsCA: true,
|
|
Subject: pkix.Name{CommonName: "sample"},
|
|
},
|
|
expected: "sample",
|
|
},
|
|
{
|
|
name: "cert with common name and other subject fields",
|
|
input: x509.Certificate{
|
|
IsCA: true,
|
|
Subject: pkix.Name{
|
|
CommonName: "sample",
|
|
Organization: []string{"foo"},
|
|
OrganizationalUnit: []string{"bar"},
|
|
},
|
|
},
|
|
expected: "sample",
|
|
},
|
|
{
|
|
name: "common name with spaces",
|
|
input: x509.Certificate{
|
|
IsCA: true,
|
|
Subject: pkix.Name{CommonName: "sample name"},
|
|
},
|
|
expected: "sample-name",
|
|
},
|
|
{
|
|
name: "common name with special characters",
|
|
input: x509.Certificate{
|
|
IsCA: true,
|
|
Subject: pkix.Name{CommonName: "sample common-name"},
|
|
},
|
|
expected: "sample_common-name",
|
|
},
|
|
{
|
|
name: "cert with other subject fields but no common name",
|
|
input: x509.Certificate{
|
|
IsCA: true,
|
|
Subject: pkix.Name{
|
|
Organization: []string{"foo"},
|
|
OrganizationalUnit: []string{"bar"},
|
|
},
|
|
},
|
|
expected: "OU=bar,O=foo",
|
|
},
|
|
{
|
|
name: "leaf cert with common name",
|
|
input: x509.Certificate{
|
|
IsCA: false,
|
|
Subject: pkix.Name{CommonName: "sample"},
|
|
},
|
|
expected: "sample",
|
|
},
|
|
{
|
|
name: "leaf cert with dns name",
|
|
input: x509.Certificate{
|
|
IsCA: false,
|
|
DNSNames: []string{"example.com"},
|
|
},
|
|
expected: "example.com",
|
|
},
|
|
{
|
|
name: "leaf cert with dns names",
|
|
input: x509.Certificate{
|
|
IsCA: false,
|
|
DNSNames: []string{"example.com", "*.example.com"},
|
|
},
|
|
expected: "*.example.com",
|
|
},
|
|
{
|
|
name: "leaf cert with neither common name nor dns names",
|
|
input: x509.Certificate{
|
|
IsCA: false,
|
|
},
|
|
expected: "leaf",
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
nbf := time.Now()
|
|
tc.input.NotBefore = nbf
|
|
tc.expected += fmt.Sprintf("@%d", nbf.Unix())
|
|
out := importutil.GenerateCertName(&tc.input)
|
|
assert.Equal(t, tc.expected, *out)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGenerateRouteNames(t *testing.T) {
|
|
const testExample = "https://test.example.com"
|
|
cases := []struct {
|
|
name string
|
|
input []*configpb.Route
|
|
expected []string
|
|
}{
|
|
{
|
|
name: "single domain name",
|
|
input: []*configpb.Route{
|
|
{From: "https://foo.example.com"},
|
|
{From: "https://bar.example.com"},
|
|
{From: "https://baz.example.com"},
|
|
},
|
|
expected: []string{"foo", "bar", "baz"},
|
|
},
|
|
{
|
|
name: "multiple domain names, unique subdomains",
|
|
input: []*configpb.Route{
|
|
{From: "https://a.domain1.example.com"},
|
|
{From: "https://b.domain1.example.com"},
|
|
{From: "https://c.domain1.example.com"},
|
|
{From: "https://d.domain2.example.com"},
|
|
{From: "https://e.domain2.example.com"},
|
|
{From: "https://f.domain2.example.com"},
|
|
},
|
|
expected: []string{"a", "b", "c", "d", "e", "f"},
|
|
},
|
|
{
|
|
name: "multiple domain names, conflicting subdomains",
|
|
input: []*configpb.Route{
|
|
{From: "https://a.domain1.example.com"},
|
|
{From: "https://b.domain1.example.com"},
|
|
{From: "https://c.domain1.example.com"},
|
|
{From: "https://a.domain2.example.com"},
|
|
{From: "https://b.domain2.example.com"},
|
|
{From: "https://c.domain2.example.com"},
|
|
},
|
|
expected: []string{
|
|
"a-domain1",
|
|
"b-domain1",
|
|
"c-domain1",
|
|
"a-domain2",
|
|
"b-domain2",
|
|
"c-domain2",
|
|
},
|
|
},
|
|
{
|
|
name: "multiple nested domain names, conflicting subdomains",
|
|
input: []*configpb.Route{
|
|
{From: "https://a.domain1.domain2.domain3.example.com"},
|
|
{From: "https://b.domain1.domain2.domain3.example.com"},
|
|
{From: "https://c.domain1.domain2.domain3.example.com"},
|
|
{From: "https://a.domain1.domain2.domain4.example.com"},
|
|
{From: "https://b.domain1.domain2.domain4.example.com"},
|
|
{From: "https://c.domain1.domain2.domain4.example.com"},
|
|
|
|
{From: "https://a.domain1.domain2.domain5.example.com"},
|
|
{From: "https://b.domain2.domain2.domain5.example.com"},
|
|
{From: "https://c.domain3.domain2.domain5.example.com"},
|
|
{From: "https://a.domain1.domain2.domain6.example.com"},
|
|
{From: "https://b.domain2.domain2.domain6.example.com"},
|
|
{From: "https://c.domain3.domain2.domain6.example.com"},
|
|
},
|
|
expected: []string{
|
|
"a-domain3",
|
|
"b-domain3",
|
|
"c-domain3",
|
|
"a-domain4",
|
|
"b-domain4",
|
|
"c-domain4",
|
|
|
|
"a-domain5",
|
|
"b-domain5",
|
|
"c-domain5",
|
|
"a-domain6",
|
|
"b-domain6",
|
|
"c-domain6",
|
|
},
|
|
},
|
|
{
|
|
name: "conflicting subdomain names nested at different levels",
|
|
input: []*configpb.Route{
|
|
{From: "https://a.domain1.domain2.example.com"},
|
|
{From: "https://a.domain1.example.com"},
|
|
{From: "https://a.example.com"},
|
|
{From: "https://a.domain3.domain2.example.com"},
|
|
{From: "https://a.domain3.example.com"},
|
|
},
|
|
expected: []string{
|
|
"a-domain2-domain1",
|
|
"a-domain1",
|
|
"a",
|
|
"a-domain2-domain3",
|
|
"a-domain3",
|
|
},
|
|
},
|
|
{
|
|
name: "conflicting subdomain names nested at different levels, unique paths",
|
|
input: []*configpb.Route{
|
|
{From: "https://a.domain1.domain2.example.com"},
|
|
{From: "https://a.domain1.example.com"},
|
|
{From: "https://a.example.com"},
|
|
},
|
|
expected: []string{
|
|
"a-domain2-domain1",
|
|
"a-domain1",
|
|
"a",
|
|
},
|
|
},
|
|
{
|
|
name: "same domain, separate prefix options",
|
|
input: []*configpb.Route{
|
|
{From: testExample, Prefix: "/a"},
|
|
{From: testExample, Prefix: "/b"},
|
|
{From: testExample, Prefix: "/c"},
|
|
},
|
|
expected: []string{"test-a", "test-b", "test-c"},
|
|
},
|
|
{
|
|
name: "same domain, mixed prefix/path options",
|
|
input: []*configpb.Route{
|
|
{From: testExample, Prefix: "/a"},
|
|
{From: testExample, Path: "/b"},
|
|
{From: testExample, Prefix: "/c"},
|
|
{From: testExample, Path: "/d"},
|
|
},
|
|
expected: []string{"test-a", "test-b", "test-c", "test-d"},
|
|
},
|
|
{
|
|
name: "same domain, name-conflicting prefix/path options (1 prefix/1 path)",
|
|
input: []*configpb.Route{
|
|
{From: testExample, Prefix: "/a/"},
|
|
{From: testExample, Path: "/a"},
|
|
},
|
|
expected: []string{"test-a-prefix", "test-a"},
|
|
},
|
|
{
|
|
name: "same domain, name-conflicting prefix/path options (more prefixes than paths)",
|
|
input: []*configpb.Route{
|
|
{From: testExample, Prefix: "/a/"},
|
|
{From: testExample, Prefix: "/b/"},
|
|
{From: testExample, Prefix: "/c/"},
|
|
{From: testExample, Path: "/a"},
|
|
},
|
|
expected: []string{"test-a", "test-b", "test-c", "test-a-path"},
|
|
},
|
|
{
|
|
name: "same domain, name-conflicting prefix/path options (more paths than prefixes)",
|
|
input: []*configpb.Route{
|
|
{From: testExample, Path: "/a"},
|
|
{From: testExample, Path: "/b"},
|
|
{From: testExample, Path: "/c"},
|
|
{From: testExample, Prefix: "/a/"},
|
|
},
|
|
expected: []string{"test-a", "test-b", "test-c", "test-a-prefix"},
|
|
},
|
|
{
|
|
name: "same domain, name-conflicting path options, duplicate names",
|
|
input: []*configpb.Route{
|
|
{From: testExample, Path: "/a"},
|
|
{From: testExample, Path: "/a/"},
|
|
},
|
|
expected: []string{"test-a", "test-a (2)"},
|
|
},
|
|
{
|
|
name: "same domain, name-conflicting prefix options, duplicate names",
|
|
input: []*configpb.Route{
|
|
{From: testExample, Prefix: "/a"},
|
|
{From: testExample, Prefix: "/a/"},
|
|
},
|
|
expected: []string{"test-a", "test-a (2)"},
|
|
},
|
|
{
|
|
name: "missing domain name",
|
|
input: []*configpb.Route{{From: "https://:1234"}},
|
|
expected: []string{"route-0"},
|
|
},
|
|
{
|
|
name: "invalid URL",
|
|
input: []*configpb.Route{{From: "https://\x7f"}},
|
|
expected: []string{"route-0"},
|
|
},
|
|
{
|
|
name: "regex paths",
|
|
input: []*configpb.Route{
|
|
{From: testExample, Regex: `/a/(.*)/b`},
|
|
{From: testExample, Regex: `/a/(foo|bar)/b`},
|
|
{From: testExample, Regex: `/(authorize.*|login|logout)`},
|
|
{From: testExample, Regex: `/foo.+=-())(*+=,;:@~!'''-+_/.*`},
|
|
{From: testExample, Regex: `/*`},
|
|
{From: testExample, Regex: `/other/(.*)`},
|
|
{From: testExample, Regex: `/other/.*`},
|
|
{From: testExample, Regex: `/other/([^/]+)`},
|
|
{From: testExample, Regex: `/other/([^/]*)`},
|
|
{From: testExample, Regex: `/other/([^\/]+)`},
|
|
{From: testExample, Regex: `/other/([^\/]*)`},
|
|
{From: testExample, Regex: `/other/[^/]+`},
|
|
{From: testExample, Regex: `/other/[^/]*`},
|
|
{From: testExample, Regex: `/other/[^\/]+`},
|
|
{From: testExample, Regex: `/other/[^\/]*`},
|
|
{From: testExample, Regex: `/foo/bar/baz/.*`},
|
|
{From: testExample, Regex: `/.*`},
|
|
{From: testExample, Regex: `/.*`},
|
|
{From: testExample, Regex: `/(.*)`},
|
|
{From: testExample, Regex: `/.+`},
|
|
{From: testExample, Regex: `/(.+)`},
|
|
{From: testExample, Regex: `/([^/]+)`},
|
|
{From: testExample, Regex: `/([^/]*)`},
|
|
{From: testExample, Regex: `/([^\/]+)`},
|
|
{From: testExample, Regex: `/([^\/]*)`},
|
|
{From: testExample, Regex: `/[^/]+`},
|
|
{From: testExample, Regex: `/[^/]*`},
|
|
{From: testExample, Regex: `/[^\/]+`},
|
|
{From: testExample, Regex: `/[^\/]*`},
|
|
{From: testExample, Regex: `.+`},
|
|
{From: testExample, Regex: `(.+)`},
|
|
{From: testExample, Regex: `([^/]+)`},
|
|
{From: testExample, Regex: `([^/]*)`},
|
|
{From: testExample, Regex: `([^\/]+)`},
|
|
{From: testExample, Regex: `([^\/]*)`},
|
|
{From: testExample, Regex: `[^/]+`},
|
|
{From: testExample, Regex: `[^/]*`},
|
|
{From: testExample, Regex: `[^\/]+`},
|
|
{From: testExample, Regex: `[^\/]*`},
|
|
{From: testExample, Regex: `\w+`},
|
|
{From: testExample, Regex: `\w*`},
|
|
{From: testExample, Regex: `/\w+`},
|
|
{From: testExample, Regex: `/\w*`},
|
|
{From: testExample, Regex: `/(\w+)`},
|
|
{From: testExample, Regex: `/(\w*)`},
|
|
{From: testExample, Regex: `foo/.*`},
|
|
{From: testExample, Regex: `/foo/.*`},
|
|
{From: testExample, Regex: `/foo/\w+`},
|
|
{From: testExample, Regex: `/foo/\w*`},
|
|
},
|
|
expected: slices.Collect(func(yield func(string) bool) {
|
|
yield("test-re-1")
|
|
yield("test-re-2")
|
|
yield("test-re-3")
|
|
yield("test-re-4")
|
|
yield("test-re-5")
|
|
yield("test-re-other-prefix")
|
|
for i := 2; i <= 10; i++ {
|
|
yield(fmt.Sprintf("test-re-other-prefix (%d)", i))
|
|
}
|
|
yield("test-re-foo-bar-baz-prefix")
|
|
yield("test-re-any")
|
|
for i := 2; i <= 29; i++ {
|
|
yield(fmt.Sprintf("test-re-any (%d)", i))
|
|
}
|
|
yield("test-re-foo-prefix")
|
|
yield("test-re-foo-prefix (2)")
|
|
yield("test-re-foo-prefix (3)")
|
|
yield("test-re-foo-prefix (4)")
|
|
}),
|
|
},
|
|
{
|
|
name: "duplicate routes",
|
|
input: []*configpb.Route{
|
|
{From: "https://route1.localhost.pomerium.io:8443"},
|
|
{From: "https://route1.localhost.pomerium.io:8443"},
|
|
{From: "https://route2.localhost.pomerium.io:8443"},
|
|
{From: "https://route3.localhost.pomerium.io:8443"},
|
|
{From: "https://route4.localhost.pomerium.io:8443"},
|
|
},
|
|
expected: []string{
|
|
"route1",
|
|
"route1 (2)",
|
|
"route2",
|
|
"route3",
|
|
"route4",
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
assert.Equal(t, tc.expected, importutil.GenerateRouteNames(tc.input))
|
|
})
|
|
}
|
|
}
|