runtime: provide credentials to services (#1817)

* runtime: inject credentials into service

* util/auth: self generate accounts (needed for jwt)

* runtime/kubernetes: add logging for creds

* runtime/kubernetes: serialize secret name

* runtime/kubernetes: remove unused code

* runtime/kubernetes: base64 encode secret

* runtime/kubernetes: remove metadata from secret

* util/kubernetes/client: omit empty secret metadata

* util/kubernetes/client: fix secret template

* util/kubernetes/client: fix secrets

* web: update auth util

* util/auth: fix missing arg

* extend token expiry

* extend token expiry
This commit is contained in:
ben-toogood
2020-07-10 16:25:46 +01:00
committed by GitHub
parent 3480e0a64e
commit 09ec20fded
10 changed files with 128 additions and 23 deletions

View File

@@ -2,10 +2,14 @@
package kubernetes
import (
"encoding/base64"
"errors"
"fmt"
"strings"
"sync"
"time"
"github.com/micro/go-micro/v2/logger"
log "github.com/micro/go-micro/v2/logger"
"github.com/micro/go-micro/v2/runtime"
"github.com/micro/go-micro/v2/util/kubernetes/client"
@@ -420,10 +424,27 @@ func (k *kubernetes) Create(s *runtime.Service, opts ...runtime.CreateOption) er
return err
}
}
// determine the image from the source and options
options.Image = k.getImage(s, options)
// create a secret for the credentials if some where provided
if len(options.Credentials) > 0 {
secret, err := k.createCredentials(s, options)
if err != nil {
if logger.V(logger.WarnLevel, logger.DefaultLogger) {
logger.Warnf("Error generating auth credentials for service: %v", err)
}
return err
}
if logger.V(logger.DebugLevel, logger.DefaultLogger) {
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
service := newService(s, options)
@@ -530,7 +551,6 @@ func (k *kubernetes) Delete(s *runtime.Service, opts ...runtime.DeleteOption) er
options := runtime.DeleteOptions{
Namespace: client.DefaultNamespace,
}
for _, o := range opts {
o(&options)
}
@@ -544,7 +564,11 @@ func (k *kubernetes) Delete(s *runtime.Service, opts ...runtime.DeleteOption) er
Namespace: options.Namespace,
})
return service.Stop(k.client, client.DeleteNamespace(options.Namespace))
// delete the service credentials
ns := client.DeleteNamespace(options.Namespace)
k.client.Delete(&client.Resource{Name: credentialsName(s), Kind: "secret"}, ns)
return service.Stop(k.client, ns)
}
// Start starts the runtime
@@ -643,3 +667,36 @@ func (k *kubernetes) getImage(s *runtime.Service, options runtime.CreateOptions)
return ""
}
func (k *kubernetes) createCredentials(service *runtime.Service, options runtime.CreateOptions) (string, error) {
// validate the creds
comps := strings.Split(options.Credentials, ":")
if len(comps) != 2 {
return "", errors.New("Invalid credentials, expected format 'user:pass'")
}
// construct the k8s secret object
secret := &client.Secret{
Type: "Opaque",
Data: map[string]string{
"id": base64.StdEncoding.EncodeToString([]byte(comps[0])),
"secret": base64.StdEncoding.EncodeToString([]byte(comps[1])),
},
Metadata: &client.Metadata{
Name: credentialsName(service),
Namespace: options.Namespace,
},
}
// create options specify the namespace
ns := client.CreateNamespace(options.Namespace)
// crete the secret in kubernetes
name := credentialsName(service)
err := k.client.Create(&client.Resource{Kind: "secret", Name: name, Value: secret}, ns)
return name, err
}
func credentialsName(service *runtime.Service) string {
name := fmt.Sprintf("%v-%v-credentials", service.Name, service.Version)
return client.SerializeResourceName(name)
}

View File

@@ -75,6 +75,27 @@ func newService(s *runtime.Service, c runtime.CreateOptions) *service {
env = append(env, client.EnvVar{Name: evarPair[0], Value: evarPair[1]})
}
// if credentials were provided, pass them to the service
if len(c.Credentials) > 0 {
env = append(env, client.EnvVar{
Name: "MICRO_AUTH_ID",
ValueFrom: &client.EnvVarSource{
SecretKeyRef: &client.SecretKeySelector{
Name: c.Credentials, Key: "id",
},
},
})
env = append(env, client.EnvVar{
Name: "MICRO_AUTH_SECRET",
ValueFrom: &client.EnvVarSource{
SecretKeyRef: &client.SecretKeySelector{
Name: c.Credentials, Key: "secret",
},
},
})
}
// if environment has been supplied update deployment default environment
if len(env) > 0 {
kdeploy.Spec.Template.PodSpec.Containers[0].Env = append(kdeploy.Spec.Template.PodSpec.Containers[0].Env, env...)