Merge pull request #87179 from Jefftree/netproxy-uds
UDS + GRPC Support for Network Proxy Kubernetes-commit: 6461e6f4fb688d3aab6934bd516e1c35dac72b39
This commit is contained in:
commit
4e3aa0457e
|
|
@ -618,6 +618,10 @@
|
||||||
"ImportPath": "k8s.io/utils",
|
"ImportPath": "k8s.io/utils",
|
||||||
"Rev": "5f6fbceb4c31"
|
"Rev": "5f6fbceb4c31"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "sigs.k8s.io/apiserver-network-proxy/konnectivity-client",
|
||||||
|
"Rev": "v0.0.5"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "sigs.k8s.io/structured-merge-diff/v3",
|
"ImportPath": "sigs.k8s.io/structured-merge-diff/v3",
|
||||||
"Rev": "5e70324e7c1c"
|
"Rev": "5e70324e7c1c"
|
||||||
|
|
|
||||||
1
go.mod
1
go.mod
|
|
@ -51,6 +51,7 @@ require (
|
||||||
k8s.io/klog v1.0.0
|
k8s.io/klog v1.0.0
|
||||||
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c
|
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c
|
||||||
k8s.io/utils v0.0.0-20200117235808-5f6fbceb4c31
|
k8s.io/utils v0.0.0-20200117235808-5f6fbceb4c31
|
||||||
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.5
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c
|
||||||
sigs.k8s.io/yaml v1.2.0
|
sigs.k8s.io/yaml v1.2.0
|
||||||
)
|
)
|
||||||
|
|
|
||||||
2
go.sum
2
go.sum
|
|
@ -350,6 +350,8 @@ k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c h1:/KUFqjjqAcY4Us6luF5RDN
|
||||||
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
|
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
|
||||||
k8s.io/utils v0.0.0-20200117235808-5f6fbceb4c31 h1:KCcLuc/HD1RogJgEbZi9ObRuLv1bgiRCfAbidLKrUpg=
|
k8s.io/utils v0.0.0-20200117235808-5f6fbceb4c31 h1:KCcLuc/HD1RogJgEbZi9ObRuLv1bgiRCfAbidLKrUpg=
|
||||||
k8s.io/utils v0.0.0-20200117235808-5f6fbceb4c31/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
k8s.io/utils v0.0.0-20200117235808-5f6fbceb4c31/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||||
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.5 h1:bwop2S7kJYCtltbitSoLqQb8HdTxbcRAKqAGzcB4Lk8=
|
||||||
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.5/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
|
|
|
||||||
|
|
@ -71,29 +71,78 @@ type EgressSelection struct {
|
||||||
|
|
||||||
// Connection provides the configuration for a single egress selection client.
|
// Connection provides the configuration for a single egress selection client.
|
||||||
type Connection struct {
|
type Connection struct {
|
||||||
// Type is the type of connection used to connect from client to konnectivity server.
|
// Protocol is the protocol used to connect from client to the konnectivity server.
|
||||||
// Currently supported values are "http-connect" and "direct".
|
ProxyProtocol ProtocolType
|
||||||
Type string
|
|
||||||
|
|
||||||
// httpConnect is the config needed to use http-connect to the konnectivity server.
|
// Transport defines the transport configurations we use to dial to the konnectivity server.
|
||||||
|
// This is required if ProxyProtocol is HTTPConnect or GRPC.
|
||||||
// +optional
|
// +optional
|
||||||
HTTPConnect *HTTPConnectConfig
|
Transport *Transport
|
||||||
}
|
}
|
||||||
|
|
||||||
type HTTPConnectConfig struct {
|
// ProtocolType is a set of valid values for Connection.ProtocolType
|
||||||
|
type ProtocolType string
|
||||||
|
|
||||||
|
// Valid types for ProtocolType for konnectivity server
|
||||||
|
const (
|
||||||
|
// Use HTTPConnect to connect to konnectivity server
|
||||||
|
ProtocolHTTPConnect ProtocolType = "HTTPConnect"
|
||||||
|
// Use grpc to connect to konnectivity server
|
||||||
|
ProtocolGRPC ProtocolType = "GRPC"
|
||||||
|
// Connect directly (skip konnectivity server)
|
||||||
|
ProtocolDirect ProtocolType = "Direct"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Transport defines the transport configurations we use to dial to the konnectivity server
|
||||||
|
type Transport struct {
|
||||||
|
// TCP is the TCP configuration for communicating with the konnectivity server via TCP
|
||||||
|
// ProxyProtocol of GRPC is not supported with TCP transport at the moment
|
||||||
|
// Requires at least one of TCP or UDS to be set
|
||||||
|
// +optional
|
||||||
|
TCP *TCPTransport
|
||||||
|
|
||||||
|
// UDS is the UDS configuration for communicating with the konnectivity server via UDS
|
||||||
|
// Requires at least one of TCP or UDS to be set
|
||||||
|
// +optional
|
||||||
|
UDS *UDSTransport
|
||||||
|
}
|
||||||
|
|
||||||
|
// TCPTransport provides the information to connect to konnectivity server via TCP
|
||||||
|
type TCPTransport struct {
|
||||||
// URL is the location of the konnectivity server to connect to.
|
// URL is the location of the konnectivity server to connect to.
|
||||||
// As an example it might be "https://127.0.0.1:8131"
|
// As an example it might be "https://127.0.0.1:8131"
|
||||||
URL string
|
URL string
|
||||||
|
|
||||||
// CABundle is the file location of the CA to be used to determine trust with the konnectivity server.
|
// TLSConfig is the config needed to use TLS when connecting to konnectivity server
|
||||||
|
// +optional
|
||||||
|
TLSConfig *TLSConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// UDSTransport provides the information to connect to konnectivity server via UDS
|
||||||
|
type UDSTransport struct {
|
||||||
|
// UDSName is the name of the unix domain socket to connect to konnectivity server
|
||||||
|
// This does not use a unix:// prefix. (Eg: /etc/srv/kubernetes/konnectivity-server/konnectivity-server.socket)
|
||||||
|
UDSName string
|
||||||
|
}
|
||||||
|
|
||||||
|
// TLSConfig provides the authentication information to connect to konnectivity server
|
||||||
|
// Only used with TCPTransport
|
||||||
|
type TLSConfig struct {
|
||||||
|
// caBundle is the file location of the CA to be used to determine trust with the konnectivity server.
|
||||||
|
// Must be absent/empty if TCPTransport.URL is prefixed with http://
|
||||||
|
// If absent while TCPTransport.URL is prefixed with https://, default to system trust roots.
|
||||||
// +optional
|
// +optional
|
||||||
CABundle string
|
CABundle string
|
||||||
|
|
||||||
// ClientKey is the file location of the client key to be used in mtls handshakes with the konnectivity server.
|
// clientKey is the file location of the client key to authenticate with the konnectivity server
|
||||||
|
// Must be absent/empty if TCPTransport.URL is prefixed with http://
|
||||||
|
// Must be configured if TCPTransport.URL is prefixed with https://
|
||||||
// +optional
|
// +optional
|
||||||
ClientKey string
|
ClientKey string
|
||||||
|
|
||||||
// ClientCert is the file location of the client certificate to be used in mtls handshakes with the konnectivity server.
|
// clientCert is the file location of the client certificate to authenticate with the konnectivity server
|
||||||
|
// Must be absent/empty if TCPTransport.URL is prefixed with http://
|
||||||
|
// Must be configured if TCPTransport.URL is prefixed with https://
|
||||||
// +optional
|
// +optional
|
||||||
ClientCert string
|
ClientCert string
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,40 +71,78 @@ type EgressSelection struct {
|
||||||
|
|
||||||
// Connection provides the configuration for a single egress selection client.
|
// Connection provides the configuration for a single egress selection client.
|
||||||
type Connection struct {
|
type Connection struct {
|
||||||
// type is the type of connection used to connect from client to network/konnectivity server.
|
// Protocol is the protocol used to connect from client to the konnectivity server.
|
||||||
// Currently supported values are "http-connect" and "direct".
|
ProxyProtocol ProtocolType `json:"proxyProtocol,omitempty"`
|
||||||
Type string `json:"type"`
|
|
||||||
|
|
||||||
// httpConnect is the config needed to use http-connect to the konnectivity server.
|
// Transport defines the transport configurations we use to dial to the konnectivity server.
|
||||||
// Absence when the type is "http-connect" will cause an error
|
// This is required if ProxyProtocol is HTTPConnect or GRPC.
|
||||||
// Presence when the type is "direct" will also cause an error
|
|
||||||
// +optional
|
// +optional
|
||||||
HTTPConnect *HTTPConnectConfig `json:"httpConnect,omitempty"`
|
Transport *Transport `json:"transport,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type HTTPConnectConfig struct {
|
// ProtocolType is a set of valid values for Connection.ProtocolType
|
||||||
// url is the location of the proxy server to connect to.
|
type ProtocolType string
|
||||||
// As an example it might be "https://127.0.0.1:8131"
|
|
||||||
URL string `json:"url"`
|
|
||||||
|
|
||||||
|
// Valid types for ProtocolType for konnectivity server
|
||||||
|
const (
|
||||||
|
// Use HTTPConnect to connect to konnectivity server
|
||||||
|
ProtocolHTTPConnect ProtocolType = "HTTPConnect"
|
||||||
|
// Use grpc to connect to konnectivity server
|
||||||
|
ProtocolGRPC ProtocolType = "GRPC"
|
||||||
|
// Connect directly (skip konnectivity server)
|
||||||
|
ProtocolDirect ProtocolType = "Direct"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Transport defines the transport configurations we use to dial to the konnectivity server
|
||||||
|
type Transport struct {
|
||||||
|
// TCP is the TCP configuration for communicating with the konnectivity server via TCP
|
||||||
|
// ProxyProtocol of GRPC is not supported with TCP transport at the moment
|
||||||
|
// Requires at least one of TCP or UDS to be set
|
||||||
|
// +optional
|
||||||
|
TCP *TCPTransport `json:"tcp,omitempty"`
|
||||||
|
|
||||||
|
// UDS is the UDS configuration for communicating with the konnectivity server via UDS
|
||||||
|
// Requires at least one of TCP or UDS to be set
|
||||||
|
// +optional
|
||||||
|
UDS *UDSTransport `json:"uds,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TCPTransport provides the information to connect to konnectivity server via TCP
|
||||||
|
type TCPTransport struct {
|
||||||
|
// URL is the location of the konnectivity server to connect to.
|
||||||
|
// As an example it might be "https://127.0.0.1:8131"
|
||||||
|
URL string `json:"url,omitempty"`
|
||||||
|
|
||||||
|
// TLSConfig is the config needed to use TLS when connecting to konnectivity server
|
||||||
|
// +optional
|
||||||
|
TLSConfig *TLSConfig `json:"tlsConfig,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UDSTransport provides the information to connect to konnectivity server via UDS
|
||||||
|
type UDSTransport struct {
|
||||||
|
// UDSName is the name of the unix domain socket to connect to konnectivity server
|
||||||
|
// This does not use a unix:// prefix. (Eg: /etc/srv/kubernetes/konnectivity-server/konnectivity-server.socket)
|
||||||
|
UDSName string `json:"udsName,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TLSConfig provides the authentication information to connect to konnectivity server
|
||||||
|
// Only used with TCPTransport
|
||||||
|
type TLSConfig struct {
|
||||||
// caBundle is the file location of the CA to be used to determine trust with the konnectivity server.
|
// caBundle is the file location of the CA to be used to determine trust with the konnectivity server.
|
||||||
// Must be absent/empty http-connect using the plain http
|
// Must be absent/empty if TCPTransport.URL is prefixed with http://
|
||||||
// Must be configured for http-connect using the https protocol
|
// If absent while TCPTransport.URL is prefixed with https://, default to system trust roots.
|
||||||
// Misconfiguration will cause an error
|
|
||||||
// +optional
|
// +optional
|
||||||
CABundle string `json:"caBundle,omitempty"`
|
CABundle string `json:"caBundle,omitempty"`
|
||||||
|
|
||||||
// clientKey is the file location of the client key to be used in mtls handshakes with the konnectivity server.
|
// clientKey is the file location of the client key to be used in mtls handshakes with the konnectivity server.
|
||||||
// Must be absent/empty http-connect using the plain http
|
// Must be absent/empty if TCPTransport.URL is prefixed with http://
|
||||||
// Must be configured for http-connect using the https protocol
|
// Must be configured if TCPTransport.URL is prefixed with https://
|
||||||
// Misconfiguration will cause an error
|
|
||||||
// +optional
|
// +optional
|
||||||
ClientKey string `json:"clientKey,omitempty"`
|
ClientKey string `json:"clientKey,omitempty"`
|
||||||
|
|
||||||
// clientCert is the file location of the client certificate to be used in mtls handshakes with the konnectivity server.
|
// clientCert is the file location of the client certificate to be used in mtls handshakes with the konnectivity server.
|
||||||
// Must be absent/empty http-connect using the plain http
|
// Must be absent/empty if TCPTransport.URL is prefixed with http://
|
||||||
// Must be configured for http-connect using the https protocol
|
// Must be configured if TCPTransport.URL is prefixed with https://
|
||||||
// Misconfiguration will cause an error
|
|
||||||
// +optional
|
// +optional
|
||||||
ClientCert string `json:"clientCert,omitempty"`
|
ClientCert string `json:"clientCert,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -85,13 +85,43 @@ func RegisterConversions(s *runtime.Scheme) error {
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := s.AddGeneratedConversionFunc((*HTTPConnectConfig)(nil), (*apiserver.HTTPConnectConfig)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
if err := s.AddGeneratedConversionFunc((*TCPTransport)(nil), (*apiserver.TCPTransport)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
return Convert_v1alpha1_HTTPConnectConfig_To_apiserver_HTTPConnectConfig(a.(*HTTPConnectConfig), b.(*apiserver.HTTPConnectConfig), scope)
|
return Convert_v1alpha1_TCPTransport_To_apiserver_TCPTransport(a.(*TCPTransport), b.(*apiserver.TCPTransport), scope)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := s.AddGeneratedConversionFunc((*apiserver.HTTPConnectConfig)(nil), (*HTTPConnectConfig)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
if err := s.AddGeneratedConversionFunc((*apiserver.TCPTransport)(nil), (*TCPTransport)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
return Convert_apiserver_HTTPConnectConfig_To_v1alpha1_HTTPConnectConfig(a.(*apiserver.HTTPConnectConfig), b.(*HTTPConnectConfig), scope)
|
return Convert_apiserver_TCPTransport_To_v1alpha1_TCPTransport(a.(*apiserver.TCPTransport), b.(*TCPTransport), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.AddGeneratedConversionFunc((*TLSConfig)(nil), (*apiserver.TLSConfig)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convert_v1alpha1_TLSConfig_To_apiserver_TLSConfig(a.(*TLSConfig), b.(*apiserver.TLSConfig), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.AddGeneratedConversionFunc((*apiserver.TLSConfig)(nil), (*TLSConfig)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convert_apiserver_TLSConfig_To_v1alpha1_TLSConfig(a.(*apiserver.TLSConfig), b.(*TLSConfig), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.AddGeneratedConversionFunc((*Transport)(nil), (*apiserver.Transport)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convert_v1alpha1_Transport_To_apiserver_Transport(a.(*Transport), b.(*apiserver.Transport), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.AddGeneratedConversionFunc((*apiserver.Transport)(nil), (*Transport)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convert_apiserver_Transport_To_v1alpha1_Transport(a.(*apiserver.Transport), b.(*Transport), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.AddGeneratedConversionFunc((*UDSTransport)(nil), (*apiserver.UDSTransport)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convert_v1alpha1_UDSTransport_To_apiserver_UDSTransport(a.(*UDSTransport), b.(*apiserver.UDSTransport), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.AddGeneratedConversionFunc((*apiserver.UDSTransport)(nil), (*UDSTransport)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convert_apiserver_UDSTransport_To_v1alpha1_UDSTransport(a.(*apiserver.UDSTransport), b.(*UDSTransport), scope)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -143,8 +173,8 @@ func Convert_apiserver_AdmissionPluginConfiguration_To_v1alpha1_AdmissionPluginC
|
||||||
}
|
}
|
||||||
|
|
||||||
func autoConvert_v1alpha1_Connection_To_apiserver_Connection(in *Connection, out *apiserver.Connection, s conversion.Scope) error {
|
func autoConvert_v1alpha1_Connection_To_apiserver_Connection(in *Connection, out *apiserver.Connection, s conversion.Scope) error {
|
||||||
out.Type = in.Type
|
out.ProxyProtocol = apiserver.ProtocolType(in.ProxyProtocol)
|
||||||
out.HTTPConnect = (*apiserver.HTTPConnectConfig)(unsafe.Pointer(in.HTTPConnect))
|
out.Transport = (*apiserver.Transport)(unsafe.Pointer(in.Transport))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -154,8 +184,8 @@ func Convert_v1alpha1_Connection_To_apiserver_Connection(in *Connection, out *ap
|
||||||
}
|
}
|
||||||
|
|
||||||
func autoConvert_apiserver_Connection_To_v1alpha1_Connection(in *apiserver.Connection, out *Connection, s conversion.Scope) error {
|
func autoConvert_apiserver_Connection_To_v1alpha1_Connection(in *apiserver.Connection, out *Connection, s conversion.Scope) error {
|
||||||
out.Type = in.Type
|
out.ProxyProtocol = ProtocolType(in.ProxyProtocol)
|
||||||
out.HTTPConnect = (*HTTPConnectConfig)(unsafe.Pointer(in.HTTPConnect))
|
out.Transport = (*Transport)(unsafe.Pointer(in.Transport))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -210,28 +240,90 @@ func Convert_apiserver_EgressSelectorConfiguration_To_v1alpha1_EgressSelectorCon
|
||||||
return autoConvert_apiserver_EgressSelectorConfiguration_To_v1alpha1_EgressSelectorConfiguration(in, out, s)
|
return autoConvert_apiserver_EgressSelectorConfiguration_To_v1alpha1_EgressSelectorConfiguration(in, out, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func autoConvert_v1alpha1_HTTPConnectConfig_To_apiserver_HTTPConnectConfig(in *HTTPConnectConfig, out *apiserver.HTTPConnectConfig, s conversion.Scope) error {
|
func autoConvert_v1alpha1_TCPTransport_To_apiserver_TCPTransport(in *TCPTransport, out *apiserver.TCPTransport, s conversion.Scope) error {
|
||||||
out.URL = in.URL
|
out.URL = in.URL
|
||||||
|
out.TLSConfig = (*apiserver.TLSConfig)(unsafe.Pointer(in.TLSConfig))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert_v1alpha1_TCPTransport_To_apiserver_TCPTransport is an autogenerated conversion function.
|
||||||
|
func Convert_v1alpha1_TCPTransport_To_apiserver_TCPTransport(in *TCPTransport, out *apiserver.TCPTransport, s conversion.Scope) error {
|
||||||
|
return autoConvert_v1alpha1_TCPTransport_To_apiserver_TCPTransport(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvert_apiserver_TCPTransport_To_v1alpha1_TCPTransport(in *apiserver.TCPTransport, out *TCPTransport, s conversion.Scope) error {
|
||||||
|
out.URL = in.URL
|
||||||
|
out.TLSConfig = (*TLSConfig)(unsafe.Pointer(in.TLSConfig))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert_apiserver_TCPTransport_To_v1alpha1_TCPTransport is an autogenerated conversion function.
|
||||||
|
func Convert_apiserver_TCPTransport_To_v1alpha1_TCPTransport(in *apiserver.TCPTransport, out *TCPTransport, s conversion.Scope) error {
|
||||||
|
return autoConvert_apiserver_TCPTransport_To_v1alpha1_TCPTransport(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvert_v1alpha1_TLSConfig_To_apiserver_TLSConfig(in *TLSConfig, out *apiserver.TLSConfig, s conversion.Scope) error {
|
||||||
out.CABundle = in.CABundle
|
out.CABundle = in.CABundle
|
||||||
out.ClientKey = in.ClientKey
|
out.ClientKey = in.ClientKey
|
||||||
out.ClientCert = in.ClientCert
|
out.ClientCert = in.ClientCert
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert_v1alpha1_HTTPConnectConfig_To_apiserver_HTTPConnectConfig is an autogenerated conversion function.
|
// Convert_v1alpha1_TLSConfig_To_apiserver_TLSConfig is an autogenerated conversion function.
|
||||||
func Convert_v1alpha1_HTTPConnectConfig_To_apiserver_HTTPConnectConfig(in *HTTPConnectConfig, out *apiserver.HTTPConnectConfig, s conversion.Scope) error {
|
func Convert_v1alpha1_TLSConfig_To_apiserver_TLSConfig(in *TLSConfig, out *apiserver.TLSConfig, s conversion.Scope) error {
|
||||||
return autoConvert_v1alpha1_HTTPConnectConfig_To_apiserver_HTTPConnectConfig(in, out, s)
|
return autoConvert_v1alpha1_TLSConfig_To_apiserver_TLSConfig(in, out, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func autoConvert_apiserver_HTTPConnectConfig_To_v1alpha1_HTTPConnectConfig(in *apiserver.HTTPConnectConfig, out *HTTPConnectConfig, s conversion.Scope) error {
|
func autoConvert_apiserver_TLSConfig_To_v1alpha1_TLSConfig(in *apiserver.TLSConfig, out *TLSConfig, s conversion.Scope) error {
|
||||||
out.URL = in.URL
|
|
||||||
out.CABundle = in.CABundle
|
out.CABundle = in.CABundle
|
||||||
out.ClientKey = in.ClientKey
|
out.ClientKey = in.ClientKey
|
||||||
out.ClientCert = in.ClientCert
|
out.ClientCert = in.ClientCert
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert_apiserver_HTTPConnectConfig_To_v1alpha1_HTTPConnectConfig is an autogenerated conversion function.
|
// Convert_apiserver_TLSConfig_To_v1alpha1_TLSConfig is an autogenerated conversion function.
|
||||||
func Convert_apiserver_HTTPConnectConfig_To_v1alpha1_HTTPConnectConfig(in *apiserver.HTTPConnectConfig, out *HTTPConnectConfig, s conversion.Scope) error {
|
func Convert_apiserver_TLSConfig_To_v1alpha1_TLSConfig(in *apiserver.TLSConfig, out *TLSConfig, s conversion.Scope) error {
|
||||||
return autoConvert_apiserver_HTTPConnectConfig_To_v1alpha1_HTTPConnectConfig(in, out, s)
|
return autoConvert_apiserver_TLSConfig_To_v1alpha1_TLSConfig(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvert_v1alpha1_Transport_To_apiserver_Transport(in *Transport, out *apiserver.Transport, s conversion.Scope) error {
|
||||||
|
out.TCP = (*apiserver.TCPTransport)(unsafe.Pointer(in.TCP))
|
||||||
|
out.UDS = (*apiserver.UDSTransport)(unsafe.Pointer(in.UDS))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert_v1alpha1_Transport_To_apiserver_Transport is an autogenerated conversion function.
|
||||||
|
func Convert_v1alpha1_Transport_To_apiserver_Transport(in *Transport, out *apiserver.Transport, s conversion.Scope) error {
|
||||||
|
return autoConvert_v1alpha1_Transport_To_apiserver_Transport(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvert_apiserver_Transport_To_v1alpha1_Transport(in *apiserver.Transport, out *Transport, s conversion.Scope) error {
|
||||||
|
out.TCP = (*TCPTransport)(unsafe.Pointer(in.TCP))
|
||||||
|
out.UDS = (*UDSTransport)(unsafe.Pointer(in.UDS))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert_apiserver_Transport_To_v1alpha1_Transport is an autogenerated conversion function.
|
||||||
|
func Convert_apiserver_Transport_To_v1alpha1_Transport(in *apiserver.Transport, out *Transport, s conversion.Scope) error {
|
||||||
|
return autoConvert_apiserver_Transport_To_v1alpha1_Transport(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvert_v1alpha1_UDSTransport_To_apiserver_UDSTransport(in *UDSTransport, out *apiserver.UDSTransport, s conversion.Scope) error {
|
||||||
|
out.UDSName = in.UDSName
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert_v1alpha1_UDSTransport_To_apiserver_UDSTransport is an autogenerated conversion function.
|
||||||
|
func Convert_v1alpha1_UDSTransport_To_apiserver_UDSTransport(in *UDSTransport, out *apiserver.UDSTransport, s conversion.Scope) error {
|
||||||
|
return autoConvert_v1alpha1_UDSTransport_To_apiserver_UDSTransport(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvert_apiserver_UDSTransport_To_v1alpha1_UDSTransport(in *apiserver.UDSTransport, out *UDSTransport, s conversion.Scope) error {
|
||||||
|
out.UDSName = in.UDSName
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert_apiserver_UDSTransport_To_v1alpha1_UDSTransport is an autogenerated conversion function.
|
||||||
|
func Convert_apiserver_UDSTransport_To_v1alpha1_UDSTransport(in *apiserver.UDSTransport, out *UDSTransport, s conversion.Scope) error {
|
||||||
|
return autoConvert_apiserver_UDSTransport_To_v1alpha1_UDSTransport(in, out, s)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,10 +80,10 @@ func (in *AdmissionPluginConfiguration) DeepCopy() *AdmissionPluginConfiguration
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *Connection) DeepCopyInto(out *Connection) {
|
func (in *Connection) DeepCopyInto(out *Connection) {
|
||||||
*out = *in
|
*out = *in
|
||||||
if in.HTTPConnect != nil {
|
if in.Transport != nil {
|
||||||
in, out := &in.HTTPConnect, &out.HTTPConnect
|
in, out := &in.Transport, &out.Transport
|
||||||
*out = new(HTTPConnectConfig)
|
*out = new(Transport)
|
||||||
**out = **in
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -148,17 +148,80 @@ func (in *EgressSelectorConfiguration) DeepCopyObject() runtime.Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *HTTPConnectConfig) DeepCopyInto(out *HTTPConnectConfig) {
|
func (in *TCPTransport) DeepCopyInto(out *TCPTransport) {
|
||||||
|
*out = *in
|
||||||
|
if in.TLSConfig != nil {
|
||||||
|
in, out := &in.TLSConfig, &out.TLSConfig
|
||||||
|
*out = new(TLSConfig)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPTransport.
|
||||||
|
func (in *TCPTransport) DeepCopy() *TCPTransport {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(TCPTransport)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *TLSConfig) DeepCopyInto(out *TLSConfig) {
|
||||||
*out = *in
|
*out = *in
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPConnectConfig.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSConfig.
|
||||||
func (in *HTTPConnectConfig) DeepCopy() *HTTPConnectConfig {
|
func (in *TLSConfig) DeepCopy() *TLSConfig {
|
||||||
if in == nil {
|
if in == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
out := new(HTTPConnectConfig)
|
out := new(TLSConfig)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *Transport) DeepCopyInto(out *Transport) {
|
||||||
|
*out = *in
|
||||||
|
if in.TCP != nil {
|
||||||
|
in, out := &in.TCP, &out.TCP
|
||||||
|
*out = new(TCPTransport)
|
||||||
|
(*in).DeepCopyInto(*out)
|
||||||
|
}
|
||||||
|
if in.UDS != nil {
|
||||||
|
in, out := &in.UDS, &out.UDS
|
||||||
|
*out = new(UDSTransport)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Transport.
|
||||||
|
func (in *Transport) DeepCopy() *Transport {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(Transport)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *UDSTransport) DeepCopyInto(out *UDSTransport) {
|
||||||
|
*out = *in
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UDSTransport.
|
||||||
|
func (in *UDSTransport) DeepCopy() *UDSTransport {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(UDSTransport)
|
||||||
in.DeepCopyInto(out)
|
in.DeepCopyInto(out)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,10 +80,10 @@ func (in *AdmissionPluginConfiguration) DeepCopy() *AdmissionPluginConfiguration
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *Connection) DeepCopyInto(out *Connection) {
|
func (in *Connection) DeepCopyInto(out *Connection) {
|
||||||
*out = *in
|
*out = *in
|
||||||
if in.HTTPConnect != nil {
|
if in.Transport != nil {
|
||||||
in, out := &in.HTTPConnect, &out.HTTPConnect
|
in, out := &in.Transport, &out.Transport
|
||||||
*out = new(HTTPConnectConfig)
|
*out = new(Transport)
|
||||||
**out = **in
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -148,17 +148,80 @@ func (in *EgressSelectorConfiguration) DeepCopyObject() runtime.Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *HTTPConnectConfig) DeepCopyInto(out *HTTPConnectConfig) {
|
func (in *TCPTransport) DeepCopyInto(out *TCPTransport) {
|
||||||
|
*out = *in
|
||||||
|
if in.TLSConfig != nil {
|
||||||
|
in, out := &in.TLSConfig, &out.TLSConfig
|
||||||
|
*out = new(TLSConfig)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPTransport.
|
||||||
|
func (in *TCPTransport) DeepCopy() *TCPTransport {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(TCPTransport)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *TLSConfig) DeepCopyInto(out *TLSConfig) {
|
||||||
*out = *in
|
*out = *in
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPConnectConfig.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSConfig.
|
||||||
func (in *HTTPConnectConfig) DeepCopy() *HTTPConnectConfig {
|
func (in *TLSConfig) DeepCopy() *TLSConfig {
|
||||||
if in == nil {
|
if in == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
out := new(HTTPConnectConfig)
|
out := new(TLSConfig)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *Transport) DeepCopyInto(out *Transport) {
|
||||||
|
*out = *in
|
||||||
|
if in.TCP != nil {
|
||||||
|
in, out := &in.TCP, &out.TCP
|
||||||
|
*out = new(TCPTransport)
|
||||||
|
(*in).DeepCopyInto(*out)
|
||||||
|
}
|
||||||
|
if in.UDS != nil {
|
||||||
|
in, out := &in.UDS, &out.UDS
|
||||||
|
*out = new(UDSTransport)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Transport.
|
||||||
|
func (in *Transport) DeepCopy() *Transport {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(Transport)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *UDSTransport) DeepCopyInto(out *UDSTransport) {
|
||||||
|
*out = *in
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UDSTransport.
|
||||||
|
func (in *UDSTransport) DeepCopy() *UDSTransport {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(UDSTransport)
|
||||||
in.DeepCopyInto(out)
|
in.DeepCopyInto(out)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,99 +78,155 @@ func ValidateEgressSelectorConfiguration(config *apiserver.EgressSelectorConfigu
|
||||||
return allErrs // Treating a nil configuration as valid
|
return allErrs // Treating a nil configuration as valid
|
||||||
}
|
}
|
||||||
for _, service := range config.EgressSelections {
|
for _, service := range config.EgressSelections {
|
||||||
base := field.NewPath("service", "connection")
|
fldPath := field.NewPath("service", "connection")
|
||||||
switch service.Connection.Type {
|
switch service.Connection.ProxyProtocol {
|
||||||
case "direct":
|
case apiserver.ProtocolDirect:
|
||||||
allErrs = append(allErrs, validateDirectConnection(service.Connection, base)...)
|
allErrs = append(allErrs, validateDirectConnection(service.Connection, fldPath)...)
|
||||||
case "http-connect":
|
case apiserver.ProtocolHTTPConnect:
|
||||||
allErrs = append(allErrs, validateHTTPConnection(service.Connection, base)...)
|
allErrs = append(allErrs, validateHTTPConnectTransport(service.Connection.Transport, fldPath)...)
|
||||||
|
case apiserver.ProtocolGRPC:
|
||||||
|
allErrs = append(allErrs, validateGRPCTransport(service.Connection.Transport, fldPath)...)
|
||||||
default:
|
default:
|
||||||
allErrs = append(allErrs, field.NotSupported(
|
allErrs = append(allErrs, field.NotSupported(
|
||||||
base.Child("type"),
|
fldPath.Child("protocol"),
|
||||||
service.Connection.Type,
|
service.Connection.ProxyProtocol,
|
||||||
[]string{"direct", "http-connect"}))
|
[]string{
|
||||||
|
string(apiserver.ProtocolDirect),
|
||||||
|
string(apiserver.ProtocolHTTPConnect),
|
||||||
|
string(apiserver.ProtocolGRPC),
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateHTTPConnectTransport(transport *apiserver.Transport, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
if transport == nil {
|
||||||
|
allErrs = append(allErrs, field.Required(
|
||||||
|
fldPath.Child("transport"),
|
||||||
|
"transport must be set for HTTPConnect"))
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
if transport.TCP != nil && transport.UDS != nil {
|
||||||
|
allErrs = append(allErrs, field.Invalid(
|
||||||
|
fldPath.Child("tcp"),
|
||||||
|
transport.TCP,
|
||||||
|
"TCP and UDS cannot both be set"))
|
||||||
|
} else if transport.TCP == nil && transport.UDS == nil {
|
||||||
|
allErrs = append(allErrs, field.Required(
|
||||||
|
fldPath.Child("tcp"),
|
||||||
|
"One of TCP or UDS must be set"))
|
||||||
|
} else if transport.TCP != nil {
|
||||||
|
allErrs = append(allErrs, validateTCPConnection(transport.TCP, fldPath)...)
|
||||||
|
} else if transport.UDS != nil {
|
||||||
|
allErrs = append(allErrs, validateUDSConnection(transport.UDS, fldPath)...)
|
||||||
|
}
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateGRPCTransport(transport *apiserver.Transport, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
if transport == nil {
|
||||||
|
allErrs = append(allErrs, field.Required(
|
||||||
|
fldPath.Child("transport"),
|
||||||
|
"transport must be set for GRPC"))
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
if transport.UDS != nil {
|
||||||
|
allErrs = append(allErrs, validateUDSConnection(transport.UDS, fldPath)...)
|
||||||
|
} else {
|
||||||
|
allErrs = append(allErrs, field.Required(
|
||||||
|
fldPath.Child("uds"),
|
||||||
|
"UDS must be set with GRPC"))
|
||||||
|
}
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateDirectConnection(connection apiserver.Connection, fldPath *field.Path) field.ErrorList {
|
func validateDirectConnection(connection apiserver.Connection, fldPath *field.Path) field.ErrorList {
|
||||||
if connection.HTTPConnect != nil {
|
if connection.Transport != nil {
|
||||||
return field.ErrorList{field.Invalid(
|
return field.ErrorList{field.Invalid(
|
||||||
fldPath.Child("httpConnect"),
|
fldPath.Child("transport"),
|
||||||
"direct",
|
"direct",
|
||||||
"httpConnect config should be absent for direct connect"),
|
"Transport config should be absent for direct connect"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateHTTPConnection(connection apiserver.Connection, fldPath *field.Path) field.ErrorList {
|
func validateUDSConnection(udsConfig *apiserver.UDSTransport, fldPath *field.Path) field.ErrorList {
|
||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
if connection.HTTPConnect == nil {
|
if udsConfig.UDSName == "" {
|
||||||
allErrs = append(allErrs, field.Invalid(
|
allErrs = append(allErrs, field.Invalid(
|
||||||
fldPath.Child("httpConnect"),
|
fldPath.Child("udsName"),
|
||||||
"nil",
|
"nil",
|
||||||
"httpConnect config should be present for http-connect"))
|
"UDSName should be present for UDS connections"))
|
||||||
} else if strings.HasPrefix(connection.HTTPConnect.URL, "https://") {
|
}
|
||||||
if connection.HTTPConnect.CABundle == "" {
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateTCPConnection(tcpConfig *apiserver.TCPTransport, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
|
||||||
|
if strings.HasPrefix(tcpConfig.URL, "http://") {
|
||||||
|
if tcpConfig.TLSConfig != nil {
|
||||||
allErrs = append(allErrs, field.Invalid(
|
allErrs = append(allErrs, field.Invalid(
|
||||||
fldPath.Child("httpConnect", "caBundle"),
|
fldPath.Child("tlsConfig"),
|
||||||
"nil",
|
"nil",
|
||||||
"http-connect via https requires caBundle"))
|
"TLSConfig config should not be present when using HTTP"))
|
||||||
} else if exists, err := path.Exists(path.CheckFollowSymlink, connection.HTTPConnect.CABundle); exists == false || err != nil {
|
|
||||||
allErrs = append(allErrs, field.Invalid(
|
|
||||||
fldPath.Child("httpConnect", "caBundle"),
|
|
||||||
connection.HTTPConnect.CABundle,
|
|
||||||
"http-connect ca bundle does not exist"))
|
|
||||||
}
|
|
||||||
if connection.HTTPConnect.ClientCert == "" {
|
|
||||||
allErrs = append(allErrs, field.Invalid(
|
|
||||||
fldPath.Child("httpConnect", "clientCert"),
|
|
||||||
"nil",
|
|
||||||
"http-connect via https requires clientCert"))
|
|
||||||
} else if exists, err := path.Exists(path.CheckFollowSymlink, connection.HTTPConnect.ClientCert); exists == false || err != nil {
|
|
||||||
allErrs = append(allErrs, field.Invalid(
|
|
||||||
fldPath.Child("httpConnect", "clientCert"),
|
|
||||||
connection.HTTPConnect.ClientCert,
|
|
||||||
"http-connect client cert does not exist"))
|
|
||||||
}
|
|
||||||
if connection.HTTPConnect.ClientKey == "" {
|
|
||||||
allErrs = append(allErrs, field.Invalid(
|
|
||||||
fldPath.Child("httpConnect", "clientKey"),
|
|
||||||
"nil",
|
|
||||||
"http-connect via https requires clientKey"))
|
|
||||||
} else if exists, err := path.Exists(path.CheckFollowSymlink, connection.HTTPConnect.ClientKey); exists == false || err != nil {
|
|
||||||
allErrs = append(allErrs, field.Invalid(
|
|
||||||
fldPath.Child("httpConnect", "clientKey"),
|
|
||||||
connection.HTTPConnect.ClientKey,
|
|
||||||
"http-connect client key does not exist"))
|
|
||||||
}
|
|
||||||
} else if strings.HasPrefix(connection.HTTPConnect.URL, "http://") {
|
|
||||||
if connection.HTTPConnect.CABundle != "" {
|
|
||||||
allErrs = append(allErrs, field.Invalid(
|
|
||||||
fldPath.Child("httpConnect", "caBundle"),
|
|
||||||
connection.HTTPConnect.CABundle,
|
|
||||||
"http-connect via http does not support caBundle"))
|
|
||||||
}
|
|
||||||
if connection.HTTPConnect.ClientCert != "" {
|
|
||||||
allErrs = append(allErrs, field.Invalid(
|
|
||||||
fldPath.Child("httpConnect", "clientCert"),
|
|
||||||
connection.HTTPConnect.ClientCert,
|
|
||||||
"http-connect via http does not support clientCert"))
|
|
||||||
}
|
|
||||||
if connection.HTTPConnect.ClientKey != "" {
|
|
||||||
allErrs = append(allErrs, field.Invalid(
|
|
||||||
fldPath.Child("httpConnect", "clientKey"),
|
|
||||||
connection.HTTPConnect.ClientKey,
|
|
||||||
"http-connect via http does not support clientKey"))
|
|
||||||
}
|
}
|
||||||
|
} else if strings.HasPrefix(tcpConfig.URL, "https://") {
|
||||||
|
return validateTLSConfig(tcpConfig.TLSConfig, fldPath)
|
||||||
} else {
|
} else {
|
||||||
allErrs = append(allErrs, field.Invalid(
|
allErrs = append(allErrs, field.Invalid(
|
||||||
fldPath.Child("httpConnect", "url"),
|
fldPath.Child("url"),
|
||||||
connection.HTTPConnect.URL,
|
tcpConfig.URL,
|
||||||
"supported connection protocols are http:// and https://"))
|
"supported connection protocols are http:// and https://"))
|
||||||
}
|
}
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateTLSConfig(tlsConfig *apiserver.TLSConfig, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
|
||||||
|
if tlsConfig == nil {
|
||||||
|
allErrs = append(allErrs, field.Required(
|
||||||
|
fldPath.Child("tlsConfig"),
|
||||||
|
"TLSConfig must be present when using HTTPS"))
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
if tlsConfig.CABundle != "" {
|
||||||
|
if exists, err := path.Exists(path.CheckFollowSymlink, tlsConfig.CABundle); exists == false || err != nil {
|
||||||
|
allErrs = append(allErrs, field.Invalid(
|
||||||
|
fldPath.Child("tlsConfig", "caBundle"),
|
||||||
|
tlsConfig.CABundle,
|
||||||
|
"TLS config ca bundle does not exist"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tlsConfig.ClientCert == "" {
|
||||||
|
allErrs = append(allErrs, field.Invalid(
|
||||||
|
fldPath.Child("tlsConfig", "clientCert"),
|
||||||
|
"nil",
|
||||||
|
"Using TLS requires clientCert"))
|
||||||
|
} else if exists, err := path.Exists(path.CheckFollowSymlink, tlsConfig.ClientCert); exists == false || err != nil {
|
||||||
|
allErrs = append(allErrs, field.Invalid(
|
||||||
|
fldPath.Child("tlsConfig", "clientCert"),
|
||||||
|
tlsConfig.ClientCert,
|
||||||
|
"TLS client cert does not exist"))
|
||||||
|
}
|
||||||
|
if tlsConfig.ClientKey == "" {
|
||||||
|
allErrs = append(allErrs, field.Invalid(
|
||||||
|
fldPath.Child("tlsConfig", "clientKey"),
|
||||||
|
"nil",
|
||||||
|
"Using TLS requires requires clientKey"))
|
||||||
|
} else if exists, err := path.Exists(path.CheckFollowSymlink, tlsConfig.ClientKey); exists == false || err != nil {
|
||||||
|
allErrs = append(allErrs, field.Invalid(
|
||||||
|
fldPath.Child("tlsConfig", "clientKey"),
|
||||||
|
tlsConfig.ClientKey,
|
||||||
|
"TLS client key does not exist"))
|
||||||
|
}
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,23 +62,27 @@ kind: EgressSelectorConfiguration
|
||||||
egressSelections:
|
egressSelections:
|
||||||
- name: "cluster"
|
- name: "cluster"
|
||||||
connection:
|
connection:
|
||||||
type: "http-connect"
|
proxyProtocol: "HTTPConnect"
|
||||||
httpConnect:
|
transport:
|
||||||
url: "https://127.0.0.1:8131"
|
tcp:
|
||||||
caBundle: "/etc/srv/kubernetes/pki/konnectivity-server/ca.crt"
|
url: "https://127.0.0.1:8131"
|
||||||
clientKey: "/etc/srv/kubernetes/pki/konnectivity-server/client.key"
|
tlsConfig:
|
||||||
clientCert: "/etc/srv/kubernetes/pki/konnectivity-server/client.crt"
|
caBundle: "/etc/srv/kubernetes/pki/konnectivity-server/ca.crt"
|
||||||
|
clientKey: "/etc/srv/kubernetes/pki/konnectivity-server/client.key"
|
||||||
|
clientCert: "/etc/srv/kubernetes/pki/konnectivity-server/client.crt"
|
||||||
- name: "master"
|
- name: "master"
|
||||||
connection:
|
connection:
|
||||||
type: "http-connect"
|
proxyProtocol: "HTTPConnect"
|
||||||
httpConnect:
|
transport:
|
||||||
url: "https://127.0.0.1:8132"
|
tcp:
|
||||||
caBundle: "/etc/srv/kubernetes/pki/konnectivity-server-master/ca.crt"
|
url: "https://127.0.0.1:8132"
|
||||||
clientKey: "/etc/srv/kubernetes/pki/konnectivity-server-master/client.key"
|
tlsConfig:
|
||||||
clientCert: "/etc/srv/kubernetes/pki/konnectivity-server-master/client.crt"
|
caBundle: "/etc/srv/kubernetes/pki/konnectivity-server-master/ca.crt"
|
||||||
|
clientKey: "/etc/srv/kubernetes/pki/konnectivity-server-master/client.key"
|
||||||
|
clientCert: "/etc/srv/kubernetes/pki/konnectivity-server-master/client.crt"
|
||||||
- name: "etcd"
|
- name: "etcd"
|
||||||
connection:
|
connection:
|
||||||
type: "direct"
|
proxyProtocol: "Direct"
|
||||||
`,
|
`,
|
||||||
expectedResult: &apiserver.EgressSelectorConfiguration{
|
expectedResult: &apiserver.EgressSelectorConfiguration{
|
||||||
TypeMeta: metav1.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
|
@ -89,31 +93,40 @@ egressSelections:
|
||||||
{
|
{
|
||||||
Name: "cluster",
|
Name: "cluster",
|
||||||
Connection: apiserver.Connection{
|
Connection: apiserver.Connection{
|
||||||
Type: "http-connect",
|
ProxyProtocol: "HTTPConnect",
|
||||||
HTTPConnect: &apiserver.HTTPConnectConfig{
|
Transport: &apiserver.Transport{
|
||||||
URL: "https://127.0.0.1:8131",
|
TCP: &apiserver.TCPTransport{
|
||||||
CABundle: "/etc/srv/kubernetes/pki/konnectivity-server/ca.crt",
|
URL: "https://127.0.0.1:8131",
|
||||||
ClientKey: "/etc/srv/kubernetes/pki/konnectivity-server/client.key",
|
|
||||||
ClientCert: "/etc/srv/kubernetes/pki/konnectivity-server/client.crt",
|
TLSConfig: &apiserver.TLSConfig{
|
||||||
|
CABundle: "/etc/srv/kubernetes/pki/konnectivity-server/ca.crt",
|
||||||
|
ClientKey: "/etc/srv/kubernetes/pki/konnectivity-server/client.key",
|
||||||
|
ClientCert: "/etc/srv/kubernetes/pki/konnectivity-server/client.crt",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "master",
|
Name: "master",
|
||||||
Connection: apiserver.Connection{
|
Connection: apiserver.Connection{
|
||||||
Type: "http-connect",
|
ProxyProtocol: "HTTPConnect",
|
||||||
HTTPConnect: &apiserver.HTTPConnectConfig{
|
Transport: &apiserver.Transport{
|
||||||
URL: "https://127.0.0.1:8132",
|
TCP: &apiserver.TCPTransport{
|
||||||
CABundle: "/etc/srv/kubernetes/pki/konnectivity-server-master/ca.crt",
|
URL: "https://127.0.0.1:8132",
|
||||||
ClientKey: "/etc/srv/kubernetes/pki/konnectivity-server-master/client.key",
|
TLSConfig: &apiserver.TLSConfig{
|
||||||
ClientCert: "/etc/srv/kubernetes/pki/konnectivity-server-master/client.crt",
|
CABundle: "/etc/srv/kubernetes/pki/konnectivity-server-master/ca.crt",
|
||||||
|
ClientKey: "/etc/srv/kubernetes/pki/konnectivity-server-master/client.key",
|
||||||
|
ClientCert: "/etc/srv/kubernetes/pki/konnectivity-server-master/client.crt",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "etcd",
|
Name: "etcd",
|
||||||
Connection: apiserver.Connection{
|
Connection: apiserver.Connection{
|
||||||
Type: "direct",
|
ProxyProtocol: "Direct",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -210,3 +223,206 @@ spec:
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValidateEgressSelectorConfiguration(t *testing.T) {
|
||||||
|
testcases := []struct {
|
||||||
|
name string
|
||||||
|
expectError bool
|
||||||
|
contents *apiserver.EgressSelectorConfiguration
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "direct-valid",
|
||||||
|
expectError: false,
|
||||||
|
contents: &apiserver.EgressSelectorConfiguration{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
Kind: "",
|
||||||
|
APIVersion: "",
|
||||||
|
},
|
||||||
|
EgressSelections: []apiserver.EgressSelection{
|
||||||
|
{
|
||||||
|
Name: "master",
|
||||||
|
Connection: apiserver.Connection{
|
||||||
|
ProxyProtocol: apiserver.ProtocolDirect,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "direct-invalid-transport",
|
||||||
|
expectError: true,
|
||||||
|
contents: &apiserver.EgressSelectorConfiguration{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
Kind: "",
|
||||||
|
APIVersion: "",
|
||||||
|
},
|
||||||
|
EgressSelections: []apiserver.EgressSelection{
|
||||||
|
{
|
||||||
|
Name: "master",
|
||||||
|
Connection: apiserver.Connection{
|
||||||
|
ProxyProtocol: apiserver.ProtocolDirect,
|
||||||
|
Transport: &apiserver.Transport{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "httpconnect-no-https",
|
||||||
|
expectError: false,
|
||||||
|
contents: &apiserver.EgressSelectorConfiguration{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
Kind: "",
|
||||||
|
APIVersion: "",
|
||||||
|
},
|
||||||
|
EgressSelections: []apiserver.EgressSelection{
|
||||||
|
{
|
||||||
|
Name: "cluster",
|
||||||
|
Connection: apiserver.Connection{
|
||||||
|
ProxyProtocol: apiserver.ProtocolHTTPConnect,
|
||||||
|
Transport: &apiserver.Transport{
|
||||||
|
TCP: &apiserver.TCPTransport{
|
||||||
|
URL: "http://127.0.0.1:8131",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "httpconnect-https-no-cert-error",
|
||||||
|
expectError: true,
|
||||||
|
contents: &apiserver.EgressSelectorConfiguration{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
Kind: "",
|
||||||
|
APIVersion: "",
|
||||||
|
},
|
||||||
|
EgressSelections: []apiserver.EgressSelection{
|
||||||
|
{
|
||||||
|
Name: "cluster",
|
||||||
|
Connection: apiserver.Connection{
|
||||||
|
ProxyProtocol: apiserver.ProtocolHTTPConnect,
|
||||||
|
Transport: &apiserver.Transport{
|
||||||
|
TCP: &apiserver.TCPTransport{
|
||||||
|
URL: "https://127.0.0.1:8131",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "httpconnect-tcp-uds-both-set",
|
||||||
|
expectError: true,
|
||||||
|
contents: &apiserver.EgressSelectorConfiguration{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
Kind: "",
|
||||||
|
APIVersion: "",
|
||||||
|
},
|
||||||
|
EgressSelections: []apiserver.EgressSelection{
|
||||||
|
{
|
||||||
|
Name: "cluster",
|
||||||
|
Connection: apiserver.Connection{
|
||||||
|
ProxyProtocol: apiserver.ProtocolHTTPConnect,
|
||||||
|
Transport: &apiserver.Transport{
|
||||||
|
TCP: &apiserver.TCPTransport{
|
||||||
|
URL: "http://127.0.0.1:8131",
|
||||||
|
},
|
||||||
|
UDS: &apiserver.UDSTransport{
|
||||||
|
UDSName: "/etc/srv/kubernetes/konnectivity/konnectivity-server.socket",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "httpconnect-uds",
|
||||||
|
expectError: false,
|
||||||
|
contents: &apiserver.EgressSelectorConfiguration{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
Kind: "",
|
||||||
|
APIVersion: "",
|
||||||
|
},
|
||||||
|
EgressSelections: []apiserver.EgressSelection{
|
||||||
|
{
|
||||||
|
Name: "cluster",
|
||||||
|
Connection: apiserver.Connection{
|
||||||
|
ProxyProtocol: apiserver.ProtocolHTTPConnect,
|
||||||
|
Transport: &apiserver.Transport{
|
||||||
|
UDS: &apiserver.UDSTransport{
|
||||||
|
UDSName: "/etc/srv/kubernetes/konnectivity/konnectivity-server.socket",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "grpc-https-invalid",
|
||||||
|
expectError: true,
|
||||||
|
contents: &apiserver.EgressSelectorConfiguration{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
Kind: "",
|
||||||
|
APIVersion: "",
|
||||||
|
},
|
||||||
|
EgressSelections: []apiserver.EgressSelection{
|
||||||
|
{
|
||||||
|
Name: "cluster",
|
||||||
|
Connection: apiserver.Connection{
|
||||||
|
ProxyProtocol: apiserver.ProtocolGRPC,
|
||||||
|
Transport: &apiserver.Transport{
|
||||||
|
TCP: &apiserver.TCPTransport{
|
||||||
|
URL: "http://127.0.0.1:8131",
|
||||||
|
TLSConfig: &apiserver.TLSConfig{
|
||||||
|
CABundle: "",
|
||||||
|
ClientKey: "",
|
||||||
|
ClientCert: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "grpc-uds",
|
||||||
|
expectError: false,
|
||||||
|
contents: &apiserver.EgressSelectorConfiguration{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
Kind: "",
|
||||||
|
APIVersion: "",
|
||||||
|
},
|
||||||
|
EgressSelections: []apiserver.EgressSelection{
|
||||||
|
{
|
||||||
|
Name: "cluster",
|
||||||
|
Connection: apiserver.Connection{
|
||||||
|
ProxyProtocol: apiserver.ProtocolGRPC,
|
||||||
|
Transport: &apiserver.Transport{
|
||||||
|
UDS: &apiserver.UDSTransport{
|
||||||
|
UDSName: "/etc/srv/kubernetes/konnectivity/konnectivity-server.socket",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testcases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
errs := ValidateEgressSelectorConfiguration(tc.contents)
|
||||||
|
if tc.expectError == false && len(errs) != 0 {
|
||||||
|
t.Errorf("Calling ValidateEgressSelectorConfiguration expected no error, got %v", errs)
|
||||||
|
} else if tc.expectError == true && len(errs) == 0 {
|
||||||
|
t.Errorf("Calling ValidateEgressSelectorConfiguration expected error, got no error")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"google.golang.org/grpc"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||||
"k8s.io/apiserver/pkg/apis/apiserver"
|
"k8s.io/apiserver/pkg/apis/apiserver"
|
||||||
|
|
@ -29,6 +30,7 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
client "sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -94,13 +96,40 @@ func lookupServiceName(name string) (EgressType, error) {
|
||||||
return -1, fmt.Errorf("unrecognized service name %s", name)
|
return -1, fmt.Errorf("unrecognized service name %s", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createConnectDialer(connectConfig *apiserver.HTTPConnectConfig) (utilnet.DialFunc, error) {
|
func tunnelHTTPConnect(proxyConn net.Conn, proxyAddress, addr string) (net.Conn, error) {
|
||||||
clientCert := connectConfig.ClientCert
|
fmt.Fprintf(proxyConn, "CONNECT %s HTTP/1.1\r\nHost: %s\r\n\r\n", addr, "127.0.0.1")
|
||||||
clientKey := connectConfig.ClientKey
|
br := bufio.NewReader(proxyConn)
|
||||||
caCert := connectConfig.CABundle
|
res, err := http.ReadResponse(br, nil)
|
||||||
proxyURL, err := url.Parse(connectConfig.URL)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("invalid proxy server url %q: %v", connectConfig.URL, err)
|
proxyConn.Close()
|
||||||
|
return nil, fmt.Errorf("reading HTTP response from CONNECT to %s via proxy %s failed: %v",
|
||||||
|
addr, proxyAddress, err)
|
||||||
|
}
|
||||||
|
if res.StatusCode != 200 {
|
||||||
|
proxyConn.Close()
|
||||||
|
return nil, fmt.Errorf("proxy error from %s while dialing %s, code %d: %v",
|
||||||
|
proxyAddress, addr, res.StatusCode, res.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's safe to discard the bufio.Reader here and return the
|
||||||
|
// original TCP conn directly because we only use this for
|
||||||
|
// TLS, and in TLS the client speaks first, so we know there's
|
||||||
|
// no unbuffered data. But we can double-check.
|
||||||
|
if br.Buffered() > 0 {
|
||||||
|
proxyConn.Close()
|
||||||
|
return nil, fmt.Errorf("unexpected %d bytes of buffered data from CONNECT proxy %q",
|
||||||
|
br.Buffered(), proxyAddress)
|
||||||
|
}
|
||||||
|
return proxyConn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createConnectTCPDialer(tcpTransport *apiserver.TCPTransport) (utilnet.DialFunc, error) {
|
||||||
|
clientCert := tcpTransport.TLSConfig.ClientCert
|
||||||
|
clientKey := tcpTransport.TLSConfig.ClientKey
|
||||||
|
caCert := tcpTransport.TLSConfig.CABundle
|
||||||
|
proxyURL, err := url.Parse(tcpTransport.URL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid proxy server url %q: %v", tcpTransport.URL, err)
|
||||||
}
|
}
|
||||||
proxyAddress := proxyURL.Host
|
proxyAddress := proxyURL.Host
|
||||||
|
|
||||||
|
|
@ -109,13 +138,18 @@ func createConnectDialer(connectConfig *apiserver.HTTPConnectConfig) (utilnet.Di
|
||||||
return nil, fmt.Errorf("failed to read key pair %s & %s, got %v", clientCert, clientKey, err)
|
return nil, fmt.Errorf("failed to read key pair %s & %s, got %v", clientCert, clientKey, err)
|
||||||
}
|
}
|
||||||
certPool := x509.NewCertPool()
|
certPool := x509.NewCertPool()
|
||||||
certBytes, err := ioutil.ReadFile(caCert)
|
if caCert != "" {
|
||||||
if err != nil {
|
certBytes, err := ioutil.ReadFile(caCert)
|
||||||
return nil, fmt.Errorf("failed to read cert file %s, got %v", caCert, err)
|
if err != nil {
|
||||||
}
|
return nil, fmt.Errorf("failed to read cert file %s, got %v", caCert, err)
|
||||||
ok := certPool.AppendCertsFromPEM(certBytes)
|
}
|
||||||
if !ok {
|
ok := certPool.AppendCertsFromPEM(certBytes)
|
||||||
return nil, fmt.Errorf("failed to append CA cert to the cert pool")
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("failed to append CA cert to the cert pool")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Use host's root CA set instead of providing our own
|
||||||
|
certPool = nil
|
||||||
}
|
}
|
||||||
contextDialer := func(ctx context.Context, network, addr string) (net.Conn, error) {
|
contextDialer := func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
klog.V(4).Infof("Sending request to %q.", addr)
|
klog.V(4).Infof("Sending request to %q.", addr)
|
||||||
|
|
@ -128,30 +162,42 @@ func createConnectDialer(connectConfig *apiserver.HTTPConnectConfig) (utilnet.Di
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("dialing proxy %q failed: %v", proxyAddress, err)
|
return nil, fmt.Errorf("dialing proxy %q failed: %v", proxyAddress, err)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(proxyConn, "CONNECT %s HTTP/1.1\r\nHost: %s\r\n\r\n", addr, "127.0.0.1")
|
return tunnelHTTPConnect(proxyConn, proxyAddress, addr)
|
||||||
br := bufio.NewReader(proxyConn)
|
}
|
||||||
res, err := http.ReadResponse(br, nil)
|
return contextDialer, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createConnectUDSDialer(udsConfig *apiserver.UDSTransport) (utilnet.DialFunc, error) {
|
||||||
|
contextDialer := func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
|
proxyConn, err := net.Dial("unix", udsConfig.UDSName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
proxyConn.Close()
|
return nil, fmt.Errorf("dialing proxy %q failed: %v", udsConfig.UDSName, err)
|
||||||
return nil, fmt.Errorf("reading HTTP response from CONNECT to %s via proxy %s failed: %v",
|
|
||||||
addr, proxyAddress, err)
|
|
||||||
}
|
}
|
||||||
if res.StatusCode != 200 {
|
return tunnelHTTPConnect(proxyConn, udsConfig.UDSName, addr)
|
||||||
proxyConn.Close()
|
}
|
||||||
return nil, fmt.Errorf("proxy error from %s while dialing %s, code %d: %v",
|
return contextDialer, nil
|
||||||
proxyAddress, addr, res.StatusCode, res.Status)
|
}
|
||||||
|
|
||||||
|
func createGRPCUDSDialer(udsName string) (utilnet.DialFunc, error) {
|
||||||
|
contextDialer := func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
|
|
||||||
|
dialOption := grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) {
|
||||||
|
c, err := net.Dial("unix", udsName)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("failed to create connection to uds name %s, error: %v", udsName, err)
|
||||||
|
}
|
||||||
|
return c, err
|
||||||
|
})
|
||||||
|
|
||||||
|
tunnel, err := client.CreateGrpcTunnel(udsName, dialOption, grpc.WithInsecure())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// It's safe to discard the bufio.Reader here and return the
|
proxyConn, err := tunnel.Dial("tcp", addr)
|
||||||
// original TCP conn directly because we only use this for
|
if err != nil {
|
||||||
// TLS, and in TLS the client speaks first, so we know there's
|
return nil, err
|
||||||
// no unbuffered data. But we can double-check.
|
|
||||||
if br.Buffered() > 0 {
|
|
||||||
proxyConn.Close()
|
|
||||||
return nil, fmt.Errorf("unexpected %d bytes of buffered data from CONNECT proxy %q",
|
|
||||||
br.Buffered(), proxyAddress)
|
|
||||||
}
|
}
|
||||||
klog.V(4).Infof("About to proxy request to %s over %s.", addr, proxyAddress)
|
|
||||||
return proxyConn, nil
|
return proxyConn, nil
|
||||||
}
|
}
|
||||||
return contextDialer, nil
|
return contextDialer, nil
|
||||||
|
|
@ -172,17 +218,39 @@ func NewEgressSelector(config *apiserver.EgressSelectorConfiguration) (*EgressSe
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
switch service.Connection.Type {
|
switch service.Connection.ProxyProtocol {
|
||||||
case "http-connect":
|
|
||||||
contextDialer, err := createConnectDialer(service.Connection.HTTPConnect)
|
case apiserver.ProtocolHTTPConnect:
|
||||||
if err != nil {
|
if service.Connection.Transport.UDS != nil {
|
||||||
return nil, fmt.Errorf("failed to create http-connect dialer: %v", err)
|
contextDialer, err := createConnectUDSDialer(service.Connection.Transport.UDS)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create HTTPConnect uds dialer: %v", err)
|
||||||
|
}
|
||||||
|
cs.egressToDialer[name] = contextDialer
|
||||||
|
} else if service.Connection.Transport.TCP != nil {
|
||||||
|
contextDialer, err := createConnectTCPDialer(service.Connection.Transport.TCP)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create HTTPConnect dialer: %v", err)
|
||||||
|
}
|
||||||
|
cs.egressToDialer[name] = contextDialer
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("Either a TCP or UDS transport must be specified")
|
||||||
}
|
}
|
||||||
cs.egressToDialer[name] = contextDialer
|
case apiserver.ProtocolGRPC:
|
||||||
case "direct":
|
if service.Connection.Transport.UDS != nil {
|
||||||
|
grpcContextDialer, err := createGRPCUDSDialer(service.Connection.Transport.UDS.UDSName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create grpc dialer: %v", err)
|
||||||
|
}
|
||||||
|
cs.egressToDialer[name] = grpcContextDialer
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("UDS transport must be specified for GRPC")
|
||||||
|
}
|
||||||
|
case apiserver.ProtocolDirect:
|
||||||
cs.egressToDialer[name] = directDialer
|
cs.egressToDialer[name] = directDialer
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unrecognized service connection type %q", service.Connection.Type)
|
return nil, fmt.Errorf("unrecognized service connection protocol %q", service.Connection.ProxyProtocol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cs, nil
|
return cs, nil
|
||||||
|
|
|
||||||
|
|
@ -53,37 +53,19 @@ func TestEgressSelector(t *testing.T) {
|
||||||
{
|
{
|
||||||
Name: "cluster",
|
Name: "cluster",
|
||||||
Connection: apiserver.Connection{
|
Connection: apiserver.Connection{
|
||||||
Type: "direct",
|
ProxyProtocol: apiserver.ProtocolDirect,
|
||||||
HTTPConnect: &apiserver.HTTPConnectConfig{
|
|
||||||
URL: "",
|
|
||||||
CABundle: "",
|
|
||||||
ClientKey: "",
|
|
||||||
ClientCert: "",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "master",
|
Name: "master",
|
||||||
Connection: apiserver.Connection{
|
Connection: apiserver.Connection{
|
||||||
Type: "direct",
|
ProxyProtocol: apiserver.ProtocolDirect,
|
||||||
HTTPConnect: &apiserver.HTTPConnectConfig{
|
|
||||||
URL: "",
|
|
||||||
CABundle: "",
|
|
||||||
ClientKey: "",
|
|
||||||
ClientCert: "",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "etcd",
|
Name: "etcd",
|
||||||
Connection: apiserver.Connection{
|
Connection: apiserver.Connection{
|
||||||
Type: "direct",
|
ProxyProtocol: apiserver.ProtocolDirect,
|
||||||
HTTPConnect: &apiserver.HTTPConnectConfig{
|
|
||||||
URL: "",
|
|
||||||
CABundle: "",
|
|
||||||
ClientKey: "",
|
|
||||||
ClientCert: "",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue