Switch impersonatorconfig to new endpointaddr package.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
This commit is contained in:
Matt Moyer 2021-05-25 17:44:25 -05:00
parent c970dd1fb0
commit 450ce6a4aa
No known key found for this signature in database
GPG Key ID: EAE88AD172C5AE2D
2 changed files with 11 additions and 96 deletions

View File

@ -12,7 +12,6 @@ import (
"fmt" "fmt"
"net" "net"
"reflect" "reflect"
"strconv"
"strings" "strings"
"time" "time"
@ -41,6 +40,7 @@ import (
"go.pinniped.dev/internal/controller/issuerconfig" "go.pinniped.dev/internal/controller/issuerconfig"
"go.pinniped.dev/internal/controllerlib" "go.pinniped.dev/internal/controllerlib"
"go.pinniped.dev/internal/dynamiccert" "go.pinniped.dev/internal/dynamiccert"
"go.pinniped.dev/internal/endpointaddr"
"go.pinniped.dev/internal/plog" "go.pinniped.dev/internal/plog"
) )
@ -761,13 +761,13 @@ func (c *impersonatorConfigController) findDesiredTLSCertificateName(config *v1a
} }
func (c *impersonatorConfigController) findTLSCertificateNameFromEndpointConfig(config *v1alpha1.ImpersonationProxySpec) *certNameInfo { func (c *impersonatorConfigController) findTLSCertificateNameFromEndpointConfig(config *v1alpha1.ImpersonationProxySpec) *certNameInfo {
endpointMaybeWithPort := config.ExternalEndpoint addr, _ := endpointaddr.Parse(config.ExternalEndpoint, 443)
endpointWithoutPort := strings.Split(endpointMaybeWithPort, ":")[0] endpoint := strings.TrimSuffix(addr.Endpoint(), ":443")
parsedAsIP := net.ParseIP(endpointWithoutPort)
if parsedAsIP != nil { if ip := net.ParseIP(addr.Host); ip != nil {
return &certNameInfo{ready: true, selectedIP: parsedAsIP, clientEndpoint: endpointMaybeWithPort} return &certNameInfo{ready: true, selectedIP: ip, clientEndpoint: endpoint}
} }
return &certNameInfo{ready: true, selectedHostname: endpointWithoutPort, clientEndpoint: endpointMaybeWithPort} return &certNameInfo{ready: true, selectedHostname: addr.Host, clientEndpoint: endpoint}
} }
func (c *impersonatorConfigController) findTLSCertificateNameFromLoadBalancer() (*certNameInfo, error) { func (c *impersonatorConfigController) findTLSCertificateNameFromLoadBalancer() (*certNameInfo, error) {
@ -1017,46 +1017,11 @@ func validateCredentialIssuerSpec(spec *v1alpha1.ImpersonationProxySpec) error {
return fmt.Errorf("externalEndpoint must be set when service.type is None") return fmt.Errorf("externalEndpoint must be set when service.type is None")
} }
if err := validateExternalEndpoint(spec.ExternalEndpoint); err != nil { if spec.ExternalEndpoint != "" {
if _, err := endpointaddr.Parse(spec.ExternalEndpoint, 443); err != nil {
return fmt.Errorf("invalid ExternalEndpoint %q: %w", spec.ExternalEndpoint, err) return fmt.Errorf("invalid ExternalEndpoint %q: %w", spec.ExternalEndpoint, err)
} }
}
return nil return nil
} }
func validateExternalEndpoint(endpoint string) error {
// Empty string is valid (no external endpoint, default to service name)
if endpoint == "" {
return nil
}
// Try parsing it both with and without an implicit port 443 at the end.
host, port, err := net.SplitHostPort(endpoint)
// If we got an error parsing the raw input, try adding an implicit port 443.
if err != nil {
host, port, err = net.SplitHostPort(net.JoinHostPort(endpoint, "443"))
}
// If there's still an error, fail now.
if err != nil {
return err
}
portInt, _ := strconv.Atoi(port)
if len(validation.IsValidPortNum(portInt)) > 0 {
return fmt.Errorf("invalid port %q", port)
}
// Check if the host part is a valid IP address.
if len(validation.IsValidIP(host)) == 0 {
return nil
}
// Check if the host part is a valid hostname according to RFC 1123.
if len(validation.IsDNS1123Subdomain(host)) == 0 {
return nil
}
return fmt.Errorf("host %q is not a valid hostname or IP address", host)
}

View File

@ -3535,53 +3535,3 @@ func (q *testQueue) AddRateLimited(key controllerlib.Key) {
q.key = key q.key = key
} }
func TestValidateExternalEndpoint(t *testing.T) {
t.Parallel()
for _, tt := range []struct {
input string
expectErr string
}{
{input: ""},
{input: "127.0.0.1"},
{input: "127.0.0.1:8443"},
{input: "[127.0.0.1]:8443"},
{input: "2001:db8::ffff"},
{input: "[2001:db8::ffff]:8443"},
{input: "host.example.com"},
{input: "host-dev.example.com"},
{input: "host.example.com:8443"},
{input: "[host.example.com]:8443"},
{
input: "https://host.example.com",
expectErr: `invalid port "//host.example.com"`,
},
{
input: "host.example.com/some/path",
expectErr: `host "host.example.com/some/path" is not a valid hostname or IP address`,
},
{
input: "[host.example.com",
expectErr: "address [host.example.com:443: missing ']' in address",
},
{
input: "___.example.com:1234",
expectErr: `host "___.example.com" is not a valid hostname or IP address`,
},
{
input: "HOST.EXAMPLE.COM",
expectErr: `host "HOST.EXAMPLE.COM" is not a valid hostname or IP address`,
},
} {
tt := tt
t.Run(fmt.Sprintf("parse %q", tt.input), func(t *testing.T) {
got := validateExternalEndpoint(tt.input)
if tt.expectErr == "" {
require.NoError(t, got)
} else {
require.EqualError(t, got, tt.expectErr)
}
})
}
}