Skip to content

Commit

Permalink
Pull latest to dist for 0.11.0 release
Browse files Browse the repository at this point in the history
  • Loading branch information
kevana committed Sep 7, 2016
2 parents 98f2a3f + db5dd0c commit a58d10a
Show file tree
Hide file tree
Showing 16 changed files with 260 additions and 215 deletions.
28 changes: 28 additions & 0 deletions api/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package main // import "github.com/kevana/ui-for-docker"

import (
"flag"
"log"
"net/http"
)

func main() {
var (
endpoint = flag.String("H", "unix:///var/run/docker.sock", "Dockerd endpoint")
addr = flag.String("p", ":9000", "Address and port to serve UI For Docker")
assets = flag.String("a", ".", "Path to the assets")
data = flag.String("d", ".", "Path to the data")
tlsverify = flag.Bool("tlsverify", false, "TLS support")
tlscacert = flag.String("tlscacert", "/certs/ca.pem", "Path to the CA")
tlscert = flag.String("tlscert", "/certs/cert.pem", "Path to the TLS certificate file")
tlskey = flag.String("tlskey", "/certs/key.pem", "Path to the TLS key")
)
flag.Parse()

tlsFlags := newTLSFlags(*tlsverify, *tlscacert, *tlscert, *tlskey)

handler := newHandler(*assets, *data, *endpoint, tlsFlags)
if err := http.ListenAndServe(*addr, handler); err != nil {
log.Fatal(err)
}
}
48 changes: 48 additions & 0 deletions api/csrf.go
Original file line number Diff line number Diff line change
@@ -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)
})
}
19 changes: 19 additions & 0 deletions api/flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package main

// TLSFlags defines all the flags associated to the SSL configuration
type TLSFlags struct {
tls bool
caPath string
certPath string
keyPath string
}

// 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,
}
}
75 changes: 75 additions & 0 deletions api/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
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, 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)
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
}
27 changes: 27 additions & 0 deletions api/ssl.go
Original file line number Diff line number Diff line change
@@ -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
}
47 changes: 47 additions & 0 deletions api/unix_handler.go
Original file line number Diff line number Diff line change
@@ -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)
}
}
}
2 changes: 1 addition & 1 deletion app/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,4 @@ angular.module('uifordocker', [
// You need to set this to the api endpoint without the port i.e. http://192.168.1.9
.constant('DOCKER_ENDPOINT', 'dockerapi')
.constant('DOCKER_PORT', '') // Docker port, leave as an empty string if no port is requred. If you have a port, prefix it with a ':' i.e. :4243
.constant('UI_VERSION', 'v0.11.0-beta');
.constant('UI_VERSION', 'v0.11.0');
2 changes: 1 addition & 1 deletion app/components/containers/containersController.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ angular.module('containers', [])
Container.get({id: c.Id}, function (d) {
c = d;
counter = counter + 1;
action({id: c.Id, HostConfig: c.HostConfig || {}}, function (d) {
action({id: c.Id}, {}, function (d) {
Messages.send("Container " + msg, c.Id);
var index = $scope.containers.indexOf(c);
complete();
Expand Down
17 changes: 4 additions & 13 deletions app/components/startContainer/startContainerController.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,19 +125,10 @@ angular.module('startContainer', ['ui.bootstrap'])
var s = $scope;
Container.create(config, function (d) {
if (d.Id) {
var reqBody = config.HostConfig || {};
reqBody.id = d.Id;
ctor.start(reqBody, function (cd) {
if (cd.id) {
Messages.send('Container Started', d.Id);
$('#create-modal').modal('hide');
loc.path('/containers/' + d.Id + '/');
} else {
failedRequestHandler(cd, Messages);
ctor.remove({id: d.Id}, function () {
Messages.send('Container Removed', d.Id);
});
}
ctor.start({id: d.Id}, {}, function (cd) {
Messages.send('Container Started', d.Id);
$('#create-modal').modal('hide');
loc.path('/containers/' + d.Id + '/');
}, function (e) {
failedRequestHandler(e, Messages);
});
Expand Down
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "uifordocker",
"version": "0.11.0-beta",
"version": "0.11.0",
"homepage": "https://github.com/kevana/ui-for-docker",
"authors": [
"Michael Crosby <[email protected]>",
Expand Down
Binary file modified dist/ui-for-docker
Binary file not shown.
8 changes: 4 additions & 4 deletions dist/uifordocker.js

Large diffs are not rendered by default.

Loading

0 comments on commit a58d10a

Please sign in to comment.