Skip to content

Commit

Permalink
Add Redis Generator for SecretProviderClass (#168)
Browse files Browse the repository at this point in the history
  • Loading branch information
AbdullahAlShaad authored Dec 28, 2022
1 parent 85d3fa7 commit 66fccc5
Show file tree
Hide file tree
Showing 145 changed files with 8,273 additions and 7,144 deletions.
31 changes: 16 additions & 15 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ module kubevault.dev/cli
go 1.18

require (
cloud.google.com/go/kms v1.4.0
cloud.google.com/go/storage v1.26.0
cloud.google.com/go/kms v1.7.0
cloud.google.com/go/storage v1.27.0
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets v0.10.0
github.com/aws/aws-sdk-go v1.44.100
Expand All @@ -14,13 +14,12 @@ require (
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.5.0
github.com/spf13/pflag v1.0.5
golang.org/x/text v0.3.7
golang.org/x/text v0.4.0
gomodules.xyz/logs v0.0.6
gomodules.xyz/pointer v0.1.0
gomodules.xyz/runtime v0.3.0
gomodules.xyz/x v0.0.14
google.golang.org/api v0.96.0
google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa
google.golang.org/api v0.103.0
google.golang.org/protobuf v1.28.1
k8s.io/api v0.25.1
k8s.io/apimachinery v0.25.1
Expand All @@ -36,9 +35,10 @@ require (
)

require (
cloud.google.com/go v0.102.1 // indirect
cloud.google.com/go/compute v1.7.0 // indirect
cloud.google.com/go/iam v0.3.0 // indirect
cloud.google.com/go v0.105.0 // indirect
cloud.google.com/go/compute v1.12.1 // indirect
cloud.google.com/go/compute/metadata v0.2.1 // indirect
cloud.google.com/go/iam v0.7.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.6.0 // indirect
Expand Down Expand Up @@ -80,8 +80,8 @@ require (
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.1.0 // indirect
github.com/googleapis/gax-go/v2 v2.4.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect
github.com/googleapis/gax-go/v2 v2.7.0 // indirect
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
Expand Down Expand Up @@ -133,24 +133,25 @@ require (
github.com/xlab/treeprint v1.1.0 // indirect
github.com/yudai/gojsondiff v1.0.0 // indirect
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
go.opencensus.io v0.23.0 // indirect
go.opencensus.io v0.24.0 // indirect
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
go.uber.org/atomic v1.9.0 // indirect
golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 // indirect
golang.org/x/net v0.0.0-20220909164309-bea034e7d591 // indirect
golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094 // indirect
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b // indirect
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 // indirect
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 // indirect
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 // indirect
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
gomodules.xyz/clock v0.0.0-20200817085942-06523dba733f // indirect
gomodules.xyz/flags v0.1.3 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
gomodules.xyz/mergo v0.3.13 // indirect
gomodules.xyz/sets v0.2.1 // indirect
gomodules.xyz/wait v0.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/grpc v1.48.0 // indirect
google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c // indirect
google.golang.org/grpc v1.50.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
Expand Down
449 changes: 40 additions & 409 deletions go.sum

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pkg/cmds/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ Examples:
# Generate secretproviderclass for the MongoDB username and password
$ kubectl vault generate secretproviderclass mongo-secret-provider -n test
$ kubectl vault generate secretproviderclass mongo-secret-provider -n test \
--secretrolebinding=dev/secret-r-binding \
--vaultrole=MongoDBRole/mongo-role \
--keys username=mongo-user --keys password=mongo-pass -o yaml
Expand Down
162 changes: 162 additions & 0 deletions pkg/generate/database/redis/redis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/*
Copyright AppsCode Inc. and Contributors
Licensed under the AppsCode Community License 1.0.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md
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 redis

import (
"context"
"fmt"
"strings"

engineapi "kubevault.dev/apimachinery/apis/engine/v1alpha1"
vaultapi "kubevault.dev/apimachinery/apis/kubevault/v1alpha2"
enginecs "kubevault.dev/apimachinery/client/clientset/versioned/typed/engine/v1alpha1"
vaultcs "kubevault.dev/apimachinery/client/clientset/versioned/typed/kubevault/v1alpha2"
policycs "kubevault.dev/apimachinery/client/clientset/versioned/typed/policy/v1alpha1"
"kubevault.dev/cli/pkg/generate/api"

"github.com/go-errors/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"sigs.k8s.io/yaml"
)

var available = map[string]bool{
"username": true,
"password": true,
}

type SecretObject struct {
ObjectName string `json:"objectName,omitempty"`
SecretPath string `json:"secretPath,omitempty"`
SecretKey string `json:"secretKey,omitempty"`
Method string `json:"method,omitempty"`
SecretArgs map[string]interface{} `json:"secretArgs,omitempty"`
}

type RedisGenerator struct {
role []string
srb *engineapi.SecretRoleBinding
se *engineapi.SecretEngine
keys map[string]string
engineClient *enginecs.EngineV1alpha1Client
vaultClient *vaultcs.KubevaultV1alpha2Client
policyClient *policycs.PolicyV1alpha1Client
clusterName string
}

var _ api.GeneratorInterface = &RedisGenerator{}

func NewRedisGenerator(role []string, srb *engineapi.SecretRoleBinding, keys map[string]string, engineClient *enginecs.EngineV1alpha1Client, vaultClient *vaultcs.KubevaultV1alpha2Client, policyClient *policycs.PolicyV1alpha1Client, kubeClient *kubernetes.Clientset) (*RedisGenerator, error) {
redisRole, err := engineClient.RedisRoles(srb.Namespace).Get(context.TODO(), role[1], metav1.GetOptions{})
if err != nil {
return nil, err
}

se, err := engineClient.SecretEngines(srb.Namespace).Get(context.TODO(), redisRole.Spec.SecretEngineRef.Name, metav1.GetOptions{})
if err != nil {
return nil, err
}

sts, err := kubeClient.AppsV1().StatefulSets(se.Spec.VaultRef.Namespace).Get(context.TODO(), se.Spec.VaultRef.Name, metav1.GetOptions{})
if err != nil {
return nil, err
}

var clName string
for _, cont := range sts.Spec.Template.Spec.Containers {
if cont.Name != vaultapi.VaultUnsealerContainerName {
continue
}
for _, arg := range cont.Args {
if strings.HasPrefix(arg, "--cluster-name=") {
clName = arg[1+strings.Index(arg, "="):]
}
}
}

return &RedisGenerator{
role: role,
srb: srb,
se: se,
keys: keys,
engineClient: engineClient,
vaultClient: vaultClient,
policyClient: policyClient,
clusterName: clName,
}, nil
}

func (g *RedisGenerator) Generate() (string, error) {
redisRole, err := g.engineClient.RedisRoles(g.srb.Namespace).Get(context.TODO(), g.role[1], metav1.GetOptions{})
if err != nil {
return "", err
}

for key := range g.keys {
if _, ok := available[key]; !ok {
var klist []string
for k := range available {
klist = append(klist, k)
}
return "", errors.Errorf("key %s not available for roleKind %s\navailable keys are: %s", key, g.role[0], strings.Join(klist, ", "))
}
}

var object []SecretObject
for key, mapping := range g.keys {
doc := g.GetSecretObject(key, mapping, redisRole)
object = append(object, *doc)
}

data, err := yaml.Marshal(object)
if err != nil {
return "", err
}

return string(data), nil
}

func (g *RedisGenerator) GetVaultServerURL() (string, error) {
vs, err := g.vaultClient.VaultServers(g.se.Spec.VaultRef.Namespace).Get(context.TODO(), g.se.Spec.VaultRef.Name, metav1.GetOptions{})
if err != nil {
return "", err
}

address := fmt.Sprintf("%s://%s.%s:8200", vs.Scheme(), vs.Name, vs.Namespace)
return address, nil
}

func (g *RedisGenerator) GetVaultRoleName() (string, error) {
vpb, err := g.policyClient.VaultPolicyBindings(g.se.Spec.VaultRef.Namespace).Get(context.TODO(), g.srb.VaultPolicyBindingName(), metav1.GetOptions{})
if err != nil {
return "", err
}

return vpb.Spec.VaultRoleName, nil
}

func (g *RedisGenerator) GetSecretObject(key, mapping string, redisRole *engineapi.RedisRole) *SecretObject {
sePath := fmt.Sprintf("k8s.%s.%s.%s.%s", g.clusterName, g.se.GetSecretEngineType(), g.se.Namespace, g.se.Name)
roleName := fmt.Sprintf("k8s.%s.%s.%s", g.clusterName, redisRole.Namespace, redisRole.Name)
path := fmt.Sprintf("/%s/creds/%s", sePath, roleName)

return &SecretObject{
ObjectName: mapping,
SecretPath: path,
SecretKey: key,
}
}
5 changes: 4 additions & 1 deletion pkg/generate/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
mongo "kubevault.dev/cli/pkg/generate/database/mongodb"
sql "kubevault.dev/cli/pkg/generate/database/mysql"
pg "kubevault.dev/cli/pkg/generate/database/postgres"
rd "kubevault.dev/cli/pkg/generate/database/redis"
"kubevault.dev/cli/pkg/generate/gcp"

"github.com/go-errors/errors"
Expand All @@ -51,9 +52,11 @@ func NewGenerator(role []string, srb *engineapi.SecretRoleBinding, keys map[stri
return sql.NewMySQLGenerator(role, srb, keys, engineClient, vaultClient, policyClient, kubeClient)
case engineapi.ResourceKindMariaDBRole:
return maria.NewMariaDBGenerator(role, srb, keys, engineClient, vaultClient, policyClient, kubeClient)
case engineapi.ResourceKindRedisRole:
return rd.NewRedisGenerator(role, srb, keys, engineClient, vaultClient, policyClient, kubeClient)
case engineapi.ResourceKindPostgresRole:
return pg.NewPostgresGenerator(role, srb, keys, engineClient, vaultClient, policyClient, kubeClient)
default:
return nil, errors.New("unknown/unsupported resource")
return nil, errors.New("unknown role")
}
}
2 changes: 1 addition & 1 deletion pkg/token-keys-store/google-kms-gcs/google_kms_gcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ import (
"kubevault.dev/cli/pkg/token-keys-store/api"

kms "cloud.google.com/go/kms/apiv1"
"cloud.google.com/go/kms/apiv1/kmspb"
"cloud.google.com/go/storage"
"github.com/pkg/errors"
"google.golang.org/api/cloudkms/v1"
"google.golang.org/api/option"
kmspb "google.golang.org/genproto/googleapis/cloud/kms/v1"
"google.golang.org/protobuf/types/known/wrapperspb"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
Expand Down
12 changes: 0 additions & 12 deletions vendor/cloud.google.com/go/.gitignore

This file was deleted.

Loading

0 comments on commit 66fccc5

Please sign in to comment.