agent/connect: support any values in the URL

This commit is contained in:
Mitchell Hashimoto 2018-03-26 20:31:17 -07:00
parent 8934f00d03
commit 9d93c52098
No known key found for this signature in database
GPG Key ID: 744E147AA52F5B0A
2 changed files with 47 additions and 5 deletions

View File

@ -20,7 +20,7 @@ type CertURI interface {
var ( var (
spiffeIDServiceRegexp = regexp.MustCompile( spiffeIDServiceRegexp = regexp.MustCompile(
`^/ns/(\w+)/dc/(\w+)/svc/(\w+)$`) `^/ns/([^/]+)/dc/([^/]+)/svc/([^/]+)$`)
) )
// ParseCertURI parses a the URI value from a TLS certificate. // ParseCertURI parses a the URI value from a TLS certificate.
@ -29,13 +29,40 @@ func ParseCertURI(input *url.URL) (CertURI, error) {
return nil, fmt.Errorf("SPIFFE ID must have 'spiffe' scheme") return nil, fmt.Errorf("SPIFFE ID must have 'spiffe' scheme")
} }
// Path is the raw value of the path without url decoding values.
// RawPath is empty if there were no encoded values so we must
// check both.
path := input.Path
if input.RawPath != "" {
path = input.RawPath
}
// Test for service IDs // Test for service IDs
if v := spiffeIDServiceRegexp.FindStringSubmatch(input.Path); v != nil { if v := spiffeIDServiceRegexp.FindStringSubmatch(path); v != nil {
// Determine the values. We assume they're sane to save cycles,
// but if the raw path is not empty that means that something is
// URL encoded so we go to the slow path.
ns := v[1]
dc := v[2]
service := v[3]
if input.RawPath != "" {
var err error
if ns, err = url.PathUnescape(v[1]); err != nil {
return nil, fmt.Errorf("Invalid namespace: %s", err)
}
if dc, err = url.PathUnescape(v[2]); err != nil {
return nil, fmt.Errorf("Invalid datacenter: %s", err)
}
if service, err = url.PathUnescape(v[3]); err != nil {
return nil, fmt.Errorf("Invalid service: %s", err)
}
}
return &SpiffeIDService{ return &SpiffeIDService{
Host: input.Host, Host: input.Host,
Namespace: v[1], Namespace: ns,
Datacenter: v[2], Datacenter: dc,
Service: v[3], Service: service,
}, nil }, nil
} }

View File

@ -34,6 +34,18 @@ var testCertURICases = []struct {
"", "",
}, },
{
"service with URL-encoded values",
"spiffe://1234.consul/ns/foo%2Fbar/dc/bar%2Fbaz/svc/baz%2Fqux",
&SpiffeIDService{
Host: "1234.consul",
Namespace: "foo/bar",
Datacenter: "bar/baz",
Service: "baz/qux",
},
"",
},
{ {
"signing ID", "signing ID",
"spiffe://1234.consul", "spiffe://1234.consul",
@ -56,6 +68,9 @@ func TestParseCertURI(t *testing.T) {
// Parse the ID and check the error/return value // Parse the ID and check the error/return value
actual, err := ParseCertURI(uri) actual, err := ParseCertURI(uri)
if err != nil {
t.Logf("parse error: %s", err.Error())
}
assert.Equal(tc.ParseError != "", err != nil, "error value") assert.Equal(tc.ParseError != "", err != nil, "error value")
if err != nil { if err != nil {
assert.Contains(err.Error(), tc.ParseError) assert.Contains(err.Error(), tc.ParseError)