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:
@@ -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)
|
||||
}
|
||||
|
@@ -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...)
|
||||
|
Reference in New Issue
Block a user