v0,28,2
This commit is contained in:
1 parent
d940f9995f
commit
65e082b9d1
61 files changed
+1225
-581
No files matched your search
@@ -36,6 +36,7 @@ function syncCertificateFileSource() {
|
||||
const helpKey = external ? "certificateSourceExternalHelp" : "certificateSourceManagedHelp";
|
||||
$("certificate-file-source-help").dataset.i18n = helpKey;
|
||||
$("certificate-file-source-help").textContent = t(helpKey);
|
||||
$("certificate-external-acl-example").hidden = !external;
|
||||
}
|
||||
$("certificate-file-source").addEventListener("change", syncCertificateFileSource);
|
||||
|
||||
|
||||
@@ -1186,6 +1186,7 @@
|
||||
<option data-i18n="certificateSourceExternal" value="external"></option>
|
||||
</select>
|
||||
<p class="fine" id="certificate-file-source-help" data-i18n="certificateSourceManagedHelp"></p>
|
||||
<pre class="metrics-example" data-i18n="certificateExternalAclExample" hidden id="certificate-external-acl-example"></pre>
|
||||
<label data-i18n="certificateFile" for="certificate-file"></label><input
|
||||
id="certificate-file" maxlength="96" pattern="[A-Za-z0-9_.-]+"
|
||||
placeholder="app.pem" required="" />
|
||||
@@ -2728,14 +2729,20 @@
|
||||
class="pill live">SCOPED TOKENS</span>
|
||||
</div>
|
||||
<p class="fine" data-i18n="certificateApiHelp">Separate Key ID + Bearer Token
|
||||
credentials can only deploy or reload externally managed certificates. They cannot
|
||||
read configuration or use other administration APIs.</p>
|
||||
credentials are reload-only by default and restricted to explicit certificate IDs.
|
||||
Deploy is optional; tokens cannot read configuration or use other administration APIs.</p>
|
||||
<p class="fine" id="certificate-api-status" role="status"></p>
|
||||
<label><span data-i18n="certificateApiKeyId">Key ID</span><input
|
||||
id="certificate-api-key-id" maxlength="64" placeholder="certbot-main" /></label>
|
||||
<label><span data-i18n="certificateApiComment">Comment</span><input
|
||||
id="certificate-api-comment" maxlength="256"
|
||||
placeholder="Certbot on edge-01" /></label>
|
||||
<label><span data-i18n="certificateApiCertificateIds">Allowed certificate IDs</span><textarea
|
||||
id="certificate-api-certificate-ids" maxlength="2048" placeholder="shared-cert" required rows="3"></textarea></label>
|
||||
<p class="fine" data-i18n="certificateApiCertificateIdsHelp">List one or more certificate IDs separated by commas or new lines. The token can act only on these IDs.</p>
|
||||
<label class="check"><input id="certificate-api-allow-deploy" type="checkbox" /><span
|
||||
data-i18n="certificateApiAllowDeploy">Also allow deploy</span></label>
|
||||
<p class="fine" data-i18n="certificateApiAllowDeployHelp">Leave disabled for Certbot renewal hooks. Reload-only is the recommended least-privilege mode.</p>
|
||||
<label><span data-i18n="certificateApiToken">Bearer token (optional custom
|
||||
value)</span><input autocomplete="off" id="certificate-api-token"
|
||||
maxlength="128" minlength="32"
|
||||
@@ -2752,8 +2759,8 @@
|
||||
</div>
|
||||
<div class="certificate-api-credentials" id="certificate-api-credentials"></div>
|
||||
<p class="fine" data-i18n="certificateApiCurlHelp">External automation sends the Key ID
|
||||
header and Bearer token to the certificate deploy/reload endpoints over HTTPS (or
|
||||
loopback HTTP).</p>
|
||||
header and Bearer token over HTTPS (or loopback HTTP). Reload tokens use the targeted
|
||||
/api/certificates/{id}/reload endpoint; token access cannot trigger global reload.</p>
|
||||
<pre class="metrics-example" id="certificate-api-curl"></pre>
|
||||
</form>
|
||||
</div>
|
||||
@@ -2884,7 +2891,7 @@
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
<footer class="page-footer"><span>RustProxy <b>0.28.1</b></span><span id="footer-status">API - /
|
||||
<footer class="page-footer"><span>RustProxy <b>0.28.2</b></span><span id="footer-status">API - /
|
||||
dropped: 0</span></footer>
|
||||
</div>
|
||||
</main>
|
||||
@@ -3628,7 +3635,7 @@ max_execution_time = 30</code></pre>
|
||||
<article class="card about-card">
|
||||
<div class="about-product">
|
||||
<span aria-hidden="true" class="brand-mark">r<span>/</span>p</span>
|
||||
<div><span class="small-label">RustProxy</span><strong>0.28.1</strong></div>
|
||||
<div><span class="small-label">RustProxy</span><strong>0.28.2</strong></div>
|
||||
</div>
|
||||
<dl class="about-meta">
|
||||
<div>
|
||||
|
||||
+26
-11
@@ -88,18 +88,25 @@
|
||||
}
|
||||
function certificateApiExample() {
|
||||
const key = $("certificate-api-key-id").value.trim() || certificateApiCredentials()[0]?.key_id || "certbot-main";
|
||||
$("certificate-api-curl").textContent = `curl --fail --show-error --request POST \
|
||||
const enteredIds = $("certificate-api-certificate-ids").value.split(/[\n,]+/).map(value => value.trim()).filter(Boolean);
|
||||
const selected = enteredIds[0] || certificateApiCredentials()[0]?.certificate_ids?.find(value => value !== "*") || "CERTIFICATE_ID";
|
||||
const reload = `curl --fail --show-error --request POST \
|
||||
--header 'Authorization: Bearer $RUSTPROXY_CERT_TOKEN' \
|
||||
--header 'X-RustProxy-Certificate-Key: ${key}' \
|
||||
${location.origin}/api/certificates/${selected}/reload`;
|
||||
if (!$("certificate-api-allow-deploy").checked) {
|
||||
$("certificate-api-curl").textContent = reload;
|
||||
return;
|
||||
}
|
||||
$("certificate-api-curl").textContent = `${reload}
|
||||
|
||||
# Optional higher-privilege deploy for the same allowlisted certificate IDs:
|
||||
curl --fail --show-error --request POST \
|
||||
--header 'Authorization: Bearer $RUSTPROXY_CERT_TOKEN' \
|
||||
--header 'X-RustProxy-Certificate-Key: ${key}' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data @deploy.json \
|
||||
${location.origin}/api/certificates/deploy
|
||||
|
||||
# Reload one manual/file-backed certificate without changing its configuration:
|
||||
curl --fail --show-error --request POST \
|
||||
--header 'Authorization: Bearer $RUSTPROXY_CERT_TOKEN' \
|
||||
--header 'X-RustProxy-Certificate-Key: ${key}' \
|
||||
${location.origin}/api/certificates/CERTIFICATE_ID/reload`;
|
||||
${location.origin}/api/certificates/deploy`;
|
||||
}
|
||||
function renderCertificateApi() {
|
||||
const state = certificateApiState, target = $("certificate-api-credentials");
|
||||
@@ -116,6 +123,9 @@ curl --fail --show-error --request POST \
|
||||
const info = el("div", undefined, "certificate-api-credential-info");
|
||||
info.append(el("b", credential.key_id || "-", "mono"));
|
||||
if (credential.comment) info.append(el("span", credential.comment, "fine"));
|
||||
const scope = credential.allow_deploy ? t("certificateApiScopeDeployReload") : t("certificateApiScopeReloadOnly");
|
||||
const ids = Array.isArray(credential.certificate_ids) ? credential.certificate_ids.join(", ") : "-";
|
||||
info.append(el("span", `${scope} · ${t("certificateApiAllowedIds")}: ${ids}`, "fine mono"));
|
||||
const lastUsed = credential.last_used_at ? formatDateTime(Number(credential.last_used_at) * 1000) : t("certificateApiNeverUsed");
|
||||
info.append(el("span", `${t("certificateApiLastUsed")}: ${lastUsed}`, "fine"));
|
||||
const remove = action(t("certificateApiRevoke"), async () => {
|
||||
@@ -267,9 +277,12 @@ curl --fail --show-error --request POST \
|
||||
event.preventDefault(); const button = event.submitter || $("certificate-api-form").querySelector("button[type=submit]"); button.disabled = true;
|
||||
try {
|
||||
const keyId = $("certificate-api-key-id").value.trim(), token = $("certificate-api-token").value.trim(), comment = $("certificate-api-comment").value.trim();
|
||||
const payload = await api("/api/certificate-api", { method: "PUT", body: JSON.stringify({ key_id: keyId || null, token: token || null, comment }) });
|
||||
const certificateIds = $("certificate-api-certificate-ids").value.split(/[\n,]+/).map(value => value.trim()).filter(Boolean);
|
||||
if (!certificateIds.length) throw fieldError($("certificate-api-certificate-ids"), t("certificateApiCertificateIdsRequired"));
|
||||
const allowDeploy = $("certificate-api-allow-deploy").checked;
|
||||
const payload = await api("/api/certificate-api", { method: "PUT", body: JSON.stringify({ key_id: keyId || null, token: token || null, comment, certificate_ids: certificateIds, allow_deploy: allowDeploy }) });
|
||||
const clearToken = payload.token || ""; certificateApiState = { ...payload }; delete certificateApiState.token; delete certificateApiState.credential;
|
||||
$("certificate-api-key-id").value = ""; $("certificate-api-comment").value = ""; $("certificate-api-token").value = ""; $("certificate-api-secret").textContent = clearToken; $("certificate-api-secret-wrap").hidden = !clearToken; renderCertificateApi(); toast(t("certificateApiRotated"));
|
||||
$("certificate-api-key-id").value = ""; $("certificate-api-comment").value = ""; $("certificate-api-certificate-ids").value = ""; $("certificate-api-allow-deploy").checked = false; $("certificate-api-token").value = ""; $("certificate-api-secret").textContent = clearToken; $("certificate-api-secret-wrap").hidden = !clearToken; renderCertificateApi(); toast(t("certificateApiRotated"));
|
||||
} catch (error) { toast(error.message, true); } finally { button.disabled = false; }
|
||||
});
|
||||
$("certificate-api-revoke-all").addEventListener("click", async () => {
|
||||
@@ -279,6 +292,8 @@ curl --fail --show-error --request POST \
|
||||
catch (error) { toast(error.message, true); } finally { button.disabled = false; }
|
||||
});
|
||||
$("certificate-api-key-id").addEventListener("input", certificateApiExample);
|
||||
$("certificate-api-certificate-ids").addEventListener("input", certificateApiExample);
|
||||
$("certificate-api-allow-deploy").addEventListener("change", certificateApiExample);
|
||||
$("admin-tls").addEventListener("change", () => { $("admin-certificate").disabled = !$("admin-tls").checked; });
|
||||
$("prometheus-form").addEventListener("input", example);
|
||||
$("prom-preview").addEventListener("click", async () => {
|
||||
@@ -288,6 +303,6 @@ curl --fail --show-error --request POST \
|
||||
const text = await response.text(); if (epoch !== authEpoch || !authenticated) return; $("prom-preview-output").textContent = text.slice(0, 262144); $("prom-preview-output").hidden = false;
|
||||
} catch (error) { if (epoch === authEpoch) toast(error.message, true); } finally { button.disabled = false; }
|
||||
});
|
||||
window.rustProxySettings = { select, selectHttpTab, syncLocation, render, refreshSearch: applySettingsSearch, current: () => active, reset() { if (search) search.value = ""; applySettingsSearch(); select("listeners", false, false); selectCacheTab("general"); selectLoggingTab("outputs"); selectHttpTab("http2"); certificateApiState = null; certificateApiLoading = false; $("certificate-api-key-id").value = ""; $("certificate-api-comment").value = ""; $("certificate-api-token").value = ""; $("certificate-api-secret").textContent = ""; $("certificate-api-credentials").replaceChildren(); $("certificate-api-secret-wrap").hidden = true; $("prom-preview-output").textContent = ""; $("prom-preview-output").hidden = true; } };
|
||||
window.rustProxySettings = { select, selectHttpTab, syncLocation, render, refreshSearch: applySettingsSearch, current: () => active, reset() { if (search) search.value = ""; applySettingsSearch(); select("listeners", false, false); selectCacheTab("general"); selectLoggingTab("outputs"); selectHttpTab("http2"); certificateApiState = null; certificateApiLoading = false; $("certificate-api-key-id").value = ""; $("certificate-api-comment").value = ""; $("certificate-api-certificate-ids").value = ""; $("certificate-api-allow-deploy").checked = false; $("certificate-api-token").value = ""; $("certificate-api-secret").textContent = ""; $("certificate-api-credentials").replaceChildren(); $("certificate-api-secret-wrap").hidden = true; $("prom-preview-output").textContent = ""; $("prom-preview-output").hidden = true; } };
|
||||
select(active); render();
|
||||
})();
|
||||
Reference in new issue
Block a user