Commit ab004371 authored by Brad Davidson's avatar Brad Davidson Committed by Brad Davidson

Add client certificate authentication support to core Authenticator

This is required to make the websocket tunnel server functional on etcd-only nodes, and will save some code on the RKE2 side once pulled through. Signed-off-by: 's avatarBrad Davidson <brad.davidson@rancher.com> (cherry picked from commit af0b496e)
parent 8fdd9a0d
package control
package authenticator
import (
"strings"
"github.com/rancher/k3s/pkg/authenticator/basicauth"
"github.com/rancher/k3s/pkg/authenticator/passwordfile"
"k8s.io/apiserver/pkg/authentication/authenticator"
"k8s.io/apiserver/pkg/authentication/group"
"k8s.io/apiserver/pkg/authentication/request/union"
"k8s.io/apiserver/pkg/authentication/request/x509"
"k8s.io/apiserver/pkg/server/dynamiccertificates"
)
func basicAuthenticator(basicAuthFile string) (authenticator.Request, error) {
if basicAuthFile == "" {
return nil, nil
func FromArgs(args []string) (authenticator.Request, error) {
var authenticators []authenticator.Request
basicFile := getArg("--basic-auth-file", args)
if basicFile != "" {
basicAuthenticator, err := passwordfile.NewCSV(basicFile)
if err != nil {
return nil, err
}
authenticators = append(authenticators, basicauth.New(basicAuthenticator))
}
clientCA := getArg("--client-ca-file", args)
if clientCA != "" {
ca, err := dynamiccertificates.NewDynamicCAContentFromFile("client-ca", clientCA)
if err != nil {
return nil, err
}
authenticators = append(authenticators, x509.NewDynamic(ca.VerifyOptions, x509.CommonNameUserConversion))
}
basicAuthenticator, err := passwordfile.NewCSV(basicAuthFile)
if err != nil {
return nil, err
return Combine(authenticators...), nil
}
func getArg(key string, args []string) string {
for _, arg := range args {
if !strings.HasPrefix(arg, key) {
continue
}
return strings.SplitN(arg, "=", 2)[1]
}
return basicauth.New(basicAuthenticator), nil
return ""
}
func combineAuthenticators(auths ...authenticator.Request) authenticator.Request {
func Combine(auths ...authenticator.Request) authenticator.Request {
var authenticators []authenticator.Request
for _, auth := range auths {
if auth != nil {
......
......@@ -20,17 +20,16 @@ import (
"errors"
"net/http"
localAuthenticator "github.com/rancher/k3s/pkg/authenticator"
"k8s.io/apiserver/pkg/authentication/authenticator"
)
// Authenticator authenticates requests using basic auth
type Authenticator struct {
auth localAuthenticator.Password
auth Password
}
// New returns a request authenticator that validates credentials using the provided password authenticator
func New(auth localAuthenticator.Password) *Authenticator {
func New(auth Password) *Authenticator {
return &Authenticator{auth}
}
......
......@@ -11,7 +11,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package authenticator
package basicauth
import (
"context"
......
......@@ -12,6 +12,7 @@ import (
"time"
"github.com/pkg/errors"
"github.com/rancher/k3s/pkg/authenticator"
"github.com/rancher/k3s/pkg/cluster"
"github.com/rancher/k3s/pkg/daemons/config"
"github.com/rancher/k3s/pkg/daemons/control/deps"
......@@ -50,11 +51,15 @@ func Server(ctx context.Context, cfg *config.Control) error {
cfg.Runtime.Tunnel = setupTunnel()
proxyutil.DisableProxyHostnameCheck = true
basicAuth, err := basicAuthenticator(cfg.Runtime.PasswdFile)
authArgs := []string{
"--basic-auth-file=" + cfg.Runtime.PasswdFile,
"--client-ca-file=" + cfg.Runtime.ClientCA,
}
auth, err := authenticator.FromArgs(authArgs)
if err != nil {
return err
}
cfg.Runtime.Authenticator = basicAuth
cfg.Runtime.Authenticator = auth
if !cfg.DisableAPIServer {
go waitForAPIServerHandlers(ctx, cfg.Runtime)
......@@ -429,7 +434,7 @@ func waitForAPIServerHandlers(ctx context.Context, runtime *config.ControlRuntim
if err != nil {
logrus.Fatalf("Failed to get request handlers from apiserver: %v", err)
}
runtime.Authenticator = combineAuthenticators(runtime.Authenticator, auth)
runtime.Authenticator = authenticator.Combine(runtime.Authenticator, auth)
runtime.APIServer = handler
}
......
......@@ -9,13 +9,20 @@ import (
"github.com/rancher/remotedialer"
"github.com/rancher/wrangler/pkg/kv"
"github.com/sirupsen/logrus"
utilnet "k8s.io/apimachinery/pkg/util/net"
"k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/kubernetes/cmd/kube-apiserver/app"
)
func loggingErrorWriter(rw http.ResponseWriter, req *http.Request, code int, err error) {
logrus.Debugf("remoteDialer error: %d %v", code, err)
rw.WriteHeader(code)
rw.Write([]byte(err.Error()))
}
func setupTunnel() http.Handler {
tunnelServer := remotedialer.New(authorizer, remotedialer.DefaultErrorWriter)
tunnelServer := remotedialer.New(authorizer, loggingErrorWriter)
setupProxyDialer(tunnelServer)
return tunnelServer
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment