dls: password support
This commit is contained in:
		@ -160,6 +160,10 @@ func (ctx *renderContext) templateFuncs(ctxMap map[string]interface{}) map[strin
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return map[string]interface{}{
 | 
			
		||||
		"password": func(name string) (s string) {
 | 
			
		||||
			return fmt.Sprintf("{{ password %q %q }}", cluster, name)
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		"token": func(name string) (s string) {
 | 
			
		||||
			return fmt.Sprintf("{{ token %q %q }}", cluster, name)
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
@ -5,6 +5,7 @@ import (
 | 
			
		||||
	"crypto/sha256"
 | 
			
		||||
	"encoding/hex"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"log"
 | 
			
		||||
	"net/http"
 | 
			
		||||
@ -135,6 +136,14 @@ func (ctx *renderContext) templateFuncs() map[string]interface{} {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return map[string]interface{}{
 | 
			
		||||
		"password": func(cluster, name string) (password string, err error) {
 | 
			
		||||
			password = secretData.Password(cluster, name)
 | 
			
		||||
			if len(password) == 0 {
 | 
			
		||||
				err = fmt.Errorf("password %q not defined for cluster %q", name, cluster)
 | 
			
		||||
			}
 | 
			
		||||
			return
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		"token": func(cluster, name string) (s string, err error) {
 | 
			
		||||
			return secretData.Token(cluster, name)
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
@ -10,6 +10,7 @@ import (
 | 
			
		||||
	"net"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"github.com/cloudflare/cfssl/config"
 | 
			
		||||
@ -36,8 +37,9 @@ type SecretData struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ClusterSecrets struct {
 | 
			
		||||
	CAs    map[string]*CA
 | 
			
		||||
	Tokens map[string]string
 | 
			
		||||
	CAs       map[string]*CA
 | 
			
		||||
	Tokens    map[string]string
 | 
			
		||||
	Passwords map[string]string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CA struct {
 | 
			
		||||
@ -101,6 +103,14 @@ func (sd *SecretData) Save() error {
 | 
			
		||||
	return ioutil.WriteFile(secretDataPath(), ba, 0600)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newClusterSecrets() *ClusterSecrets {
 | 
			
		||||
	return &ClusterSecrets{
 | 
			
		||||
		CAs:       make(map[string]*CA),
 | 
			
		||||
		Tokens:    make(map[string]string),
 | 
			
		||||
		Passwords: make(map[string]string),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (sd *SecretData) cluster(name string) (cs *ClusterSecrets) {
 | 
			
		||||
	cs, ok := sd.clusters[name]
 | 
			
		||||
	if ok {
 | 
			
		||||
@ -112,15 +122,47 @@ func (sd *SecretData) cluster(name string) (cs *ClusterSecrets) {
 | 
			
		||||
 | 
			
		||||
	log.Info("secret-data: new cluster: ", name)
 | 
			
		||||
 | 
			
		||||
	cs = &ClusterSecrets{
 | 
			
		||||
		CAs:    make(map[string]*CA),
 | 
			
		||||
		Tokens: make(map[string]string),
 | 
			
		||||
	}
 | 
			
		||||
	cs = newClusterSecrets()
 | 
			
		||||
	sd.clusters[name] = cs
 | 
			
		||||
	sd.changed = true
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (sd *SecretData) Passwords(cluster string) (passwords []string) {
 | 
			
		||||
	cs := sd.cluster(cluster)
 | 
			
		||||
 | 
			
		||||
	passwords = make([]string, 0, len(cs.Passwords))
 | 
			
		||||
	for name := range cs.Passwords {
 | 
			
		||||
		passwords = append(passwords, name)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sort.Strings(passwords)
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (sd *SecretData) Password(cluster, name string) (password string) {
 | 
			
		||||
	cs := sd.cluster(cluster)
 | 
			
		||||
 | 
			
		||||
	if cs.Passwords == nil {
 | 
			
		||||
		cs.Passwords = make(map[string]string)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	password = cs.Passwords[name]
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (sd *SecretData) SetPassword(cluster, name, password string) {
 | 
			
		||||
	cs := sd.cluster(cluster)
 | 
			
		||||
 | 
			
		||||
	if cs.Passwords == nil {
 | 
			
		||||
		cs.Passwords = make(map[string]string)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cs.Passwords[name] = password
 | 
			
		||||
	sd.changed = true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (sd *SecretData) Token(cluster, name string) (token string, err error) {
 | 
			
		||||
	cs := sd.cluster(cluster)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -61,3 +61,42 @@ func wsClusterAddons(req *restful.Request, resp *restful.Response) {
 | 
			
		||||
 | 
			
		||||
	resp.Write([]byte(cluster.Addons))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func wsClusterPasswords(req *restful.Request, resp *restful.Response) {
 | 
			
		||||
	cluster := wsReadCluster(req, resp)
 | 
			
		||||
	if cluster == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resp.WriteEntity(secretData.Passwords(cluster.Name))
 | 
			
		||||
}
 | 
			
		||||
func wsClusterPassword(req *restful.Request, resp *restful.Response) {
 | 
			
		||||
	cluster := wsReadCluster(req, resp)
 | 
			
		||||
	if cluster == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	name := req.PathParameter("password-name")
 | 
			
		||||
 | 
			
		||||
	resp.WriteEntity(secretData.Password(cluster.Name, name))
 | 
			
		||||
}
 | 
			
		||||
func wsClusterSetPassword(req *restful.Request, resp *restful.Response) {
 | 
			
		||||
	cluster := wsReadCluster(req, resp)
 | 
			
		||||
	if cluster == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	name := req.PathParameter("password-name")
 | 
			
		||||
 | 
			
		||||
	var password string
 | 
			
		||||
	if err := req.ReadEntity(&password); err != nil {
 | 
			
		||||
		wsError(resp, err) // FIXME this is a BadRequest
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	secretData.SetPassword(cluster.Name, name, password)
 | 
			
		||||
 | 
			
		||||
	if err := secretData.Save(); err != nil {
 | 
			
		||||
		wsError(resp, err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -31,6 +31,13 @@ func buildWS() *restful.WebService {
 | 
			
		||||
		Returns(http.StatusOK, "OK", nil).
 | 
			
		||||
		Returns(http.StatusNotFound, "The cluster does not exists or does not have addons defined", nil))
 | 
			
		||||
 | 
			
		||||
	ws.Route(ws.GET("/clusters/{cluster-name}/passwords").Filter(adminAuth).To(wsClusterPasswords).
 | 
			
		||||
		Doc("List cluster's passwords"))
 | 
			
		||||
	ws.Route(ws.GET("/clusters/{cluster-name}/passwords/{password-name}").Filter(adminAuth).To(wsClusterPassword).
 | 
			
		||||
		Doc("Get cluster's password"))
 | 
			
		||||
	ws.Route(ws.PUT("/clusters/{cluster-name}/passwords/{password-name}").Filter(adminAuth).To(wsClusterSetPassword).
 | 
			
		||||
		Doc("Set cluster's password"))
 | 
			
		||||
 | 
			
		||||
	// hosts API
 | 
			
		||||
	ws.Route(ws.GET("/hosts").Filter(hostsAuth).To(wsListHosts).
 | 
			
		||||
		Doc("List hosts"))
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user