From 4c1e892d88e6d978248f949ec5a806e88133553f Mon Sep 17 00:00:00 2001 From: Markus Lehtonen Date: Thu, 31 Jan 2019 15:54:06 +0200 Subject: [PATCH] nfd-master: implement --verify-node-name Make NodeName based authorization of the workers optional (off by default). This makes it possible for all nfd-worker pods in the cluster to use one shared secret, making NFD deployment much easier. However, this also opens a way for nfd-workers to label other nodes (than what it is running on), too. --- cmd/nfd-master/main.go | 49 ++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/cmd/nfd-master/main.go b/cmd/nfd-master/main.go index b1681c3f1..b2904a351 100644 --- a/cmd/nfd-master/main.go +++ b/cmd/nfd-master/main.go @@ -73,6 +73,7 @@ type Args struct { labelWhiteList *regexp.Regexp noPublish bool port int + verifyNodeName bool } func main() { @@ -145,6 +146,7 @@ func argsParse(argv []string) (Args, error) { Usage: %s [--no-publish] [--label-whitelist=] [--port=] [--ca-file=] [--cert-file=] [--key-file=] + [--verify-node-name] %s -h | --help %s --version @@ -159,6 +161,9 @@ func argsParse(argv []string) (Args, error) { [Default: ] --key-file= Private key matching --cert-file [Default: ] + --verify-node-name Verify worker node name against CN from the TLS + certificate. Only has effect when TLS authentication + has been enabled. --no-publish Do not publish feature labels --label-whitelist= Regular expression to filter label names to publish to the Kubernetes API server. [Default: ]`, @@ -185,6 +190,7 @@ func argsParse(argv []string) (Args, error) { if err != nil { return args, fmt.Errorf("error parsing whitelist regex (%s): %s", arguments["--label-whitelist"], err) } + args.verifyNodeName = arguments["--verify-node-name"].(bool) // Check TLS related args if args.certFile != "" || args.keyFile != "" || args.caFile != "" { @@ -242,28 +248,29 @@ type labelerServer struct { // Service SetLabels func (s *labelerServer) SetLabels(c context.Context, r *pb.SetLabelsRequest) (*pb.SetLabelsReply, error) { - // Client authorization. - // Check that the node name matches the CN from the TLS cert - client, ok := peer.FromContext(c) - if !ok { - stderrLogger.Printf("gRPC request error: failed to get peer (client)") - return &pb.SetLabelsReply{}, fmt.Errorf("failed to get peer (client)") + if s.args.verifyNodeName { + // Client authorization. + // Check that the node name matches the CN from the TLS cert + client, ok := peer.FromContext(c) + if !ok { + stderrLogger.Printf("gRPC request error: failed to get peer (client)") + return &pb.SetLabelsReply{}, fmt.Errorf("failed to get peer (client)") + } + tlsAuth, ok := client.AuthInfo.(credentials.TLSInfo) + if !ok { + stderrLogger.Printf("gRPC request error: incorrect client credentials from '%v'", client.Addr) + return &pb.SetLabelsReply{}, fmt.Errorf("incorrect client credentials") + } + if len(tlsAuth.State.VerifiedChains) == 0 || len(tlsAuth.State.VerifiedChains[0]) == 0 { + stderrLogger.Printf("gRPC request error: client certificate verification for '%v' failed", client.Addr) + return &pb.SetLabelsReply{}, fmt.Errorf("client certificate verification failed") + } + cn := tlsAuth.State.VerifiedChains[0][0].Subject.CommonName + if cn != r.NodeName { + stderrLogger.Printf("gRPC request error: authorization for %v failed: cert valid for '%s', requested node name '%s'", client.Addr, cn, r.NodeName) + return &pb.SetLabelsReply{}, fmt.Errorf("request authorization failed: cert valid for '%s', requested node name '%s'", cn, r.NodeName) + } } - tlsAuth, ok := client.AuthInfo.(credentials.TLSInfo) - if !ok { - stderrLogger.Printf("gRPC request error: incorrect client credentials from '%v'", client.Addr) - return &pb.SetLabelsReply{}, fmt.Errorf("incorrect client credentials") - } - if len(tlsAuth.State.VerifiedChains) == 0 || len(tlsAuth.State.VerifiedChains[0]) == 0 { - stderrLogger.Printf("gRPC request error: client certificate verification for '%v' failed", client.Addr) - return &pb.SetLabelsReply{}, fmt.Errorf("client certificate verification failed") - } - cn := tlsAuth.State.VerifiedChains[0][0].Subject.CommonName - if cn != r.NodeName { - stderrLogger.Printf("gRPC request error: authorization for %v failed: cert valid for '%s', requested node name '%s'", client.Addr, cn, r.NodeName) - return &pb.SetLabelsReply{}, fmt.Errorf("request authorization failed: cert valid for '%s', requested node name '%s'", cn, r.NodeName) - } - stdoutLogger.Printf("REQUEST Node: %s NFD-version: %s Labels: %s", r.NodeName, r.NfdVersion, r.Labels) if !s.args.noPublish {