From 3085dac359f4a43b43f2f0c3b0c53cf379f4897b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Cluseau?= Date: Thu, 22 Jan 2026 17:54:31 +0100 Subject: [PATCH] move ui to using trunk cargo install trunk --- cmd/dkl-local-server/ws-ssh-acls.go | 44 ------------- cmd/dkl-local-server/ws.go | 54 ---------------- html/html.go | 2 +- ui/Trunk.toml | 24 +++++++ {html/ui => ui}/app.css | 13 ++++ {html => ui}/favicon.ico | Bin {html/ui => ui}/index.html | 21 +++--- {html/ui => ui}/js/Cluster.js | 90 +++++++++++++++----------- {html/ui => ui}/js/Downloads.js | 3 +- {html/ui => ui}/js/GetCopy.js | 2 +- {html/ui => ui}/js/Host.js | 5 +- {html/ui => ui}/js/app.js | 6 +- {html/ui => ui}/js/jsonpatch.min.js | 0 {html/ui => ui}/js/vue.esm-browser.js | 0 {html/ui => ui}/style.css | 0 15 files changed, 109 insertions(+), 155 deletions(-) delete mode 100644 cmd/dkl-local-server/ws-ssh-acls.go create mode 100644 ui/Trunk.toml rename {html/ui => ui}/app.css (76%) rename {html => ui}/favicon.ico (100%) rename {html/ui => ui}/index.html (89%) rename {html/ui => ui}/js/Cluster.js (71%) rename {html/ui => ui}/js/Downloads.js (99%) rename {html/ui => ui}/js/GetCopy.js (98%) rename {html/ui => ui}/js/Host.js (86%) rename {html/ui => ui}/js/app.js (98%) rename {html/ui => ui}/js/jsonpatch.min.js (100%) rename {html/ui => ui}/js/vue.esm-browser.js (100%) rename {html/ui => ui}/style.css (100%) diff --git a/cmd/dkl-local-server/ws-ssh-acls.go b/cmd/dkl-local-server/ws-ssh-acls.go deleted file mode 100644 index 32d20f7..0000000 --- a/cmd/dkl-local-server/ws-ssh-acls.go +++ /dev/null @@ -1,44 +0,0 @@ -package main - -import ( - "net/http" - "os" - "path/filepath" - - restful "github.com/emicklei/go-restful" - yaml "gopkg.in/yaml.v2" -) - -type SSH_ACL struct { - Keys []string - Clusters []string - Groups []string - Hosts []string -} - -func loadSSH_ACLs() (acls []SSH_ACL, err error) { - f, err := os.Open(filepath.Join(*dataDir, "ssh-acls.yaml")) - if err != nil { - return - } - - defer f.Close() - - err = yaml.NewDecoder(f).Decode(&acls) - return -} - -func wsSSH_ACL_List(req *restful.Request, resp *restful.Response) { - // TODO - http.NotFound(resp.ResponseWriter, req.Request) -} - -func wsSSH_ACL_Get(req *restful.Request, resp *restful.Response) { - // TODO - http.NotFound(resp.ResponseWriter, req.Request) -} - -func wsSSH_ACL_Set(req *restful.Request, resp *restful.Response) { - // TODO - http.NotFound(resp.ResponseWriter, req.Request) -} diff --git a/cmd/dkl-local-server/ws.go b/cmd/dkl-local-server/ws.go index bec8a7f..4f95ff3 100644 --- a/cmd/dkl-local-server/ws.go +++ b/cmd/dkl-local-server/ws.go @@ -4,9 +4,7 @@ import ( "errors" "fmt" "log" - "net" "net/http" - "strings" "text/template" cfsslconfig "github.com/cloudflare/cfssl/config" @@ -152,10 +150,6 @@ func registerWS(rest *restful.Container) { ws.Route(ws.GET("/hosts").To(wsListHosts). Doc("List hosts")) - ws.Route(ws.GET("/ssh-acls").To(wsSSH_ACL_List)) - ws.Route(ws.GET("/ssh-acls/{acl-name}").To(wsSSH_ACL_Get)) - ws.Route(ws.PUT("/ssh-acls/{acl-name}").To(wsSSH_ACL_Set)) - rest.Add(ws) // Hosts API @@ -176,19 +170,6 @@ func registerWS(rest *restful.Container) { rest.Add(ws) - // Detected host API - ws = (&restful.WebService{}). - Filter(requireSecStore). - Path("/me"). - Param(ws.HeaderParameter("Authorization", "Host or admin bearer token")) - - (&wsHost{ - hostDoc: "detected host", - getHost: detectHost, - }).register(ws, func(rb *restful.RouteBuilder) { - rb.Notes("In this case, the host is detected from the remote IP") - }) - // Hosts by token API ws = (&restful.WebService{}). Filter(requireSecStore). @@ -229,41 +210,6 @@ func requireSecStore(req *restful.Request, resp *restful.Response, chain *restfu chain.ProcessFilter(req, resp) } -func detectHost(req *restful.Request) (hostName string, err error) { - if !*allowDetectedHost { - return - } - - r := req.Request - remoteAddr := r.RemoteAddr - - if *trustXFF { - if xff := r.Header.Get("X-Forwarded-For"); xff != "" { - remoteAddr = strings.Split(xff, ",")[0] - } - } - - hostIP, _, err := net.SplitHostPort(remoteAddr) - - if err != nil { - hostIP = remoteAddr - } - - cfg, err := readConfig() - if err != nil { - return - } - - host := cfg.HostByIP(hostIP) - - if host == nil { - log.Print("no host found for IP ", hostIP) - return - } - - return host.Name, nil -} - func wsReadConfig(resp *restful.Response) *localconfig.Config { cfg, err := readConfig() if err != nil { diff --git a/html/html.go b/html/html.go index eb03fda..8755ed7 100644 --- a/html/html.go +++ b/html/html.go @@ -2,5 +2,5 @@ package dlshtml import "embed" -//go:embed favicon.ico ui +//go:embed ui var FS embed.FS diff --git a/ui/Trunk.toml b/ui/Trunk.toml new file mode 100644 index 0000000..cf581d6 --- /dev/null +++ b/ui/Trunk.toml @@ -0,0 +1,24 @@ +[build] +public_url = "/ui" +dist = "../html/ui" + +[[proxy]] +backend = "http://localhost:7606/public-state" +[[proxy]] +backend = "http://localhost:7606/state" +[[proxy]] +backend = "http://localhost:7606/public" +[[proxy]] +backend = "http://localhost:7606/store" +[[proxy]] +backend = "http://localhost:7606/authorize-download" +[[proxy]] +backend = "http://localhost:7606/sign-download-set" +[[proxy]] +backend = "http://localhost:7606/configs" +[[proxy]] +backend = "http://localhost:7606/clusters" +[[proxy]] +backend = "http://localhost:7606/hosts-from-template" +[[proxy]] +backend = "http://localhost:7606/hosts" diff --git a/html/ui/app.css b/ui/app.css similarity index 76% rename from html/ui/app.css rename to ui/app.css index d5dd4c3..f3a6bab 100644 --- a/html/ui/app.css +++ b/ui/app.css @@ -27,3 +27,16 @@ color: var(--link); } } + +.text-and-file { + position:relative; + + textarea { + width: 64em; + } + + input[type="file"] { + position:absolute; + bottom:0;right:0; + } +} diff --git a/html/favicon.ico b/ui/favicon.ico similarity index 100% rename from html/favicon.ico rename to ui/favicon.ico diff --git a/html/ui/index.html b/ui/index.html similarity index 89% rename from html/ui/index.html rename to ui/index.html index 61616f7..7f2215a 100644 --- a/html/ui/index.html +++ b/ui/index.html @@ -2,18 +2,24 @@ Direktil Local Server - - - + + + + + + + + + + + +
@@ -134,6 +140,5 @@
- diff --git a/html/ui/js/Cluster.js b/ui/js/Cluster.js similarity index 71% rename from html/ui/js/Cluster.js rename to ui/js/Cluster.js index 49a67d5..2436c51 100644 --- a/html/ui/js/Cluster.js +++ b/ui/js/Cluster.js @@ -1,8 +1,4 @@ - -import Downloads from './Downloads.js'; -import GetCopy from './GetCopy.js'; - -export default { +const Cluster = { components: { Downloads, GetCopy }, props: [ 'cluster', 'token', 'state' ], data() { @@ -52,8 +48,61 @@ export default { }) .catch((e) => { alert('failed to sign: '+e); }) }, + readFile(e, onload) { + const file = e.target.files[0]; + if (!file) { return; } + const reader = new FileReader(); + reader.onload = () => { onload(reader.result) }; + reader.onerror = () => { alert("error reading file"); }; + reader.readAsText(file); + }, + loadPubKey(e) { + this.readFile(e, (v) => { + this.sshSignReq.PubKey = v; + }); + }, + loadCSR(e) { + this.readFile(e, (v) => { + this.kubeSignReq.CSR = v; + }); + }, }, template: ` +

Access

+ +

Allow cluster access from a public key

+ +

Grant SSH access

+ +

Validity: time range, ie: -5m:1w, 5m, 1M, 1y, 1d-1s, etc.

+

User:

+

Public key (OpenSSH format):
+ + +

+ +

+ +

+ +

Grant Kubernetes API access

+ +

Validity: time range, ie: -5m:1w, 5m, 1M, 1y, 1d-1s, etc.

+

User: (by default, from the CSR)

+

Group:

+

Certificate signing request (PEM format):
+ + +

+ +

+ +

+

Tokens