runtime: support for dynamic secrets (#1861)
* runtime: replace CreateCredentials with CreateSecret * runtime/kubernetes: secrets support * runtime: CreateSecret => WithSecret * runtime: use map[string]string for secrets * runtime/kubernetes: update to use kv secrets * Fix merge conflict (missing import) Co-authored-by: Asim Aslam <asim@aslam.me>
This commit is contained in:
parent
3d1ba914fc
commit
006bbefaf3
@ -3,7 +3,6 @@ package kubernetes
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@ -450,9 +449,8 @@ func (k *kubernetes) Create(s *runtime.Service, opts ...runtime.CreateOption) er
|
|||||||
options.Image = k.getImage(s, options)
|
options.Image = k.getImage(s, options)
|
||||||
|
|
||||||
// create a secret for the credentials if some where provided
|
// create a secret for the credentials if some where provided
|
||||||
if len(options.Credentials) > 0 {
|
if len(options.Secrets) > 0 {
|
||||||
secret, err := k.createCredentials(s, options)
|
if err := k.createCredentials(s, options); err != nil {
|
||||||
if err != nil {
|
|
||||||
if logger.V(logger.WarnLevel, logger.DefaultLogger) {
|
if logger.V(logger.WarnLevel, logger.DefaultLogger) {
|
||||||
logger.Warnf("Error generating auth credentials for service: %v", err)
|
logger.Warnf("Error generating auth credentials for service: %v", err)
|
||||||
}
|
}
|
||||||
@ -462,9 +460,6 @@ func (k *kubernetes) Create(s *runtime.Service, opts ...runtime.CreateOption) er
|
|||||||
if logger.V(logger.DebugLevel, logger.DefaultLogger) {
|
if logger.V(logger.DebugLevel, logger.DefaultLogger) {
|
||||||
logger.Debugf("Generated auth credentials for service %v", s.Name)
|
logger.Debugf("Generated auth credentials for service %v", s.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// pass the secret name to the client via the credentials option
|
|
||||||
options.Credentials = secret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// create new service
|
// create new service
|
||||||
@ -689,33 +684,27 @@ func (k *kubernetes) getImage(s *runtime.Service, options runtime.CreateOptions)
|
|||||||
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
func (k *kubernetes) createCredentials(service *runtime.Service, options runtime.CreateOptions) (string, error) {
|
func (k *kubernetes) createCredentials(service *runtime.Service, options runtime.CreateOptions) error {
|
||||||
// validate the creds
|
data := make(map[string]string, len(options.Secrets))
|
||||||
comps := strings.Split(options.Credentials, ":")
|
for key, value := range options.Secrets {
|
||||||
if len(comps) != 2 {
|
data[key] = base64.StdEncoding.EncodeToString([]byte(value))
|
||||||
return "", errors.New("Invalid credentials, expected format 'user:pass'")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// construct the k8s secret object
|
// construct the k8s secret object
|
||||||
secret := &client.Secret{
|
secret := &client.Secret{
|
||||||
Type: "Opaque",
|
Type: "Opaque",
|
||||||
Data: map[string]string{
|
Data: data,
|
||||||
"id": base64.StdEncoding.EncodeToString([]byte(comps[0])),
|
|
||||||
"secret": base64.StdEncoding.EncodeToString([]byte(comps[1])),
|
|
||||||
},
|
|
||||||
Metadata: &client.Metadata{
|
Metadata: &client.Metadata{
|
||||||
Name: credentialsName(service),
|
Name: credentialsName(service),
|
||||||
Namespace: options.Namespace,
|
Namespace: options.Namespace,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// create options specify the namespace
|
|
||||||
ns := client.CreateNamespace(options.Namespace)
|
|
||||||
|
|
||||||
// crete the secret in kubernetes
|
// crete the secret in kubernetes
|
||||||
name := credentialsName(service)
|
name := credentialsName(service)
|
||||||
err := k.client.Create(&client.Resource{Kind: "secret", Name: name, Value: secret}, ns)
|
return k.client.Create(&client.Resource{
|
||||||
return name, err
|
Kind: "secret", Name: name, Value: secret,
|
||||||
|
}, client.CreateNamespace(options.Namespace))
|
||||||
}
|
}
|
||||||
|
|
||||||
func credentialsName(service *runtime.Service) string {
|
func credentialsName(service *runtime.Service) string {
|
||||||
|
@ -75,22 +75,14 @@ func newService(s *runtime.Service, c runtime.CreateOptions) *service {
|
|||||||
env = append(env, client.EnvVar{Name: evarPair[0], Value: evarPair[1]})
|
env = append(env, client.EnvVar{Name: evarPair[0], Value: evarPair[1]})
|
||||||
}
|
}
|
||||||
|
|
||||||
// if credentials were provided, pass them to the service
|
// if secrets were provided, pass them to the service
|
||||||
if len(c.Credentials) > 0 {
|
for key := range c.Secrets {
|
||||||
env = append(env, client.EnvVar{
|
env = append(env, client.EnvVar{
|
||||||
Name: "MICRO_AUTH_ID",
|
Name: key,
|
||||||
ValueFrom: &client.EnvVarSource{
|
ValueFrom: &client.EnvVarSource{
|
||||||
SecretKeyRef: &client.SecretKeySelector{
|
SecretKeyRef: &client.SecretKeySelector{
|
||||||
Name: c.Credentials, Key: "id",
|
Name: credentialsName(s),
|
||||||
},
|
Key: key,
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
env = append(env, client.EnvVar{
|
|
||||||
Name: "MICRO_AUTH_SECRET",
|
|
||||||
ValueFrom: &client.EnvVarSource{
|
|
||||||
SecretKeyRef: &client.SecretKeySelector{
|
|
||||||
Name: c.Credentials, Key: "secret",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -270,16 +270,9 @@ func (r *localRuntime) Create(s *runtime.Service, opts ...runtime.CreateOption)
|
|||||||
options.Args = []string{"run", "."}
|
options.Args = []string{"run", "."}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pass credentials as env vars
|
// pass secrets as env vars
|
||||||
if len(options.Credentials) > 0 {
|
for key, value := range options.Secrets {
|
||||||
// validate the creds
|
options.Env = append(options.Env, key, value)
|
||||||
comps := strings.Split(options.Credentials, ":")
|
|
||||||
if len(comps) != 2 {
|
|
||||||
return errors.New("Invalid credentials, expected format 'user:pass'")
|
|
||||||
}
|
|
||||||
|
|
||||||
options.Env = append(options.Env, "MICRO_AUTH_ID", comps[0])
|
|
||||||
options.Env = append(options.Env, "MICRO_AUTH_SECRET", comps[1])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := r.namespaces[options.Namespace]; !ok {
|
if _, ok := r.namespaces[options.Namespace]; !ok {
|
||||||
|
@ -82,8 +82,8 @@ type CreateOptions struct {
|
|||||||
Namespace string
|
Namespace string
|
||||||
// Specify the context to use
|
// Specify the context to use
|
||||||
Context context.Context
|
Context context.Context
|
||||||
// Credentials for the service to use
|
// Secrets to use
|
||||||
Credentials string
|
Secrets map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadOptions queries runtime services
|
// ReadOptions queries runtime services
|
||||||
@ -128,10 +128,14 @@ func CreateContext(ctx context.Context) CreateOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateCredentials sets the credentials to start the service with
|
// WithSecret sets a secret to provide the service with
|
||||||
func CreateCredentials(user, pass string) CreateOption {
|
func WithSecret(key, value string) CreateOption {
|
||||||
return func(o *CreateOptions) {
|
return func(o *CreateOptions) {
|
||||||
o.Credentials = user + ":" + pass
|
if o.Secrets == nil {
|
||||||
|
o.Secrets = map[string]string{key: value}
|
||||||
|
} else {
|
||||||
|
o.Secrets[key] = value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user