Merge pull request #64575 from immutableT/in-memory-domain-socket

Automatic merge from submit-queue (batch tested with PRs 64575, 65120, 65463, 65434, 65522). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Add support for Linux Abstract Socket Namespace for KMS provider plugin.

**What this PR does / why we need it**:
Currently, kube-apiserver and kms-plugin interact via a Unix Domain Socket. The current implementation, assumes that such a Domain Socket is supported via a socket file, which is in turn is supported via a volume shared between kube-apiserver and kms-plugin containers.
However, Linux supports Abstract Socket Namespace, where a socket does not need to be back-up by a file. In golang, such sockets are created by prefixing a socket's name with @.

Benefits of using Linux Abstract Socket Namespace:
1. Don't need to worry about possible collisions with existing files.
2. Simpler configuration of master's manifest - no need to setup a shared volume between kube-apiserver and kms-plugin containers.
3. Don't need to remember to unlink the socket when KMS Plugin shuts down.
4. Creates a possibility to run KMS Plugin without access to file system.

This PR adds the ability to define a KMS endpoint as: unix:///@kms-provider.sock

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
Fixes #

**Special notes for your reviewer**:

**Release note**:

```release-note
NONE
```
pull/8/head
Kubernetes Submit Queue 2018-06-28 02:20:09 -07:00 committed by GitHub
commit 75c8b56dcb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 18 additions and 56 deletions

View File

@ -36,52 +36,42 @@ go_test(
] + select({
"@io_bazel_rules_go//go/platform:android": [
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library",
],
"@io_bazel_rules_go//go/platform:darwin": [
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library",
],
"@io_bazel_rules_go//go/platform:linux": [
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library",
],
"@io_bazel_rules_go//go/platform:nacl": [
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library",
],
"@io_bazel_rules_go//go/platform:plan9": [
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library",
],
"@io_bazel_rules_go//go/platform:solaris": [
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library",
],
"//conditions:default": [],

View File

@ -22,6 +22,7 @@ import (
"fmt"
"net"
"net/url"
"strings"
"time"
"github.com/golang/glog"
@ -93,6 +94,15 @@ func parseEndpoint(endpoint string) (string, error) {
if u.Scheme != unixProtocol {
return "", fmt.Errorf("unsupported scheme %q for remote KMS provider", u.Scheme)
}
// Linux abstract namespace socket - no physical file required
// Warning: Linux Abstract sockets have not concept of ACL (unlike traditional file based sockets).
// However, Linux Abstract sockets are subject to Linux networking namespace, so will only be accessible to
// containers within the same pod (unless host networking is used).
if strings.HasPrefix(u.Path, "/@") {
return strings.TrimPrefix(u.Path, "/"), nil
}
return u.Path, nil
}

View File

@ -24,19 +24,16 @@ import (
"encoding/base64"
"fmt"
"net"
"os"
"reflect"
"testing"
"google.golang.org/grpc"
"golang.org/x/sys/unix"
kmsapi "k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1"
)
const (
sockFile = "/tmp/kms-provider.sock"
endpoint = "unix:///@kms-socket.sock"
)
// Normal encryption and decryption operation.
@ -49,7 +46,6 @@ func TestGRPCService(t *testing.T) {
defer stopTestKMSProvider(server)
// Create the gRPC client service.
endpoint := unixProtocol + "://" + sockFile
service, err := NewGRPCService(endpoint)
if err != nil {
t.Fatalf("failed to create envelope service, error: %v", err)
@ -95,8 +91,8 @@ func TestInvalidConfiguration(t *testing.T) {
}{
{"emptyConfiguration", kmsapiVersion, ""},
{"invalidScheme", kmsapiVersion, "tcp://localhost:6060"},
{"unavailableEndpoint", kmsapiVersion, unixProtocol + "://" + sockFile + ".nonexist"},
{"invalidAPIVersion", "invalidVersion", unixProtocol + "://" + sockFile},
{"unavailableEndpoint", kmsapiVersion, unixProtocol + ":///kms-socket.nonexist"},
{"invalidAPIVersion", "invalidVersion", endpoint},
}
for _, testCase := range invalidConfigs {
@ -114,10 +110,10 @@ func TestInvalidConfiguration(t *testing.T) {
// Start the gRPC server that listens on unix socket.
func startTestKMSProvider() (*grpc.Server, error) {
if err := cleanSockFile(); err != nil {
return nil, err
sockFile, err := parseEndpoint(endpoint)
if err != nil {
return nil, fmt.Errorf("failed to parse endpoint:%q, error %v", endpoint, err)
}
listener, err := net.Listen(unixProtocol, sockFile)
if err != nil {
return nil, fmt.Errorf("failed to listen on the unix socket, error: %v", err)
@ -131,15 +127,6 @@ func startTestKMSProvider() (*grpc.Server, error) {
func stopTestKMSProvider(server *grpc.Server) {
server.Stop()
cleanSockFile()
}
func cleanSockFile() error {
err := unix.Unlink(sockFile)
if err != nil && !os.IsNotExist(err) {
return fmt.Errorf("failed to delete the socket file, error: %v", err)
}
return nil
}
// Fake gRPC sever for remote KMS provider.

View File

@ -131,61 +131,51 @@ go_library(
"@io_bazel_rules_go//go/platform:android": [
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library",
],
"@io_bazel_rules_go//go/platform:darwin": [
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library",
],
"@io_bazel_rules_go//go/platform:linux": [
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library",
],
"@io_bazel_rules_go//go/platform:nacl": [
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library",
],
"@io_bazel_rules_go//go/platform:plan9": [
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library",
],
"@io_bazel_rules_go//go/platform:solaris": [
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library",
],
"//conditions:default": [],

View File

@ -23,9 +23,7 @@ import (
"encoding/base64"
"fmt"
"net"
"os"
"golang.org/x/sys/unix"
"google.golang.org/grpc"
"github.com/golang/glog"
@ -34,7 +32,7 @@ import (
const (
kmsAPIVersion = "v1beta1"
sockFile = "/tmp/kms-provider.sock"
sockFile = "@kms-provider.sock"
unixProtocol = "unix"
)
@ -49,10 +47,6 @@ type base64Plugin struct {
}
func NewBase64Plugin() (*base64Plugin, error) {
if err := cleanSockFile(); err != nil {
return nil, err
}
listener, err := net.Listen(unixProtocol, sockFile)
if err != nil {
return nil, fmt.Errorf("failed to listen on the unix socket, error: %v", err)
@ -75,7 +69,6 @@ func NewBase64Plugin() (*base64Plugin, error) {
func (s *base64Plugin) cleanUp() {
s.grpcServer.Stop()
s.listener.Close()
cleanSockFile()
}
var testProviderAPIVersion = kmsAPIVersion
@ -105,11 +98,3 @@ func (s *base64Plugin) Encrypt(ctx context.Context, request *kmsapi.EncryptReque
return &kmsapi.EncryptResponse{Cipher: buf}, nil
}
func cleanSockFile() error {
err := unix.Unlink(sockFile)
if err != nil && !os.IsNotExist(err) {
return fmt.Errorf("failed to delete the socket file, error: %v", err)
}
return nil
}

View File

@ -48,7 +48,7 @@ resources:
- kms:
name: grpc-kms-provider
cachesize: 1000
endpoint: unix:///tmp/kms-provider.sock
endpoint: unix:///@kms-provider.sock
`
)