Skip to content

Commit

Permalink
Merge pull request #377 from adisky/barbican-kms-final
Browse files Browse the repository at this point in the history
Implement Barbican as KMS provider for kubernetes
  • Loading branch information
k8s-ci-robot committed Dec 24, 2018
2 parents cc82c7f + a421032 commit bc52663
Show file tree
Hide file tree
Showing 13 changed files with 585 additions and 5 deletions.
12 changes: 9 additions & 3 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 17 additions & 2 deletions Makefile
Expand Up @@ -59,7 +59,7 @@ endif
depend-update: work
dep ensure -update -v

build: openstack-cloud-controller-manager cinder-provisioner cinder-flex-volume-driver cinder-csi-plugin k8s-keystone-auth client-keystone-auth octavia-ingress-controller manila-provisioner
build: openstack-cloud-controller-manager cinder-provisioner cinder-flex-volume-driver cinder-csi-plugin k8s-keystone-auth client-keystone-auth octavia-ingress-controller manila-provisioner barbican-kms-plugin

openstack-cloud-controller-manager: depend $(SOURCES)
CGO_ENABLED=0 GOOS=$(GOOS) go build \
Expand Down Expand Up @@ -109,6 +109,12 @@ manila-provisioner: depend $(SOURCES)
-o manila-provisioner \
cmd/manila-provisioner/main.go

barbican-kms-plugin: depend $(SOURCES)
cd $(DEST) && CGO_ENABLED=0 GOOS=$(GOOS) go build \
-ldflags $(LDFLAGS) \
-o barbican-kms-plugin \
cmd/barbican-kms-plugin/main.go

test: unit functional

check: depend fmt vet lint import-boss
Expand Down Expand Up @@ -193,7 +199,7 @@ realclean: clean
shell:
$(SHELL) -i

images: image-controller-manager image-flex-volume-driver image-provisioner image-csi-plugin image-k8s-keystone-auth image-octavia-ingress-controller image-manila-provisioner
images: image-controller-manager image-flex-volume-driver image-provisioner image-csi-plugin image-k8s-keystone-auth image-octavia-ingress-controller image-manila-provisioner image-kms-plugin

image-controller-manager: depend openstack-cloud-controller-manager
ifeq ($(GOOS),linux)
Expand Down Expand Up @@ -258,6 +264,15 @@ else
$(error Please set GOOS=linux for building the image)
endif

image-kms-plugin: depend barbican-kms-plugin
ifeq ($(GOOS), linux)
cp barbican-kms-plugin cluster/images/barbican-kms-plugin
docker build -t $(REGISTRY)/barbican-kms-plugin:$(VERSION) cluster/images/barbican-kms-plugin
rm cluster/images/barbican-kms-plugin/barbican-kms-plugin
else
$(error Please set GOOS=linux for building the image)
endif

upload-images: images
@echo "push images to $(REGISTRY)"
docker login -u="$(DOCKER_USERNAME)" -p="$(DOCKER_PASSWORD)";
Expand Down
7 changes: 7 additions & 0 deletions cluster/images/barbican-kms-plugin/Dockerfile
@@ -0,0 +1,7 @@
FROM alpine:3.7
LABEL maintainers="Kubernetes Authors"
LABEL description="Barbican KMS Plugin"

ADD barbican-kms-plugin /bin/

CMD ["sh", "-c", "/bin/barbican-kms-plugin --socketpath ${socketpath} --cloud-config ${cloudconfig}"]
67 changes: 67 additions & 0 deletions cmd/barbican-kms-plugin/main.go
@@ -0,0 +1,67 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
"flag"
"fmt"
"os"
"os/signal"

"github.com/spf13/cobra"
"golang.org/x/sys/unix"
"k8s.io/cloud-provider-openstack/pkg/kms/server"
)

var (
socketpath string
cloudconfig string
)

func init() {
flag.Set("logtostderr", "true")
}

func main() {
flag.CommandLine.Parse([]string{})

cmd := &cobra.Command{
Use: "barbican-kms-plugin",
Short: "Barbican KMS plugin for kubernetes",
RunE: func(cmd *cobra.Command, args []string) error {
sigchan := make(chan os.Signal, 1)
signal.Notify(sigchan, unix.SIGTERM, unix.SIGINT)
err := server.Run(cloudconfig, socketpath, sigchan)
return err
},
}

cmd.Flags().AddGoFlagSet(flag.CommandLine)

cmd.PersistentFlags().StringVar(&socketpath, "socketpath", "", "Barbican KMS Plugin unix socket endpoint")
cmd.MarkPersistentFlagRequired("socketpath")

cmd.PersistentFlags().StringVar(&cloudconfig, "cloud-config", "", "Barbican KMS Plugin cloud config")
cmd.MarkPersistentFlagRequired("cloud-config")

if err := cmd.Execute(); err != nil {
fmt.Fprintf(os.Stderr, "%s", err.Error())
os.Exit(1)
}

os.Exit(0)
}
11 changes: 11 additions & 0 deletions manifests/barbican-kms/encryption-config.yaml
@@ -0,0 +1,11 @@
kind: EncryptionConfig
apiVersion: v1
resources:
- resources:
- secrets
providers:
- kms:
name : barbican
endpoint: unix:///var/lib/kms/kms.sock
cachesize: 20
- identity: {}
24 changes: 24 additions & 0 deletions manifests/barbican-kms/pod.yaml
@@ -0,0 +1,24 @@
apiVersion: v1
kind: Pod
metadata:
name: barbican-kms
spec:
containers:
- name: barbican-kms
image: docker.io/k8scloudprovider/barbican-kms-plugin:latest
args:
- "--socketpath=/kms/kms.sock"
- "--cloud-config=/etc/kubernetes/cloud-config"
volumeMounts:
- name: cloud-config
mountPath: /etc/kubernetes/
- name: socket-dir
mountPath: /kms/
volumes:
- name: config
hostPath:
path: /etc/kubernetes
- name: socket-dir
hostPath:
path: /var/lib/kms/
type: DirectoryOrCreate
95 changes: 95 additions & 0 deletions pkg/kms/barbican/barbican.go
@@ -0,0 +1,95 @@
package barbican

