Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion security/acme-client/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
PLUGIN_NAME= acme-client
PLUGIN_VERSION= 4.16
PLUGIN_VERSION= 4.17
PLUGIN_REVISION= 1
PLUGIN_COMMENT= ACME Client
PLUGIN_MAINTAINER= opnsense@moov.de
Expand Down
5 changes: 5 additions & 0 deletions security/acme-client/pkg-descr
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ WWW: https://github.com/acmesh-official/acme.sh
Plugin Changelog
================

4.17

Added:
* new automation to upload certificate to JetKVM via SSH (#5621)

4.16

Added:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,32 @@ public function sshTestConnectionAction()
return ["status" => "unavailable"];
}

public function jetkvmGetIdentityAction()
{
$result = ["status" => "unavailable"];

if ($response = $this->callBackend(["show-jetkvm-identity"], ["jetkvm_identity_type", "jetkvm_host"])) {
$result["status"] = "ok";
$result["identity"] = $response;
}

return $result;
}

public function jetkvmTestConnectionAction()
{
if (
$response = $this->callBackend(
["test-jetkvm-connection"],
["jetkvm_host", "jetkvm_host_key", "jetkvm_port", "jetkvm_user", "jetkvm_identity_type"]
)
) {
return $response;
}

return ["status" => "unavailable"];
}

