mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Plumb service port, URL port to webhook client auth resolution
This commit is contained in:
parent
2f5dde7672
commit
d127042cb8
@ -52,7 +52,7 @@ type authenticationInfoResolver struct {
|
|||||||
cacheMisses *int32
|
cacheMisses *int32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *authenticationInfoResolver) ClientConfigFor(server string) (*rest.Config, error) {
|
func (a *authenticationInfoResolver) ClientConfigFor(hostPort string) (*rest.Config, error) {
|
||||||
atomic.AddInt32(a.cacheMisses, 1)
|
atomic.AddInt32(a.cacheMisses, 1)
|
||||||
return a.restConfig, nil
|
return a.restConfig, nil
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,9 @@ package webhook
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -40,17 +42,17 @@ func NewDefaultAuthenticationInfoResolverWrapper(
|
|||||||
|
|
||||||
webhookAuthResolverWrapper := func(delegate AuthenticationInfoResolver) AuthenticationInfoResolver {
|
webhookAuthResolverWrapper := func(delegate AuthenticationInfoResolver) AuthenticationInfoResolver {
|
||||||
return &AuthenticationInfoResolverDelegator{
|
return &AuthenticationInfoResolverDelegator{
|
||||||
ClientConfigForFunc: func(server string) (*rest.Config, error) {
|
ClientConfigForFunc: func(hostPort string) (*rest.Config, error) {
|
||||||
if server == "kubernetes.default.svc" {
|
if hostPort == "kubernetes.default.svc:443" {
|
||||||
return kubeapiserverClientConfig, nil
|
return kubeapiserverClientConfig, nil
|
||||||
}
|
}
|
||||||
return delegate.ClientConfigFor(server)
|
return delegate.ClientConfigFor(hostPort)
|
||||||
},
|
},
|
||||||
ClientConfigForServiceFunc: func(serviceName, serviceNamespace string) (*rest.Config, error) {
|
ClientConfigForServiceFunc: func(serviceName, serviceNamespace string, servicePort int) (*rest.Config, error) {
|
||||||
if serviceName == "kubernetes" && serviceNamespace == corev1.NamespaceDefault {
|
if serviceName == "kubernetes" && serviceNamespace == corev1.NamespaceDefault && servicePort == 443 {
|
||||||
return kubeapiserverClientConfig, nil
|
return kubeapiserverClientConfig, nil
|
||||||
}
|
}
|
||||||
ret, err := delegate.ClientConfigForService(serviceName, serviceNamespace)
|
ret, err := delegate.ClientConfigForService(serviceName, serviceNamespace, servicePort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -67,27 +69,27 @@ func NewDefaultAuthenticationInfoResolverWrapper(
|
|||||||
// AuthenticationInfoResolver builds rest.Config base on the server or service
|
// AuthenticationInfoResolver builds rest.Config base on the server or service
|
||||||
// name and service namespace.
|
// name and service namespace.
|
||||||
type AuthenticationInfoResolver interface {
|
type AuthenticationInfoResolver interface {
|
||||||
// ClientConfigFor builds rest.Config based on the server.
|
// ClientConfigFor builds rest.Config based on the hostPort.
|
||||||
ClientConfigFor(server string) (*rest.Config, error)
|
ClientConfigFor(hostPort string) (*rest.Config, error)
|
||||||
// ClientConfigForService builds rest.Config based on the serviceName and
|
// ClientConfigForService builds rest.Config based on the serviceName and
|
||||||
// serviceNamespace.
|
// serviceNamespace.
|
||||||
ClientConfigForService(serviceName, serviceNamespace string) (*rest.Config, error)
|
ClientConfigForService(serviceName, serviceNamespace string, servicePort int) (*rest.Config, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AuthenticationInfoResolverDelegator implements AuthenticationInfoResolver.
|
// AuthenticationInfoResolverDelegator implements AuthenticationInfoResolver.
|
||||||
type AuthenticationInfoResolverDelegator struct {
|
type AuthenticationInfoResolverDelegator struct {
|
||||||
ClientConfigForFunc func(server string) (*rest.Config, error)
|
ClientConfigForFunc func(hostPort string) (*rest.Config, error)
|
||||||
ClientConfigForServiceFunc func(serviceName, serviceNamespace string) (*rest.Config, error)
|
ClientConfigForServiceFunc func(serviceName, serviceNamespace string, servicePort int) (*rest.Config, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClientConfigFor returns client config for given server.
|
// ClientConfigFor returns client config for given hostPort.
|
||||||
func (a *AuthenticationInfoResolverDelegator) ClientConfigFor(server string) (*rest.Config, error) {
|
func (a *AuthenticationInfoResolverDelegator) ClientConfigFor(hostPort string) (*rest.Config, error) {
|
||||||
return a.ClientConfigForFunc(server)
|
return a.ClientConfigForFunc(hostPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClientConfigForService returns client config for given service.
|
// ClientConfigForService returns client config for given service.
|
||||||
func (a *AuthenticationInfoResolverDelegator) ClientConfigForService(serviceName, serviceNamespace string) (*rest.Config, error) {
|
func (a *AuthenticationInfoResolverDelegator) ClientConfigForService(serviceName, serviceNamespace string, servicePort int) (*rest.Config, error) {
|
||||||
return a.ClientConfigForServiceFunc(serviceName, serviceNamespace)
|
return a.ClientConfigForServiceFunc(serviceName, serviceNamespace, servicePort)
|
||||||
}
|
}
|
||||||
|
|
||||||
type defaultAuthenticationInfoResolver struct {
|
type defaultAuthenticationInfoResolver struct {
|
||||||
@ -113,12 +115,12 @@ func NewDefaultAuthenticationInfoResolver(kubeconfigFile string) (Authentication
|
|||||||
return &defaultAuthenticationInfoResolver{kubeconfig: clientConfig}, nil
|
return &defaultAuthenticationInfoResolver{kubeconfig: clientConfig}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *defaultAuthenticationInfoResolver) ClientConfigFor(server string) (*rest.Config, error) {
|
func (c *defaultAuthenticationInfoResolver) ClientConfigFor(hostPort string) (*rest.Config, error) {
|
||||||
return c.clientConfig(server)
|
return c.clientConfig(hostPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *defaultAuthenticationInfoResolver) ClientConfigForService(serviceName, serviceNamespace string) (*rest.Config, error) {
|
func (c *defaultAuthenticationInfoResolver) ClientConfigForService(serviceName, serviceNamespace string, servicePort int) (*rest.Config, error) {
|
||||||
return c.clientConfig(serviceName + "." + serviceNamespace + ".svc")
|
return c.clientConfig(net.JoinHostPort(serviceName+"."+serviceNamespace+".svc", strconv.Itoa(servicePort)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *defaultAuthenticationInfoResolver) clientConfig(target string) (*rest.Config, error) {
|
func (c *defaultAuthenticationInfoResolver) clientConfig(target string) (*rest.Config, error) {
|
||||||
@ -154,7 +156,7 @@ func (c *defaultAuthenticationInfoResolver) clientConfig(target string) (*rest.C
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if we're trying to hit the kube-apiserver and there wasn't an explicit config, use the in-cluster config
|
// if we're trying to hit the kube-apiserver and there wasn't an explicit config, use the in-cluster config
|
||||||
if target == "kubernetes.default.svc" {
|
if target == "kubernetes.default.svc:443" {
|
||||||
// if we can find an in-cluster-config use that. If we can't, fall through.
|
// if we can find an in-cluster-config use that. If we can't, fall through.
|
||||||
inClusterConfig, err := rest.InClusterConfig()
|
inClusterConfig, err := rest.InClusterConfig()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/hashicorp/golang-lru"
|
"github.com/hashicorp/golang-lru"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
@ -151,13 +152,20 @@ func (cm *ClientManager) HookClient(cc ClientConfig) (*rest.RESTClient, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cc.Service != nil {
|
if cc.Service != nil {
|
||||||
restConfig, err := cm.authInfoResolver.ClientConfigForService(cc.Service.Name, cc.Service.Namespace)
|
port := cc.Service.Port
|
||||||
|
if port == 0 {
|
||||||
|
// Default to port 443 if no service port is specified
|
||||||
|
port = 443
|
||||||
|
}
|
||||||
|
|
||||||
|
restConfig, err := cm.authInfoResolver.ClientConfigForService(cc.Service.Name, cc.Service.Namespace, int(port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
cfg := rest.CopyConfig(restConfig)
|
cfg := rest.CopyConfig(restConfig)
|
||||||
serverName := cc.Service.Name + "." + cc.Service.Namespace + ".svc"
|
serverName := cc.Service.Name + "." + cc.Service.Namespace + ".svc"
|
||||||
host := serverName + ":443"
|
|
||||||
|
host := net.JoinHostPort(serverName, strconv.Itoa(int(port)))
|
||||||
cfg.Host = "https://" + host
|
cfg.Host = "https://" + host
|
||||||
cfg.APIPath = cc.Service.Path
|
cfg.APIPath = cc.Service.Path
|
||||||
// Set the server name if not already set
|
// Set the server name if not already set
|
||||||
@ -172,10 +180,6 @@ func (cm *ClientManager) HookClient(cc ClientConfig) (*rest.RESTClient, error) {
|
|||||||
}
|
}
|
||||||
cfg.Dial = func(ctx context.Context, network, addr string) (net.Conn, error) {
|
cfg.Dial = func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
if addr == host {
|
if addr == host {
|
||||||
port := cc.Service.Port
|
|
||||||
if port == 0 {
|
|
||||||
port = 443
|
|
||||||
}
|
|
||||||
u, err := cm.serviceResolver.ResolveEndpoint(cc.Service.Namespace, cc.Service.Name, port)
|
u, err := cm.serviceResolver.ResolveEndpoint(cc.Service.Namespace, cc.Service.Name, port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -197,7 +201,13 @@ func (cm *ClientManager) HookClient(cc ClientConfig) (*rest.RESTClient, error) {
|
|||||||
return nil, &ErrCallingWebhook{WebhookName: cc.Name, Reason: fmt.Errorf("Unparsable URL: %v", err)}
|
return nil, &ErrCallingWebhook{WebhookName: cc.Name, Reason: fmt.Errorf("Unparsable URL: %v", err)}
|
||||||
}
|
}
|
||||||
|
|
||||||
restConfig, err := cm.authInfoResolver.ClientConfigFor(u.Host)
|
hostPort := u.Host
|
||||||
|
if len(u.Port()) == 0 {
|
||||||
|
// Default to port 443 if no port is specified
|
||||||
|
hostPort = net.JoinHostPort(hostPort, "443")
|
||||||
|
}
|
||||||
|
|
||||||
|
restConfig, err := cm.authInfoResolver.ClientConfigFor(hostPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user