import (
"github.com/golang/glog"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack"
"github.com/gophercloud/gophercloud/openstack/keymanager/v1/secrets"
)

type BarbicanService interface {
GetSecret(cfg Config) ([]byte, error)
}

type KMSOpts struct {
KeyID string `gcfg:"key-id"`
}

//Config to read config options
type Config struct {
Global struct {
AuthURL string `gcfg:"auth-url"`
Username string
UserID string `gcfg:"user-id"`
Password string
TenantID string `gcfg:"tenant-id"`
TenantName string `gcfg:"tenant-name"`
DomainID string `gcfg:"domain-id"`
DomainName string `gcfg:"domain-name"`
Region string
}
KeyManager KMSOpts
}

// Barbican is gophercloud service client
type Barbican struct {
}

func (cfg Config) toAuthOptions() gophercloud.AuthOptions {
return gophercloud.AuthOptions{
IdentityEndpoint: cfg.Global.AuthURL,
Username: cfg.Global.Username,
UserID: cfg.Global.UserID,
Password: cfg.Global.Password,
TenantID: cfg.Global.TenantID,
TenantName: cfg.Global.TenantName,
DomainID: cfg.Global.DomainID,
DomainName: cfg.Global.DomainName,

// Persistent service, so we need to be able to renew tokens.
AllowReauth: true,
}
}

// NewBarbicanClient creates new BarbicanClient
func newBarbicanClient(cfg Config) (client *gophercloud.ServiceClient, err error) {

provider, err := openstack.AuthenticatedClient(cfg.toAuthOptions())

if err != nil {
return nil, err
}

client, err = openstack.NewKeyManagerV1(provider, gophercloud.EndpointOpts{
Region: cfg.Global.Region,
})
if err != nil {
return nil, err
}

return client, nil
}

// GetSecret gets unencrypted secret
func (barbican *Barbican) GetSecret(cfg Config) ([]byte, error) {

client, err := newBarbicanClient(cfg)

keyID := cfg.KeyManager.KeyID

if err != nil {
glog.V(4).Infof("Failed to get Barbican client %v: ", err)
return nil, err
}

opts := secrets.GetPayloadOpts{
PayloadContentType: "application/octet-stream",
}

key, err := secrets.GetPayload(client, keyID, opts).Extract()
if err != nil {
return nil, err
}

return key, nil
}
11 changes: 11 additions & 0 deletions pkg/kms/barbican/fake_barbican.go
@@ -0,0 +1,11 @@
package barbican

import "encoding/hex"

type FakeBarbican struct {
}

func (client *FakeBarbican) GetSecret(cfg Config) ([]byte, error) {
return hex.DecodeString("6368616e676520746869732070617373")

}
54 changes: 54 additions & 0 deletions pkg/kms/client/client.go
@@ -0,0 +1,54 @@
package main

import (
"fmt"
"golang.org/x/net/context"
"google.golang.org/grpc"
pb "k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1"
"os"
)

//This client is for test purpose only, Kubernetes api server will call to kms plugin grpc server

func main() {

connection, err := grpc.Dial("unix:///var/lib/kms/kms.sock", grpc.WithInsecure())
defer connection.Close()
if err != nil {
fmt.Printf("\nConnection to KMS plugin failed, error: %v", err)
}

kmsClient := pb.NewKeyManagementServiceClient(connection)
request := &pb.VersionRequest{Version: "v1beta1"}
_, err = kmsClient.Version(context.TODO(), request)

if err != nil {
fmt.Printf("\nError in getting version from KMS Plugin: %v", err)
}

secretBytes := []byte("mypassword")

//Encryption Request to KMS Plugin
encRequest := &pb.EncryptRequest{
Version: "v1beta1",
Plain: secretBytes}
encResponse, err := kmsClient.Encrypt(context.TODO(), encRequest)

if err != nil {
fmt.Printf("\nEncrypt Request Failed: %v", err)
os.Exit(1)
}

cipher := string(encResponse.Cipher)
fmt.Println("cipher:", cipher)

//Decryption Request to KMS plugin
decRequest := &pb.DecryptRequest{
Version: "v1beta1",
Cipher: encResponse.Cipher,
}

decResponse, err := kmsClient.Decrypt(context.TODO(), decRequest)

fmt.Printf("\n\ndecryption response %v", decResponse)
}

0 comments on commit bc52663

Please sign in to comment.