Skip to content

Commit a58d10a

Browse files
committed
Pull latest to dist for 0.11.0 release
2 parents 98f2a3f + db5dd0c commit a58d10a

File tree

16 files changed

+260
-215
lines changed

16 files changed

+260
-215
lines changed

api/api.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package main // import "github.com/kevana/ui-for-docker"
2+
3+
import (
4+
"flag"
5+
"log"
6+
"net/http"
7+
)
8+
9+
func main() {
10+
var (
11+
endpoint = flag.String("H", "unix:///var/run/docker.sock", "Dockerd endpoint")
12+
addr = flag.String("p", ":9000", "Address and port to serve UI For Docker")
13+
assets = flag.String("a", ".", "Path to the assets")
14+
data = flag.String("d", ".", "Path to the data")
15+
tlsverify = flag.Bool("tlsverify", false, "TLS support")
16+
tlscacert = flag.String("tlscacert", "/certs/ca.pem", "Path to the CA")
17+
tlscert = flag.String("tlscert", "/certs/cert.pem", "Path to the TLS certificate file")
18+
tlskey = flag.String("tlskey", "/certs/key.pem", "Path to the TLS key")
19+
)
20+
flag.Parse()
21+
22+
tlsFlags := newTLSFlags(*tlsverify, *tlscacert, *tlscert, *tlskey)
23+
24+
handler := newHandler(*assets, *data, *endpoint, tlsFlags)
25+
if err := http.ListenAndServe(*addr, handler); err != nil {
26+
log.Fatal(err)
27+
}
28+
}

api/csrf.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package main
2+
3+
import (
4+
"github.com/gorilla/csrf"
5+
"github.com/gorilla/securecookie"
6+
"io/ioutil"
7+
"log"
8+
"net/http"
9+
)
10+
11+
const keyFile = "authKey.dat"
12+
13+
// newAuthKey reuses an existing CSRF authkey if present or generates a new one
14+
func newAuthKey(path string) []byte {
15+
var authKey []byte
16+
authKeyPath := path + "/" + keyFile
17+
data, err := ioutil.ReadFile(authKeyPath)
18+
if err != nil {
19+
log.Print("Unable to find an existing CSRF auth key. Generating a new key.")
20+
authKey = securecookie.GenerateRandomKey(32)
21+
err := ioutil.WriteFile(authKeyPath, authKey, 0644)
22+
if err != nil {
23+
log.Fatal("Unable to persist CSRF auth key.")
24+
log.Fatal(err)
25+
}
26+
} else {
27+
authKey = data
28+
}
29+
return authKey
30+
}
31+
32+
// newCSRF initializes a new CSRF handler
33+
func newCSRFHandler(keyPath string) func(h http.Handler) http.Handler {
34+
authKey := newAuthKey(keyPath)
35+
return csrf.Protect(
36+
authKey,
37+
csrf.HttpOnly(false),
38+
csrf.Secure(false),
39+
)
40+
}
41+
42+
// newCSRFWrapper wraps a http.Handler to add the CSRF token
43+
func newCSRFWrapper(h http.Handler) http.Handler {
44+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
45+
w.Header().Set("X-CSRF-Token", csrf.Token(r))
46+
h.ServeHTTP(w, r)
47+
})
48+
}

api/flags.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package main
2+
3+
// TLSFlags defines all the flags associated to the SSL configuration
4+
type TLSFlags struct {
5+
tls bool
6+
caPath string
7+
certPath string
8+
keyPath string
9+
}
10+
11+
// newTLSFlags creates a new TLSFlags from command flags
12+
func newTLSFlags(tls bool, cacert string, cert string, key string) TLSFlags {
13+
return TLSFlags{
14+
tls: tls,
15+
caPath: cacert,
16+
certPath: cert,
17+
keyPath: key,
18+
}
19+
}

api/handler.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package main
2+
3+
import (
4+
"log"
5+
"net/http"
6+
"net/http/httputil"
7+
"net/url"
8+
"os"
9+
)
10+
11+
// newHandler creates a new http.Handler with CSRF protection
12+
func newHandler(dir string, d string, e string, tlsFlags TLSFlags) http.Handler {
13+
var (
14+
mux = http.NewServeMux()
15+
fileHandler = http.FileServer(http.Dir(dir))
16+
)
17+
18+
u, perr := url.Parse(e)
19+
if perr != nil {
20+
log.Fatal(perr)
21+
}
22+
23+
handler := newAPIHandler(u, tlsFlags)
24+
CSRFHandler := newCSRFHandler(d)
25+
26+
mux.Handle("/dockerapi/", http.StripPrefix("/dockerapi", handler))
27+
mux.Handle("/", fileHandler)
28+
return CSRFHandler(newCSRFWrapper(mux))
29+
}
30+
31+
// newAPIHandler initializes a new http.Handler based on the URL scheme
32+
func newAPIHandler(u *url.URL, tlsFlags TLSFlags) http.Handler {
33+
var handler http.Handler
34+
if u.Scheme == "tcp" {
35+
if tlsFlags.tls {
36+
handler = newTCPHandlerWithTLS(u, tlsFlags)
37+
} else {
38+
handler = newTCPHandler(u)
39+
}
40+
} else if u.Scheme == "unix" {
41+
socketPath := u.Path
42+
if _, err := os.Stat(socketPath); err != nil {
43+
if os.IsNotExist(err) {
44+
log.Fatalf("Unix socket %s does not exist", socketPath)
45+
}
46+
log.Fatal(err)
47+
}
48+
handler = newUnixHandler(socketPath)
49+
} else {
50+
log.Fatalf("Bad Docker enpoint: %s. Only unix:// and tcp:// are supported.", u)
51+
}
52+
return handler
53+
}
54+
55+
// newUnixHandler initializes a new UnixHandler
56+
func newUnixHandler(e string) http.Handler {
57+
return &unixHandler{e}
58+
}
59+
60+
// newTCPHandler initializes a HTTP reverse proxy
61+
func newTCPHandler(u *url.URL) http.Handler {
62+
u.Scheme = "http"
63+
return httputil.NewSingleHostReverseProxy(u)
64+
}
65+
66+
// newTCPHandlerWithL initializes a HTTPS reverse proxy with a TLS configuration
67+
func newTCPHandlerWithTLS(u *url.URL, tlsFlags TLSFlags) http.Handler {
68+
u.Scheme = "https"
69+
var tlsConfig = newTLSConfig(tlsFlags)
70+
proxy := httputil.NewSingleHostReverseProxy(u)
71+
proxy.Transport = &http.Transport{
72+
TLSClientConfig: tlsConfig,
73+
}
74+
return proxy
75+
}

