mirror of https://github.com/portainer/portainer
Merge branch 'refactor-backend' into internal
commit
d2b3360bff
|
@ -0,0 +1,34 @@
|
||||||
|
package main // import "github.com/cloudinovasi/ui-for-docker"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// main is the entry point of the program
|
||||||
|
func main() {
|
||||||
|
kingpin.Version("1.5.0")
|
||||||
|
var (
|
||||||
|
endpoint = kingpin.Flag("host", "Dockerd endpoint").Default("unix:///var/run/docker.sock").Short('H').String()
|
||||||
|
addr = kingpin.Flag("bind", "Address and port to serve UI For Docker").Default(":9000").Short('p').String()
|
||||||
|
assets = kingpin.Flag("assets", "Path to the assets").Default(".").Short('a').String()
|
||||||
|
data = kingpin.Flag("data", "Path to the data").Default(".").Short('d').String()
|
||||||
|
swarm = kingpin.Flag("swarm", "Swarm cluster support").Default("false").Short('s').Bool()
|
||||||
|
tlsverify = kingpin.Flag("tlsverify", "TLS support").Default("false").Bool()
|
||||||
|
tlscacert = kingpin.Flag("tlscacert", "Path to the CA").Default("/certs/ca.pem").String()
|
||||||
|
tlscert = kingpin.Flag("tlscert", "Path to the TLS certificate file").Default("/certs/cert.pem").String()
|
||||||
|
tlskey = kingpin.Flag("tlskey", "Path to the TLS key").Default("/certs/key.pem").String()
|
||||||
|
labels = pairs(kingpin.Flag("hide-label", "Hide containers with a specific label in the UI").Short('l'))
|
||||||
|
registries = pairs(kingpin.Flag("registries", "Supported Docker registries").Short('r'))
|
||||||
|
)
|
||||||
|
kingpin.Parse()
|
||||||
|
|
||||||
|
configuration := newConfig(*swarm, *labels, *registries)
|
||||||
|
tlsFlags := newTLSFlags(*tlsverify, *tlscacert, *tlscert, *tlskey)
|
||||||
|
|
||||||
|
handler := newHandler(*assets, *data, *endpoint, configuration, tlsFlags)
|
||||||
|
if err := http.ListenAndServe(*addr, handler); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Config defines the configuration available under the /config endpoint
|
||||||
|
type Config struct {
|
||||||
|
Swarm bool `json:"swarm"`
|
||||||
|
HiddenLabels pairList `json:"hiddenLabels"`
|
||||||
|
Registries pairList `json:"registries"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// newConfig creates a new Config from command flags
|
||||||
|
func newConfig(swarm bool, labels, registries pairList) Config {
|
||||||
|
return Config{
|
||||||
|
Swarm: swarm,
|
||||||
|
HiddenLabels: labels,
|
||||||
|
Registries: registries,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// configurationHandler defines a handler function used to encode the configuration in JSON
|
||||||
|
func configurationHandler(w http.ResponseWriter, r *http.Request, c Config) {
|
||||||
|
json.NewEncoder(w).Encode(c)
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gorilla/csrf"
|
||||||
|
"github.com/gorilla/securecookie"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
const keyFile = "authKey.dat"
|
||||||
|
|
||||||
|
// newAuthKey reuses an existing CSRF authkey if present or generates a new one
|
||||||
|
func newAuthKey(path string) []byte {
|
||||||
|
var authKey []byte
|
||||||
|
authKeyPath := path + "/" + keyFile
|
||||||
|
data, err := ioutil.ReadFile(authKeyPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Print("Unable to find an existing CSRF auth key. Generating a new key.")
|
||||||
|
authKey = securecookie.GenerateRandomKey(32)
|
||||||
|
err := ioutil.WriteFile(authKeyPath, authKey, 0644)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Unable to persist CSRF auth key.")
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
authKey = data
|
||||||
|
}
|
||||||
|
return authKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// newCSRF initializes a new CSRF handler
|
||||||
|
func newCSRFHandler(keyPath string) func(h http.Handler) http.Handler {
|
||||||
|
authKey := newAuthKey(keyPath)
|
||||||
|
return csrf.Protect(
|
||||||
|
authKey,
|
||||||
|
csrf.HttpOnly(false),
|
||||||
|
csrf.Secure(false),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// newCSRFWrapper wraps a http.Handler to add the CSRF token
|
||||||
|
func newCSRFWrapper(h http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("X-CSRF-Token", csrf.Token(r))
|
||||||
|
h.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TLSFlags defines all the flags associated to the SSL configuration
|
||||||
|
type TLSFlags struct {
|
||||||
|
tls bool
|
||||||
|
caPath string
|
||||||
|
certPath string
|
||||||
|
keyPath string
|
||||||
|
}
|
||||||
|
|
||||||
|
// pair defines a key/value pair
|
||||||
|
type pair struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Value string `json:"value"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// pairList defines an array of Label
|
||||||
|
type pairList []pair
|
||||||
|
|
||||||
|
// Set implementation for Labels
|
||||||
|
func (l *pairList) Set(value string) error {
|
||||||
|
parts := strings.SplitN(value, "=", 2)
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return fmt.Errorf("expected NAME=VALUE got '%s'", value)
|
||||||
|
}
|
||||||
|
p := new(pair)
|
||||||
|
p.Name = parts[0]
|
||||||
|
p.Value = parts[1]
|
||||||
|
*l = append(*l, *p)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String implementation for Labels
|
||||||
|
func (l *pairList) String() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsCumulative implementation for Labels
|
||||||
|
func (l *pairList) IsCumulative() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// LabelParser defines a custom parser for Labels flags
|
||||||
|
func pairs(s kingpin.Settings) (target *[]pair) {
|
||||||
|
target = new([]pair)
|
||||||
|
s.SetValue((*pairList)(target))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// newTLSFlags creates a new TLSFlags from command flags
|
||||||
|
func newTLSFlags(tls bool, cacert string, cert string, key string) TLSFlags {
|
||||||
|
return TLSFlags{
|
||||||
|
tls: tls,
|
||||||
|
caPath: cacert,
|
||||||
|
certPath: cert,
|
||||||
|
keyPath: key,
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httputil"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// newHandler creates a new http.Handler with CSRF protection
|
||||||
|
func newHandler(dir string, d string, e string, c Config, tlsFlags TLSFlags) http.Handler {
|
||||||
|
var (
|
||||||
|
mux = http.NewServeMux()
|
||||||
|
fileHandler = http.FileServer(http.Dir(dir))
|
||||||
|
)
|
||||||
|
|
||||||
|
u, perr := url.Parse(e)
|
||||||
|
if perr != nil {
|
||||||
|
log.Fatal(perr)
|
||||||
|
}
|
||||||
|
|
||||||
|
handler := newAPIHandler(u, tlsFlags)
|
||||||
|
CSRFHandler := newCSRFHandler(d)
|
||||||
|
|
||||||
|
mux.Handle("/dockerapi/", http.StripPrefix("/dockerapi", handler))
|
||||||
|
mux.Handle("/", fileHandler)
|
||||||
|
mux.HandleFunc("/config", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
configurationHandler(w, r, c)
|
||||||
|
})
|
||||||
|
return CSRFHandler(newCSRFWrapper(mux))
|
||||||
|
}
|
||||||
|
|
||||||
|
// newAPIHandler initializes a new http.Handler based on the URL scheme
|
||||||
|
func newAPIHandler(u *url.URL, tlsFlags TLSFlags) http.Handler {
|
||||||
|
var handler http.Handler
|
||||||
|
if u.Scheme == "tcp" {
|
||||||
|
if tlsFlags.tls {
|
||||||
|
handler = newTCPHandlerWithTLS(u, tlsFlags)
|
||||||
|
} else {
|
||||||
|
handler = newTCPHandler(u)
|
||||||
|
}
|
||||||
|
} else if u.Scheme == "unix" {
|
||||||
|
socketPath := u.Path
|
||||||
|
if _, err := os.Stat(socketPath); err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
log.Fatalf("Unix socket %s does not exist", socketPath)
|
||||||
|
}
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
handler = newUnixHandler(socketPath)
|
||||||
|
} else {
|
||||||
|
log.Fatalf("Bad Docker enpoint: %s. Only unix:// and tcp:// are supported.", u)
|
||||||
|
}
|
||||||
|
return handler
|
||||||
|
}
|
||||||
|
|
||||||
|
// newUnixHandler initializes a new UnixHandler
|
||||||
|
func newUnixHandler(e string) http.Handler {
|
||||||
|
return &unixHandler{e}
|
||||||
|
}
|
||||||
|
|
||||||
|
// newTCPHandler initializes a HTTP reverse proxy
|
||||||
|
func newTCPHandler(u *url.URL) http.Handler {
|
||||||
|
u.Scheme = "http"
|
||||||
|
return httputil.NewSingleHostReverseProxy(u)
|
||||||
|
}
|
||||||
|
|
||||||
|
// newTCPHandlerWithL initializes a HTTPS reverse proxy with a TLS configuration
|
||||||
|
func newTCPHandlerWithTLS(u *url.URL, tlsFlags TLSFlags) http.Handler {
|
||||||
|
u.Scheme = "https"
|
||||||
|
var tlsConfig = newTLSConfig(tlsFlags)
|
||||||
|
proxy := httputil.NewSingleHostReverseProxy(u)
|
||||||
|
proxy.Transport = &http.Transport{
|
||||||
|
TLSClientConfig: tlsConfig,
|
||||||
|
}
|
||||||
|
return proxy
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// newTLSConfig initializes a tls.Config from the TLS flags
|
||||||
|
func newTLSConfig(tlsFlags TLSFlags) *tls.Config {
|
||||||
|
cert, err := tls.LoadX509KeyPair(tlsFlags.certPath, tlsFlags.keyPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
caCert, err := ioutil.ReadFile(tlsFlags.caPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
caCertPool := x509.NewCertPool()
|
||||||
|
caCertPool.AppendCertsFromPEM(caCert)
|
||||||
|
tlsConfig := &tls.Config{
|
||||||
|
Certificates: []tls.Certificate{cert},
|
||||||
|
RootCAs: caCertPool,
|
||||||
|
}
|
||||||
|
return tlsConfig
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
// unixHandler defines a handler holding the path to a socket under UNIX
|
||||||
|
type unixHandler struct {
|
||||||
|
path string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServeHTTP implementation for unixHandler
|
||||||
|
func (h *unixHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
conn, err := net.Dial("unix", h.path)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c := httputil.NewClientConn(conn, nil)
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
res, err := c.Do(r)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
copyHeader(w.Header(), res.Header)
|
||||||
|
if _, err := io.Copy(w, res.Body); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyHeader(dst, src http.Header) {
|
||||||
|
for k, vv := range src {
|
||||||
|
for _, v := range vv {
|
||||||
|
dst.Add(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
246
dockerui.go
246
dockerui.go
|
@ -1,246 +0,0 @@
|
||||||
package main // import "github.com/cloudinovasi/ui-for-docker"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httputil"
|
|
||||||
"net/url"
|
|
||||||
"encoding/json"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"github.com/gorilla/csrf"
|
|
||||||
"io/ioutil"
|
|
||||||
"fmt"
|
|
||||||
"github.com/gorilla/securecookie"
|
|
||||||
"gopkg.in/alecthomas/kingpin.v2"
|
|
||||||
"crypto/tls"
|
|
||||||
"crypto/x509"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
endpoint = kingpin.Flag("host", "Dockerd endpoint").Default("unix:///var/run/docker.sock").Short('H').String()
|
|
||||||
addr = kingpin.Flag("bind", "Address and port to serve UI For Docker").Default(":9000").Short('p').String()
|
|
||||||
assets = kingpin.Flag("assets", "Path to the assets").Default(".").Short('a').String()
|
|
||||||
data = kingpin.Flag("data", "Path to the data").Default(".").Short('d').String()
|
|
||||||
swarm = kingpin.Flag("swarm", "Swarm cluster support").Default("false").Short('s').Bool()
|
|
||||||
registries = LabelParser(kingpin.Flag("registries", "Supported Docker registries").Short('r'))
|
|
||||||
tlsverify = kingpin.Flag("tlsverify", "TLS support").Default("false").Bool()
|
|
||||||
tlscacert = kingpin.Flag("tlscacert", "Path to the CA").Default("/certs/ca.pem").String()
|
|
||||||
tlscert = kingpin.Flag("tlscert", "Path to the TLS certificate file").Default("/certs/cert.pem").String()
|
|
||||||
tlskey = kingpin.Flag("tlskey", "Path to the TLS key").Default("/certs/key.pem").String()
|
|
||||||
labels = LabelParser(kingpin.Flag("hide-label", "Hide containers with a specific label in the UI").Short('l'))
|
|
||||||
authKey []byte
|
|
||||||
authKeyFile = "authKey.dat"
|
|
||||||
)
|
|
||||||
|
|
||||||
type UnixHandler struct {
|
|
||||||
path string
|
|
||||||
}
|
|
||||||
|
|
||||||
type TlsFlags struct {
|
|
||||||
tls bool
|
|
||||||
caPath string
|
|
||||||
certPath string
|
|
||||||
keyPath string
|
|
||||||
}
|
|
||||||
|
|
||||||
type Config struct {
|
|
||||||
Swarm bool `json:"swarm"`
|
|
||||||
HiddenLabels Labels `json:"hiddenLabels"`
|
|
||||||
Registries Labels `json:"registries"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Label struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Value string `json:"value"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Labels []Label
|
|
||||||
|
|
||||||
func (l *Labels) Set(value string) error {
|
|
||||||
parts := strings.SplitN(value, "=", 2)
|
|
||||||
if len(parts) != 2 {
|
|
||||||
return fmt.Errorf("expected NAME=VALUE got '%s'", value)
|
|
||||||
}
|
|
||||||
label := new(Label)
|
|
||||||
label.Name = parts[0]
|
|
||||||
label.Value = parts[1]
|
|
||||||
*l = append(*l, *label)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *Labels) String() string {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *Labels) IsCumulative() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func LabelParser(s kingpin.Settings) (target *[]Label) {
|
|
||||||
target = new([]Label)
|
|
||||||
s.SetValue((*Labels)(target))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *UnixHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
||||||
conn, err := net.Dial("unix", h.path)
|
|
||||||
if err != nil {
|
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c := httputil.NewClientConn(conn, nil)
|
|
||||||
defer c.Close()
|
|
||||||
|
|
||||||
res, err := c.Do(r)
|
|
||||||
if err != nil {
|
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer res.Body.Close()
|
|
||||||
|
|
||||||
copyHeader(w.Header(), res.Header)
|
|
||||||
if _, err := io.Copy(w, res.Body); err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func copyHeader(dst, src http.Header) {
|
|
||||||
for k, vv := range src {
|
|
||||||
for _, v := range vv {
|
|
||||||
dst.Add(k, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func configurationHandler(w http.ResponseWriter, r *http.Request, c Config) {
|
|
||||||
json.NewEncoder(w).Encode(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func createTcpHandler(u *url.URL) http.Handler {
|
|
||||||
u.Scheme = "http";
|
|
||||||
return httputil.NewSingleHostReverseProxy(u)
|
|
||||||
}
|
|
||||||
|
|
||||||
func createTlsConfig(tlsFlags TlsFlags) *tls.Config {
|
|
||||||
cert, err := tls.LoadX509KeyPair(tlsFlags.certPath, tlsFlags.keyPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
caCert, err := ioutil.ReadFile(tlsFlags.caPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
caCertPool := x509.NewCertPool()
|
|
||||||
caCertPool.AppendCertsFromPEM(caCert)
|
|
||||||
tlsConfig := &tls.Config{
|
|
||||||
Certificates: []tls.Certificate{cert},
|
|
||||||
RootCAs: caCertPool,
|
|
||||||
}
|
|
||||||
return tlsConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
func createTcpHandlerWithTLS(u *url.URL, tlsFlags TlsFlags) http.Handler {
|
|
||||||
u.Scheme = "https";
|
|
||||||
var tlsConfig = createTlsConfig(tlsFlags)
|
|
||||||
proxy := httputil.NewSingleHostReverseProxy(u)
|
|
||||||
proxy.Transport = &http.Transport{
|
|
||||||
TLSClientConfig: tlsConfig,
|
|
||||||
}
|
|
||||||
return proxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
func createUnixHandler(e string) http.Handler {
|
|
||||||
return &UnixHandler{e}
|
|
||||||
}
|
|
||||||
|
|
||||||
func createHandler(dir string, d string, e string, c Config, tlsFlags TlsFlags) http.Handler {
|
|
||||||
var (
|
|
||||||
mux = http.NewServeMux()
|
|
||||||
fileHandler = http.FileServer(http.Dir(dir))
|
|
||||||
h http.Handler
|
|
||||||
)
|
|
||||||
u, perr := url.Parse(e)
|
|
||||||
if perr != nil {
|
|
||||||
log.Fatal(perr)
|
|
||||||
}
|
|
||||||
if u.Scheme == "tcp" {
|
|
||||||
if tlsFlags.tls {
|
|
||||||
h = createTcpHandlerWithTLS(u, tlsFlags)
|
|
||||||
} else {
|
|
||||||
h = createTcpHandler(u)
|
|
||||||
}
|
|
||||||
} else if u.Scheme == "unix" {
|
|
||||||
var socketPath = u.Path
|
|
||||||
if _, err := os.Stat(socketPath); err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
log.Fatalf("unix socket %s does not exist", socketPath)
|
|
||||||
}
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
h = createUnixHandler(socketPath)
|
|
||||||
} else {
|
|
||||||
log.Fatalf("Bad Docker enpoint: %s. Only unix:// and tcp:// are supported.", e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use existing csrf authKey if present or generate a new one.
|
|
||||||
var authKeyPath = d + "/" + authKeyFile
|
|
||||||
dat, err := ioutil.ReadFile(authKeyPath)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
authKey = securecookie.GenerateRandomKey(32)
|
|
||||||
err := ioutil.WriteFile(authKeyPath, authKey, 0644)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("unable to persist auth key", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
authKey = dat
|
|
||||||
}
|
|
||||||
|
|
||||||
CSRF := csrf.Protect(
|
|
||||||
authKey,
|
|
||||||
csrf.HttpOnly(false),
|
|
||||||
csrf.Secure(false),
|
|
||||||
)
|
|
||||||
|
|
||||||
mux.Handle("/dockerapi/", http.StripPrefix("/dockerapi", h))
|
|
||||||
mux.Handle("/", fileHandler)
|
|
||||||
mux.HandleFunc("/config", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
configurationHandler(w, r, c)
|
|
||||||
})
|
|
||||||
return CSRF(csrfWrapper(mux))
|
|
||||||
}
|
|
||||||
|
|
||||||
func csrfWrapper(h http.Handler) http.Handler {
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.Header().Set("X-CSRF-Token", csrf.Token(r))
|
|
||||||
h.ServeHTTP(w, r)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
kingpin.Version("1.5.0")
|
|
||||||
kingpin.Parse()
|
|
||||||
|
|
||||||
configuration := Config{
|
|
||||||
Swarm: *swarm,
|
|
||||||
HiddenLabels: *labels,
|
|
||||||
Registries: *registries,
|
|
||||||
}
|
|
||||||
|
|
||||||
tlsFlags := TlsFlags{
|
|
||||||
tls: *tlsverify,
|
|
||||||
caPath: *tlscacert,
|
|
||||||
certPath: *tlscert,
|
|
||||||
keyPath: *tlskey,
|
|
||||||
}
|
|
||||||
|
|
||||||
handler := createHandler(*assets, *data, *endpoint, configuration, tlsFlags)
|
|
||||||
if err := http.ListenAndServe(*addr, handler); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -254,10 +254,10 @@ module.exports = function (grunt) {
|
||||||
},
|
},
|
||||||
buildBinary: {
|
buildBinary: {
|
||||||
command: [
|
command: [
|
||||||
'docker run --rm -v $(pwd):/src centurylink/golang-builder',
|
'docker run --rm -v $(pwd)/api:/src centurylink/golang-builder',
|
||||||
'shasum ui-for-docker > ui-for-docker-checksum.txt',
|
'shasum api/ui-for-docker > ui-for-docker-checksum.txt',
|
||||||
'mkdir -p dist',
|
'mkdir -p dist',
|
||||||
'mv ui-for-docker dist/'
|
'mv api/ui-for-docker dist/'
|
||||||
].join(' && ')
|
].join(' && ')
|
||||||
},
|
},
|
||||||
run: {
|
run: {
|
||||||
|
|
Loading…
Reference in New Issue