From 03f087c5a3c300c108411f6d2a1fa92d89633964 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mika=C3=ABl=20Cluseau?=
Date: Mon, 20 Jul 2026 13:42:48 +0200
Subject: [PATCH] signing ui improvements
---
...b9.js => ClusterAccess-f38a8132c1c029e.js} | 43 +++++++++++--------
html/ui/index.html | 2 +-
ui/js/ClusterAccess.js | 43 +++++++++++--------
3 files changed, 51 insertions(+), 37 deletions(-)
rename html/ui/{ClusterAccess-1090c2ac32649bb9.js => ClusterAccess-f38a8132c1c029e.js} (81%)
diff --git a/html/ui/ClusterAccess-1090c2ac32649bb9.js b/html/ui/ClusterAccess-f38a8132c1c029e.js
similarity index 81%
rename from html/ui/ClusterAccess-1090c2ac32649bb9.js
rename to html/ui/ClusterAccess-f38a8132c1c029e.js
index b54a74e..755d35b 100644
--- a/html/ui/ClusterAccess-1090c2ac32649bb9.js
+++ b/html/ui/ClusterAccess-f38a8132c1c029e.js
@@ -8,13 +8,11 @@ const ClusterAccess = {
PubKey: "",
Principal: "root",
},
- sshUserCert: null,
kubeSignReq: {
CSR: "",
User: "",
Group: "system:masters",
},
- kubeUserCert: null,
downloadSet: null,
selectedAssets: {},
loading: false,
@@ -30,8 +28,8 @@ const ClusterAccess = {
headers: { 'Content-Type': 'application/json' },
}).then(r => {
if (r.ok) r.json().then(d => {
- if (d.user) this.kubeSignReq.User = d.user;
- if (d.group) this.kubeSignReq.Group = d.group;
+ this.kubeSignReq.User = d.user || "anonymous";
+ this.kubeSignReq.Group = d.group;
});
}).catch(() => {});
}
@@ -73,7 +71,15 @@ const ClusterAccess = {
headers: { 'Authorization': 'Bearer ' + this.token, 'Content-Type': 'application/json' },
}).then((resp) => {
if (resp.ok) {
- resp.blob().then((cert) => { this.sshUserCert = URL.createObjectURL(cert); this.loading = false })
+ resp.blob().then((cert) => {
+ const url = URL.createObjectURL(cert);
+ const a = document.createElement('a');
+ const parts = this.sshSignReq.PubKey.trim().split(/\s+/);
+ const user = parts.length > 2 ? parts[parts.length - 1] : this.sshSignReq.Principal;
+ a.href = url; a.download = user + '-cert.pub';
+ a.click(); URL.revokeObjectURL(url);
+ this.loading = false;
+ })
} else {
resp.json().then((resp) => { this.msg = 'failed to sign: '+resp.message; this.loading = false })
}
@@ -89,7 +95,13 @@ const ClusterAccess = {
headers: { 'Authorization': 'Bearer ' + this.token, 'Content-Type': 'application/json' },
}).then((resp) => {
if (resp.ok) {
- resp.blob().then((cert) => { this.kubeUserCert = URL.createObjectURL(cert); this.loading = false })
+ resp.blob().then((cert) => {
+ const url = URL.createObjectURL(cert);
+ const a = document.createElement('a');
+ a.href = url; a.download = (this.kubeSignReq.User || this.kubeSignReq.Group) + '.crt';
+ a.click(); URL.revokeObjectURL(url);
+ this.loading = false;
+ })
} else {
resp.json().then((resp) => { this.msg = 'failed to sign: '+resp.message; this.loading = false })
}
@@ -152,7 +164,8 @@ const ClusterAccess = {
- Validity: time range, ie: -5m:1w, 5m, 1M, 1y, 1d-1s, etc.
+ Validity:
+ ← {{ i ? ', ' : ' ' }}{{ v }}
{{ msg }}
@@ -163,26 +176,20 @@ const ClusterAccess = {
-
-
- => Get certificate
-
-
+
diff --git a/html/ui/index.html b/html/ui/index.html
index 676f890..d7a57f8 100644
--- a/html/ui/index.html
+++ b/html/ui/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/ui/js/ClusterAccess.js b/ui/js/ClusterAccess.js
index b54a74e..755d35b 100644
--- a/ui/js/ClusterAccess.js
+++ b/ui/js/ClusterAccess.js
@@ -8,13 +8,11 @@ const ClusterAccess = {
PubKey: "",
Principal: "root",
},
- sshUserCert: null,
kubeSignReq: {
CSR: "",
User: "",
Group: "system:masters",
},
- kubeUserCert: null,
downloadSet: null,
selectedAssets: {},
loading: false,
@@ -30,8 +28,8 @@ const ClusterAccess = {
headers: { 'Content-Type': 'application/json' },
}).then(r => {
if (r.ok) r.json().then(d => {
- if (d.user) this.kubeSignReq.User = d.user;
- if (d.group) this.kubeSignReq.Group = d.group;
+ this.kubeSignReq.User = d.user || "anonymous";
+ this.kubeSignReq.Group = d.group;
});
}).catch(() => {});
}
@@ -73,7 +71,15 @@ const ClusterAccess = {
headers: { 'Authorization': 'Bearer ' + this.token, 'Content-Type': 'application/json' },
}).then((resp) => {
if (resp.ok) {
- resp.blob().then((cert) => { this.sshUserCert = URL.createObjectURL(cert); this.loading = false })
+ resp.blob().then((cert) => {
+ const url = URL.createObjectURL(cert);
+ const a = document.createElement('a');
+ const parts = this.sshSignReq.PubKey.trim().split(/\s+/);
+ const user = parts.length > 2 ? parts[parts.length - 1] : this.sshSignReq.Principal;
+ a.href = url; a.download = user + '-cert.pub';
+ a.click(); URL.revokeObjectURL(url);
+ this.loading = false;
+ })
} else {
resp.json().then((resp) => { this.msg = 'failed to sign: '+resp.message; this.loading = false })
}
@@ -89,7 +95,13 @@ const ClusterAccess = {
headers: { 'Authorization': 'Bearer ' + this.token, 'Content-Type': 'application/json' },
}).then((resp) => {
if (resp.ok) {
- resp.blob().then((cert) => { this.kubeUserCert = URL.createObjectURL(cert); this.loading = false })
+ resp.blob().then((cert) => {
+ const url = URL.createObjectURL(cert);
+ const a = document.createElement('a');
+ a.href = url; a.download = (this.kubeSignReq.User || this.kubeSignReq.Group) + '.crt';
+ a.click(); URL.revokeObjectURL(url);
+ this.loading = false;
+ })
} else {
resp.json().then((resp) => { this.msg = 'failed to sign: '+resp.message; this.loading = false })
}
@@ -152,7 +164,8 @@ const ClusterAccess = {
-
Validity: time range, ie: -5m:1w, 5m, 1M, 1y, 1d-1s, etc.
+
Validity:
+ ← {{ i ? ', ' : ' ' }}{{ v }}
{{ msg }}
@@ -163,26 +176,20 @@ const ClusterAccess = {
-
-
- => Get certificate
-
-
+