api/ssl.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package main
2+
3+
import (
4+
"crypto/tls"
5+
"crypto/x509"
6+
"io/ioutil"
7+
"log"
8+
)
9+
10+
// newTLSConfig initializes a tls.Config from the TLS flags
11+
func newTLSConfig(tlsFlags TLSFlags) *tls.Config {
12+
cert, err := tls.LoadX509KeyPair(tlsFlags.certPath, tlsFlags.keyPath)
13+
if err != nil {
14+
log.Fatal(err)
15+
}
16+
caCert, err := ioutil.ReadFile(tlsFlags.caPath)
17+
if err != nil {
18+
log.Fatal(err)
19+
}
20+
caCertPool := x509.NewCertPool()
21+
caCertPool.AppendCertsFromPEM(caCert)
22+
tlsConfig := &tls.Config{
23+
Certificates: []tls.Certificate{cert},
24+
RootCAs: caCertPool,
25+
}
26+
return tlsConfig
27+
}

api/unix_handler.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package main
2+
3+
import (
4+
"io"
5+
"log"
6+
"net"
7+
"net/http"
8+
"net/http/httputil"
9+
)
10+
11+
// unixHandler defines a handler holding the path to a socket under UNIX
12+
type unixHandler struct {
13+
path string
14+
}
15+
16+
// ServeHTTP implementation for unixHandler
17+
func (h *unixHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
18+
conn, err := net.Dial("unix", h.path)
19+
if err != nil {
20+
w.WriteHeader(http.StatusInternalServerError)
21+
log.Println(err)
22+
return
23+
}
24+
c := httputil.NewClientConn(conn, nil)
25+
defer c.Close()
26+
27+
res, err := c.Do(r)
28+
if err != nil {
29+
w.WriteHeader(http.StatusInternalServerError)
30+
log.Println(err)
31+
return
32+
}
33+
defer res.Body.Close()
34+
35+
copyHeader(w.Header(), res.Header)
36+
if _, err := io.Copy(w, res.Body); err != nil {
37+
log.Println(err)
38+
}
39+
}
40+
41+
func copyHeader(dst, src http.Header) {
42+
for k, vv := range src {
43+
for _, v := range vv {
44+
dst.Add(k, v)
45+
}
46+
}
47+
}

app/app.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,4 @@ angular.module('uifordocker', [
9797
// You need to set this to the api endpoint without the port i.e. http://192.168.1.9
9898
.constant('DOCKER_ENDPOINT', 'dockerapi')
9999
.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
100-
.constant('UI_VERSION', 'v0.11.0-beta');
100+
.constant('UI_VERSION', 'v0.11.0');

app/components/containers/containersController.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ angular.module('containers', [])
3737
Container.get({id: c.Id}, function (d) {
3838
c = d;
3939
counter = counter + 1;
40-
action({id: c.Id, HostConfig: c.HostConfig || {}}, function (d) {
40+
action({id: c.Id}, {}, function (d) {
4141
Messages.send("Container " + msg, c.Id);
4242
var index = $scope.containers.indexOf(c);
4343
complete();

app/components/startContainer/startContainerController.js

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -125,19 +125,10 @@ angular.module('startContainer', ['ui.bootstrap'])
125125
var s = $scope;
126126
Container.create(config, function (d) {
127127
if (d.Id) {
128-
var reqBody = config.HostConfig || {};
129-
reqBody.id = d.Id;
130-
ctor.start(reqBody, function (cd) {
131-
if (cd.id) {
132-
Messages.send('Container Started', d.Id);
133-
$('#create-modal').modal('hide');
134-
loc.path('/containers/' + d.Id + '/');
135-
} else {
136-
failedRequestHandler(cd, Messages);
137-
ctor.remove({id: d.Id}, function () {
138-
Messages.send('Container Removed', d.Id);
139-
});
140-
}
128+
ctor.start({id: d.Id}, {}, function (cd) {
129+
Messages.send('Container Started', d.Id);
130+
$('#create-modal').modal('hide');
131+
loc.path('/containers/' + d.Id + '/');
141132
}, function (e) {
142133
failedRequestHandler(e, Messages);
143134
});

bower.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "uifordocker",
3-
"version": "0.11.0-beta",
3+
"version": "0.11.0",
44
"homepage": "https://github.com/kevana/ui-for-docker",
55
"authors": [
66
"Michael Crosby <[email protected]>",

0 commit comments

Comments
 (0)