Skip to content

Commit

Permalink
Add ServiceAccount list, fix problem with secrets retriving
Browse files Browse the repository at this point in the history
  • Loading branch information
vadim.reyder authored and rvadim committed Nov 19, 2018
1 parent 72f2739 commit 98e221e
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 32 deletions.
22 changes: 5 additions & 17 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,22 +1,10 @@
language: go
go:
- "1.11.x"

- 1.11.x
install:
- go get github.com/Masterminds/glide
- glide up -v

- go get github.com/Masterminds/glide
- glide up -v
jobs:
include:
- stage: Test
script: make test
- stage: Build and release
script: make build
deploy:
provider: releases
api_key: $GITHUB_OAUTH_TOKEN
skip_cleanup: true
file: vault/plugin/vault-plugin-secrets-k8s
on:
tags: true

- stage: Test
script: make test
4 changes: 3 additions & 1 deletion backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package backend

import (
"context"
"sync"
"time"

"github.com/hashicorp/vault/logical"
Expand All @@ -11,6 +12,7 @@ import (
type kubeBackend struct {
*framework.Backend
testMode bool
saMutex sync.RWMutex
}

// New creates and returns new instance of Kubernetes secrets manager backend
Expand All @@ -28,8 +30,8 @@ func New() *kubeBackend {
Paths: []*framework.Path{
pathConfig(&b),
pathServiceAccounts(&b),
pathServiceAccountsList(&b),
pathSecrets(&b),
// TODO P1 pathListRoles
// TODO P1 pathConfigRotateToken
},
Secrets: []*framework.Secret{
Expand Down
2 changes: 1 addition & 1 deletion backend/path_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func (b *kubeBackend) pathConfigWrite(ctx context.Context, req *logical.Request,

if cfg == nil {
cfg = &config{
TTL: time.Duration(3600 * time.Second),
TTL: time.Duration(1800 * time.Second),
MaxTTL: time.Duration(3600 * time.Second),
}
}
Expand Down
2 changes: 1 addition & 1 deletion backend/path_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func TestConfig(t *testing.T) {
})

expected := map[string]interface{}{
"ttl": int64(3600),
"ttl": int64(1800),
"max-ttl": int64(3600),
"api-url": "https://localhost:8443/",
"CA": "aGVsbG8K",
Expand Down
4 changes: 3 additions & 1 deletion backend/path_secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func pathSecrets(b *kubeBackend) *framework.Path {
},
// ExistenceCheck: ,
Callbacks: map[logical.Operation]framework.OperationFunc{
//logical.ReadOperation: b.pathSecretsRead,
logical.ReadOperation: b.pathSecretsUpdate,
logical.UpdateOperation: b.pathSecretsUpdate,
},
HelpSynopsis: pathSecretsHelpSyn,
Expand All @@ -35,6 +35,8 @@ func pathSecrets(b *kubeBackend) *framework.Path {
}

func (b *kubeBackend) pathSecretsUpdate(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
b.saMutex.Lock()
defer b.saMutex.Unlock()
saName := d.Get("name").(string)
sa, err := getServiceAccount(ctx, saName, req.Storage)
if err != nil {
Expand Down
28 changes: 27 additions & 1 deletion backend/path_serviceaccounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ func getServiceAccount(ctx context.Context, name string, s logical.Storage) (*Se
return sa, nil
}

func pathServiceAccountsList(b *kubeBackend) *framework.Path {
return &framework.Path{
Pattern: fmt.Sprintf("%s/?$", saStoragePrefix),
Callbacks: map[logical.Operation]framework.OperationFunc{
logical.ListOperation: b.pathServiceAccountList,
},
HelpSynopsis: pathServiceAccountHelpSyn,
HelpDescription: pathServiceAccountHelpDesc,
}
}

func pathServiceAccounts(b *kubeBackend) *framework.Path {
return &framework.Path{
Pattern: fmt.Sprintf("%s/%s", saStoragePrefix, framework.GenericNameRegex("name")),
Expand All @@ -75,15 +86,26 @@ func pathServiceAccounts(b *kubeBackend) *framework.Path {
Callbacks: map[logical.Operation]framework.OperationFunc{
logical.DeleteOperation: b.pathServiceAccountDelete,
logical.ReadOperation: b.pathServiceAccountRead,
// logical.CreateOperation: b.pathServiceAccountCreateUpdate,
logical.UpdateOperation: b.pathServiceAccountCreateUpdate,
},
HelpSynopsis: pathServiceAccountHelpSyn,
HelpDescription: pathServiceAccountHelpDesc,
}
}

func (b *kubeBackend) pathServiceAccountList(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
b.saMutex.RLock()
defer b.saMutex.RUnlock()
list, err := req.Storage.List(ctx, fmt.Sprintf("%s/", saStoragePrefix))
if err != nil {
return nil, err
}
return logical.ListResponse(list), nil
}

func (b *kubeBackend) pathServiceAccountCreateUpdate(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
b.saMutex.Lock()
defer b.saMutex.Unlock()
new := false
nameRaw, ok := d.GetOk("name")
if !ok {
Expand Down Expand Up @@ -126,6 +148,8 @@ func (b *kubeBackend) pathServiceAccountCreateUpdate(ctx context.Context, req *l
}

func (b *kubeBackend) pathServiceAccountRead(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
b.saMutex.RLock()
defer b.saMutex.RUnlock()
nameRaw, ok := d.GetOk("name")
if !ok {
return logical.ErrorResponse("name is required"), nil
Expand All @@ -141,6 +165,8 @@ func (b *kubeBackend) pathServiceAccountRead(ctx context.Context, req *logical.R
}

func (b *kubeBackend) pathServiceAccountDelete(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
b.saMutex.Lock()
defer b.saMutex.Unlock()
nameRaw, ok := d.GetOk("name")
if !ok {
return logical.ErrorResponse("name is required"), nil
Expand Down
42 changes: 38 additions & 4 deletions backend/path_serviceaccounts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/hashicorp/vault/logical"
)

func TestRoleCreate(t *testing.T) {
func TestServiceAccountCreate(t *testing.T) {
b, s := getTestBackend(t)

request := &logical.Request{
Expand Down Expand Up @@ -42,7 +42,7 @@ func TestRoleCreate(t *testing.T) {
assertNoErrorRequest(t, b, request)
}

func TestRoleUpdate(t *testing.T) {
func TestServiceAccountUpdate(t *testing.T) {
b, s := getTestBackend(t)

request := &logical.Request{
Expand Down Expand Up @@ -84,7 +84,41 @@ func TestRoleUpdate(t *testing.T) {
assertEquals(t, resp.Data["namespace"], "test1", "Namespace should not be updated")
}

func TestRoleReadNotFound(t *testing.T) {
func TestServiceAccountList(t *testing.T) {
b, s := getTestBackend(t)

request := &logical.Request{
Operation: logical.ListOperation,
Path: fmt.Sprintf("%s/", saStoragePrefix),
Storage: s,
}
resp := assertNoErrorRequest(t, b, request)
assertEquals(t, len(resp.Data), 0, "Freshly crested backend shouldn't contain any ServiceAccount bindings")

request = &logical.Request{
Operation: logical.UpdateOperation,
Path: fmt.Sprintf("%s/test", saStoragePrefix),
Data: map[string]interface{}{
"namespace": "test",
"service-account-name": "test",
},
Storage: s,
}
assertNoErrorRequest(t, b, request)

request = &logical.Request{
Operation: logical.ListOperation,
Path: fmt.Sprintf("%s/", saStoragePrefix),
Storage: s,
}
resp = assertNoErrorRequest(t, b, request)
list := resp.Data["keys"].([]string)
assertEquals(t, list[0], "test", "First element from list /sa should be test, created above")
assertEquals(t, len(list), 1, "We create only one ServiceAccount, so list should return keys with len == 1")
}


func TestServiceAccountReadNotFound(t *testing.T) {
b, s := getTestBackend(t)

request := &logical.Request{
Expand All @@ -100,7 +134,7 @@ func TestRoleReadNotFound(t *testing.T) {
}
}

func TestRoleDelete(t *testing.T) {
func TestServiceAccountDelete(t *testing.T) {
b, s := getTestBackend(t)

request := &logical.Request{
Expand Down
26 changes: 20 additions & 6 deletions backend/secret_tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package backend

import (
"context"
"errors"
"fmt"
"math/rand"
"time"
Expand Down Expand Up @@ -79,6 +80,7 @@ func (b *kubeBackend) createSecret(ctx context.Context, s logical.Storage, c *co

var token, namespace string
var CABase64 interface{}
var resp *v1.Secret

if !b.testMode {
clientSet, err := getClientSet(c)
Expand All @@ -89,13 +91,25 @@ func (b *kubeBackend) createSecret(ctx context.Context, s logical.Storage, c *co
if err != nil {
return nil, errwrap.Wrapf("Unable to create secret, {{err}}", err)
}
secretResp, err := clientSet.CoreV1().Secrets(sa.Namespace).Get(secret.Name, metav1.GetOptions{})
if err != nil {
return nil, errwrap.Wrapf("Unable to get secret, {{err}}", err)
// Do 5 tries to get secret, due to it may not generated after first try
for range []int{0, 1, 2, 3, 4} {
secretResp, err := clientSet.CoreV1().Secrets(sa.Namespace).Get(secret.Name, metav1.GetOptions{})
if err != nil {
return nil, errwrap.Wrapf("Unable to get secret, {{err}}", err)
}
if len(secretResp.Data) == 0 {
time.Sleep(time.Second)
continue
}
resp = secretResp
token = string(secretResp.Data["token"])
namespace = string(secretResp.Data["namespace"])
CABase64 = secretResp.Data["ca.crt"]
break
}
if resp == nil || len(resp.Data) == 0 {
return nil, errors.New("unable to get secret with 5 tries, Data was empty")
}
token = string(secretResp.Data["token"])
namespace = string(secretResp.Data["namespace"])
CABase64 = secretResp.Data["ca.crt"]
} else {
token = "test"
namespace = "test"
Expand Down

0 comments on commit 98e221e

Please sign in to comment.