private function callBackend(array $command, array $arguments = [])
{
if ($this->request->isPost()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,103 @@
<type>text</type>
<help>The command to execute on the SSH server.</help>
</field>
<field>
<label>Required Parameters</label>
<type>header</type>
<style>method_table method_table_configd_upload_jetkvm</style>
</field>
<field>
<id>action.jetkvm_host</id>
<label>JetKVM Host</label>
<type>text</type>
<help>IP address or hostname of the JetKVM device. Requires the JetKVM device to already have "HTTPS Mode"
set to "Custom" in its own web UI (Settings &gt; Network) before this automation is attached -- it
only writes the certificate/key files and (optionally) reboots the device; it does not switch HTTPS
mode for you. Uploads will not take effect until that mode is selected on the device itself.</help>
</field>
<field>
<id>action.jetkvm_port</id>
<label>SSH Port</label>
<type>text</type>
<help>SSH server port on the JetKVM device. Leave blank to use default "22".</help>
<advanced>true</advanced>
</field>
<field>
<id>action.jetkvm_host_key</id>
<label>Host Key</label>
<type>text</type>
<help>JetKVM SSH host key, formatted as in 'known_hosts'.
Leave blank to auto accept the host key on first connect (not as secure as specifying it).</help>
</field>
<field>
<id>action.jetkvm_user</id>
<label>Username</label>
<type>text</type>
<help>The username to login to the JetKVM device via SSH. JetKVM only supports the "root" account for SSH access. Leave blank to use default "root".</help>
</field>
<field>
<id>action.jetkvm_identity_type</id>
<label>Identity Type</label>
<type>dropdown</type>
<help>The type of identity to present to the JetKVM device for authorization. Select 'none' to use default "ECDSA".
JetKVM only supports key-based SSH authentication (password logins are disabled), so the public key shown by
"Show Identity" must be added to the device's "Developer Mode" SSH key field (Settings &gt; Advanced) before this
automation can connect.</help>
</field>
<field>
<id>action.jetkvm_remote_path</id>
<label>Remote Path</label>
<type>text</type>
<help>Directory on the JetKVM device that the certificate and private key are copied into. Leave blank to use
default "/userdata/jetkvm/tls", confirmed as the storage location used by JetKVM's "Custom" TLS mode.
This is not part of JetKVM's stable/documented API and may change in a future firmware version, so
re-verify it if uploads stop being picked up after a JetKVM update.</help>
<advanced>true</advanced>
</field>
<field>
<id>action.jetkvm_filename_cert</id>
<label>Naming "user-defined.crt"</label>
<type>text</type>
<help>Filename used for the uploaded certificate (fullchain). Leave blank to use default "user-defined.crt",
confirmed as the filename JetKVM's "Custom" TLS mode reads from the remote path above (other filenames
such as "jetkvm.crt" back JetKVM's other, non-custom TLS modes and are not read by "Custom" mode).</help>
<advanced>true</advanced>
</field>
<field>
<id>action.jetkvm_filename_key</id>
<label>Naming "user-defined.key"</label>
<type>text</type>
<help>Filename used for the uploaded private key. Leave blank to use default "user-defined.key", confirmed
as the filename JetKVM's "Custom" TLS mode reads from the remote path above.</help>
<advanced>true</advanced>
</field>
<field>
<id>action.jetkvm_chmod_cert</id>
<label>Permission (Certificate)</label>
<type>text</type>
<help>Unix permission to apply to the uploaded certificate file. Leave blank to use default "0644".</help>
<advanced>true</advanced>
</field>
<field>
<id>action.jetkvm_chmod_key</id>
<label>Permission (Private Key)</label>
<type>text</type>
<help>Unix permission to apply to the uploaded private key file. Leave blank to use default "0600".</help>
<advanced>true</advanced>
</field>
<field>
<id>action.jetkvm_restart_command</id>
<label>Post-Upload Command</label>
<type>text</type>
<help>Optional command executed on the JetKVM device via the same SSH connection after the certificate and key
have been uploaded. Confirmed against a real device: JetKVM does not hot-reload a "Custom" certificate,
and its own certificate-apply script performs a full device reboot ("reboot") to pick one up, which
will briefly drop any active KVM-over-IP session. Defaults to "reboot" so a certificate renewed by an
unattended ACME cron run (typically overnight, when a session is unlikely to be active) is actually
applied without needing a human to follow up — clear the field if you'd rather apply/verify the new
certificate manually at a convenient time instead.</help>
<advanced>true</advanced>
</field>
<field>
<label>Required Parameters</label>
<type>header</type>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

/*
* Copyright (C) 2026 Frank Wall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

namespace OPNsense\AcmeClient\LeAutomation;

use OPNsense\AcmeClient\LeAutomationInterface;

/**
* Upload certificate and private key to a JetKVM device via SSH
* @package OPNsense\AcmeClient
*/
class ConfigdUploadJetkvm extends Base implements LeAutomationInterface
{
public function prepare()
{
$command = 'acmeclient upload-jetkvm ' . $this->cert_id . ' ' . $this->config->id;
$this->command = $command;
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1426,6 +1426,7 @@
<configd_reload_caddy>Reload Caddy (OPNsense plugin)</configd_reload_caddy>
<configd_upload_sftp>Upload certificate via SFTP</configd_upload_sftp>
<configd_remote_ssh>Remote Command via SSH</configd_remote_ssh>
<configd_upload_jetkvm>Upload certificate to JetKVM (SSH)</configd_upload_jetkvm>
<acme_fritzbox>Upload certificate to FRITZ!Box router</acme_fritzbox>
<acme_panos>Upload certificate to Palo Alto Networks Firewall</acme_panos>
<acme_proxmoxbs>Upload certificate to Proxmox Backup Server</acme_proxmoxbs>
Expand Down Expand Up @@ -1557,6 +1558,75 @@
<Mask>/^.{1,1024}$/u</Mask>
<ValidationMessage>Should be a shell command between 1 and 1024 characters.</ValidationMessage>
</remote_ssh_command>
<jetkvm_host type="TextField">
<Required>N</Required>
<Mask>/^.{1,255}$/u</Mask>
<ValidationMessage>Should be a string between 1 and 255 characters.</ValidationMessage>
</jetkvm_host>
<jetkvm_host_key type="TextField">
<Required>N</Required>
<!-- Key format: (comment)? key-type :SPACE: key-base64 (:SPACE: comment)?
Reference: https://stackoverflow.com/a/475217 -->
<Mask>/^.+?\s(?:[a-z0-9+\/]{4})*(?:[a-z0-9+\/]{2}==|[a-z0-9+\/]{3}=)?(?:\s.+?)?$/i</Mask>
<ValidationMessage>Should be a valid public SSH host key (see "known_hosts").</ValidationMessage>
</jetkvm_host_key>
<jetkvm_port type="IntegerField">
<Required>N</Required>
<MinimumValue>1</MinimumValue>
<MaximumValue>65535</MaximumValue>
<Default>22</Default>
<ValidationMessage>Should be a valid port number between 1 and 65535.</ValidationMessage>
</jetkvm_port>
<jetkvm_user type="TextField">
<Required>N</Required>
<Default>root</Default>
<Mask>/^.{1,128}$/u</Mask>
<ValidationMessage>Should be a string between 1 and 128 characters.</ValidationMessage>
</jetkvm_user>
<jetkvm_identity_type type="OptionField">
<Required>N</Required>
<OptionValues>
<ecdsa>ECDSA</ecdsa>
<rsa>RSA</rsa>
<ed25519>ed25519</ed25519>
</OptionValues>
</jetkvm_identity_type>
<jetkvm_remote_path type="TextField">
<Required>N</Required>
<Default>/userdata/jetkvm/tls</Default>
<Mask>/^.{1,512}$/u</Mask>
<ValidationMessage>Should be a string between 1 and 512 characters.</ValidationMessage>
</jetkvm_remote_path>
<jetkvm_filename_cert type="TextField">
<Required>N</Required>
<Default>user-defined.crt</Default>
<Mask>/^[\w\d_\-@.]{1,255}$/ui</Mask>
<ValidationMessage>Should be a plain filename (no path) between 1 and 255 characters.
Characters are limited to [a-z], [0-9] and [@._-].</ValidationMessage>
</jetkvm_filename_cert>
<jetkvm_filename_key type="TextField">
<Required>N</Required>
<Default>user-defined.key</Default>
<Mask>/^[\w\d_\-@.]{1,255}$/ui</Mask>
<ValidationMessage>Should be a plain filename (no path) between 1 and 255 characters.
Characters are limited to [a-z], [0-9] and [@._-].</ValidationMessage>
</jetkvm_filename_key>
<jetkvm_chmod_cert type="TextField">
<Required>N</Required>
<Mask>/^0[0-9]{3}$/u</Mask>
<ValidationMessage>A unix permission, 4 digits (e.g. 0644).</ValidationMessage>
</jetkvm_chmod_cert>
<jetkvm_chmod_key type="TextField">
<Required>N</Required>
<Mask>/^0[0-9]{3}$/u</Mask>
<ValidationMessage>A unix permission, 4 digits (e.g. 0600).</ValidationMessage>
</jetkvm_chmod_key>
<jetkvm_restart_command type="TextField">
<Required>N</Required>
<Default>reboot</Default>
<Mask>/^.{0,1024}$/u</Mask>
<ValidationMessage>Should be a shell command up to 1024 characters.</ValidationMessage>
</jetkvm_restart_command>
<!-- old value, should be removed in next major release -->
<configd type="ConfigdActionsField">
<filters>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ POSSIBILITY OF SUCH DAMAGE.
[
{selector: '#action\\.sftp_identity_type', group: "configd_upload_sftp", action: "sftpGetIdentity"},
{selector: '#action\\.remote_ssh_identity_type', group: "configd_remote_ssh", action: "sshGetIdentity"},
{selector: '#action\\.jetkvm_identity_type', group: "configd_upload_jetkvm", action: "jetkvmGetIdentity"},
].forEach(function(config) {
var $identityType = $(config.selector);
var identityDiv = makeStatusDiv($identityType);
Expand Down Expand Up @@ -126,6 +127,7 @@ POSSIBILITY OF SUCH DAMAGE.
[
{selector: '#action\\.sftp_user', group: "configd_upload_sftp", action: "sftpTestConnection", success: "{{ lang._('Connection and upload test succeeded.') }}"},
{selector: '#action\\.remote_ssh_user', group: "configd_remote_ssh", action: "sshTestConnection", success: "{{ lang._('Connection test succeeded.') }}"},
{selector: '#action\\.jetkvm_user', group: "configd_upload_jetkvm", action: "jetkvmTestConnection", success: "{{ lang._('Connection test succeeded.') }}"},
].forEach(function(config) {
var $user = $(config.selector);

Expand Down
Loading