signing ui improvements

This commit is contained in:
Mikaël Cluseau
2026-07-20 13:42:48 +02:00
parent d2aefba82e
commit 03f087c5a3
3 changed files with 51 additions and 37 deletions
+25 -18
View File
@@ -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 = {
<label class="radio"><input type="radio" v-model="accessType" value="download-set" /> Download set</label>
</p>
<p>Validity: <input type="text" v-model="signReqValidity"/> <small>time range, ie: -5m:1w, 5m, 1M, 1y, 1d-1s, etc.</small></p>
<p>Validity: <input type="text" v-model="signReqValidity"/>
← <template v-for="(v,i) in ['5m','1d','1w','1M','1y']">{{ i ? ', ' : ' ' }}<a href="#" @click.prevent="signReqValidity=v">{{ v }}</a></template></p>
<p class="error" v-if="msg">{{ msg }} <button class="btn-close" @click="msg=null">&times;</button></p>
@@ -163,26 +176,20 @@ const ClusterAccess = {
<span class="text-and-file"><textarea v-model="sshSignReq.PubKey" style="height:3lh"></textarea>
<input type="file" accept=".pub" @change="loadPubKey" /></span>
</p>
<p><button :disabled="loading" @click="sshCASign">{{ loading ? 'signing...' : 'Sign SSH access' }}</button>
<template v-if="sshUserCert">
=&gt; <a :href="sshUserCert" download="ssh-cert.pub">Get certificate</a>
</template>
</p>
<p><button :disabled="loading" @click="sshCASign">{{ loading ? 'signing...' : 'Sign SSH access' }}</button></p>
</div>
<div v-if="accessType == 'kube'">
<h4>Grant Kubernetes API access</h4>
<p>User: <input type="text" v-model="kubeSignReq.User"/> (by default, from the CSR)</p>
<p>Group: <input type="text" v-model="kubeSignReq.Group"/></p>
<p>Certificate signing request (PEM format):<br/>
<span class="text-and-file"><textarea v-model="kubeSignReq.CSR" style="height:7lh;"></textarea>
<input type="file" accept=".csr" @change="loadCSR" /></span>
</p>
<p><button :disabled="loading" @click="kubeCASign">{{ loading ? 'signing...' : 'Sign Kubernetes API access' }}</button>
<template v-if="kubeUserCert">
=&gt; <a :href="kubeUserCert" download="tls.crt">Get certificate</a>
</template>
<p>User: <input type="text" v-model="kubeSignReq.User"/></p>
<p>Group: <input type="text" v-model="kubeSignReq.Group"/>
<a href="#" @click.prevent="kubeSignReq.Group=''">clear</a>, <a href="#" @click.prevent="kubeSignReq.Group='system:masters'">system:masters</a>
</p>
<p><button :disabled="loading" @click="kubeCASign">{{ loading ? 'signing...' : 'Sign Kubernetes API access' }}</button></p>
</div>
<div v-if="accessType == 'download-set'">