Your own integrations
Copy link to the page “Your own integrations”Upload your script as an integration and use it in an installation plan.
What you need
Copy link to the section “What you need”- A login with the Owner role on the appliance.
agent.ymland a script for the service. See the Windows and Linux examples.- A server with a service agent and administrator access to allow your integration.
Upload the integration
Copy link to the section “Upload the integration”- Put
agent.ymland the script (.sh,.ps1or.py) in a ZIP file. - Open Appliance › Integrations › Catalogue, enable uploads of your own integrations, select the ZIP file and click Upload and approve.
- Open the server’s page. Under Own scripts, click Allow own scripts and enter an administrator login for this run.
- Select the integration and action under Advanced in the installation plan’s Review step. See choosing the service.
Check that it works
Copy link to the section “Check that it works”The server’s Own scripts shows Allowed. In the catalogue, the integration version shows Verified. The script must return status: success when installation succeeds.
If it fails
Copy link to the section “If it fails”- The ZIP file is rejected → compare it with the agent.yml requirements and file limits below.
- The licence has no slots left → Free allows 1 integration of your own, Basic 3. Professional and Enterprise have no licence limit. Another version of an existing integration takes no extra slot.
- The server rejects the signing key → check permission on the server. Integrations can run only where the server trusts the appliance’s key.
- The script returns
error→ readmessagein the result, fix the script and upload a version with the fix.
Allow the integration on the server
Copy link to the section “Allow the integration on the server”Your own integration runs on the target server, never on the appliance. It cannot call an API from the appliance. On a server with a service agent, this permission requires Windows service agent 1.5.0 or Linux service agent 0.7.0 or later. The appliance changes permission over WinRM or SSH and restarts the service agent.
During installation, select Allow own scripts from this appliance under Servers › Add server › With service agent. On an enrolled server, use Own scripts. The page shows permission, when it changed and who changed it. Every change is logged. Updating the service agent leaves permission unchanged.
Use an administrator login for the individual run. A saved administrator login can be misused if the appliance or its administrator accounts are compromised.
If you disable uploads of your own integrations in the catalogue, approved ones keep running. If you disable permission on the server, trust in this appliance’s key is removed. Other trusted keys are kept.
A ScriptPolicy from Group Policy still decides what may run. A value of 0 blocks everything, including signed FairSSL integrations. See the values under Policy and audit.
Open Appliance › Integrations › Catalogue. Appliance signing key shows a fingerprint as sha256:<64 hex>. For Linux, download sslbrain-appliance-signing-key.pem through Download the public key for the Linux service agent (PEM).
Add the fingerprint to Custom as REG_MULTI_SZ, with one fingerprint per line, and set AllowCustomAgentsFrom to local. Keep other keys and sources if the values already exist. The example is for a server without these values. Run as an administrator and replace <fingerprint> with the 64 hex characters:
reg add "HKLM\SOFTWARE\sslbrain\TrustedKeys" /v Custom /t REG_MULTI_SZ /d "sha256:<fingerprint>" /freg add "HKLM\SOFTWARE\sslbrain" /v AllowCustomAgentsFrom /t REG_SZ /d "local" /fRestart-Service sslbrainagentAt installation, you can use ALLOW_CUSTOM_AGENTS_FROM=LOCAL TRUSTEDKEYS_CUSTOM="sha256:<fingerprint>". TRUSTEDKEYS_CUSTOM fills Custom only when the value is absent or empty (MSI properties).
Copy the downloaded PEM file to the server. Place it at the fixed path:
sudo install -m 0644 sslbrain-appliance-signing-key.pem /var/lib/sslbrain/state/appliance-signing-key.pemSet this line in /etc/sslbrain/agent.conf:
ALLOW_CUSTOM_AGENTS_FROM=APPLIANCERestart the service agent:
sudo systemctl restart sslbrain-agent.serviceWithout the key file or the setting, the service agent refuses the integration of your own because of an untrusted key without running it.
The value is the sum of what the service agent may run:
| Value | May run |
|---|---|
| 1 | FairSSL integrations that read |
| 2 | FairSSL integrations that write |
| 4 | Integrations from others that read |
| 8 | Integrations from others that write |
| 16 | Own integrations |
Values 4 and 8 cover integrations from others. The catalogue’s integrations are written, reviewed and signed by FairSSL.
The Appliance › Integrations › Approval page on the appliance does not decide what the service agents run (policy).
agent.yml
Copy link to the section “agent.yml”The appliance refuses the integration if any of these fields is missing or wrong:
| Field | Value |
|---|---|
agent.name | A name no integration from FairSSL and no built-in integration uses |
agent.tier | custom |
agent.channel | push-ssh when the appliance runs the script over SSH on a server without a service agent, or pull-service-agent. On a server with an enrolled service agent, the action always runs through the service agent, whatever the channel |
actions.<name> | The action, for example deploy |
script | A .sh, .ps1 or .py file in the zip file |
shell | On every action: bash for Linux or powershell for Windows. The service agent runs only the shell for the server’s operating system |
runtime.location | target |
runtime.interpreter | bash for Linux or powershell for Windows |
runtime.delivery.mode | stdin or scp-tmp for push-ssh, none for pull-service-agent |
category | write for an action that changes something, read for one that only reads |
timeout | Seconds the action may run |
cert_format | pem or pfx_base64 (variables) |
parameters | The inputs the script gets. On a service agent, these are the only inputs |
The zip file may be at most 1 MB, with 64 files, 512 KB per file and 4 MB unpacked. The allowed file types are yml, yaml, sh, ps1, py, json, md and txt. Hidden files, symbolic links, binary files, absolute paths and .. are refused.
The zip file must not contain agent-manifest or agent-manifest.sig. The appliance signs it when uploaded.
Windows servers
Copy link to the section “Windows servers”On Windows servers, sslbrain installs certificates through the service agent. Prefer the signed catalogue integrations for IIS, Exchange, SQL Server and the Windows certificate store (Integrations). To install the service agent, see Windows servers.
For your own service, you can use this example. It imports the certificate into Cert:\LocalMachine\My. Adapt the script if the service also needs the certificate bound or needs a restart. Trust the appliance’s key and allow your own integrations first.
agent.yml:
agent: name: intranet-app-windows display_name: "Intranet-app" version: "1.0.0" tier: custom description: "Installs the certificate for the intranet app" channel: pull-service-agent compatibility: os: ["Windows"]
actions: deploy: description: "Import the certificate into the Windows certificate store" script: deploy.ps1 shell: powershell runtime: location: target interpreter: powershell delivery: mode: none category: write timeout: 120 cert_format: pfx_base64 parameters: PFX_BASE64: type: string required: true secret: true source: certificate.pfx_base64 encoding: base64 content: opaque max_decoded_bytes: 48000 validation: '^[A-Za-z0-9+/=\x09-\x0d ]+$' PFX_PASSWORD: type: string required: true secret: true source: certificate.pfx_password validation: "^[^\\x00-\\x08\\x0a-\\x1f]{1,1000}$"deploy.ps1:
param([string]$PFX_BASE64, [string]$PFX_PASSWORD)
$ErrorActionPreference = 'Stop'$tempFile = $nulltry { $tempFile = [System.IO.Path]::GetTempFileName() [System.IO.File]::WriteAllBytes($tempFile, [Convert]::FromBase64String($PFX_BASE64)) Import-PfxCertificate -FilePath $tempFile -CertStoreLocation Cert:\LocalMachine\My ` -Password (ConvertTo-SecureString $PFX_PASSWORD -AsPlainText -Force) | Out-Null Write-Output '{"status":"success"}'} catch { @{ status = 'error'; message = $_.Exception.Message } | ConvertTo-Json -Compress exit 1} finally { if ($tempFile) { Remove-Item -LiteralPath $tempFile -Force }}Your own script on a Linux server
Copy link to the section “Your own script on a Linux server”The example writes the certificate and key to files and reloads a service.
agent.yml:
agent: name: intranet-app-linux display_name: "Intranet-app" version: "1.0.0" tier: custom description: "Installs the certificate for the intranet app" channel: push-ssh
actions: deploy: description: "Write the certificate and key, and reload the service" script: deploy.sh shell: bash runtime: location: target interpreter: bash delivery: mode: stdin category: write timeout: 120 cert_format: pem parameters: CERT_PEM: type: string required: true secret: true source: certificate.pem encoding: base64 content: opaque max_decoded_bytes: 48000 validation: "[A-Za-z0-9+/]+={0,2}" KEY_PEM: type: string required: true secret: true source: certificate.key encoding: base64 content: opaque max_decoded_bytes: 48000 validation: "[A-Za-z0-9+/]+={0,2}"deploy.sh:
#!/usr/bin/env bashset -euo pipefailtrap 'echo "{\"status\":\"error\",\"message\":\"deploy failed\"}"; exit 1' ERR
SUDO=""[ "${SSLBRAIN_ELEVATE:-}" = "sudo" ] && SUDO="sudo -n"umask 077
$SUDO mkdir -p /etc/intranet-app/tlsprintf '%s' "$CERT_PEM" | base64 -d | $SUDO tee /etc/intranet-app/tls/cert.pem >/dev/nullprintf '%s' "$KEY_PEM" | base64 -d | $SUDO tee /etc/intranet-app/tls/key.pem >/dev/null$SUDO systemctl reload intranet-app
echo '{"status":"success"}'What the script gets
Copy link to the section “What the script gets”A certificate chain is the intermediate certificates that link the server’s certificate to a root the browser trusts.
The script gets the parameters the action declares under parameters, under each parameter’s own name. On a server with a service agent, the script gets no other values.
In bash the values are variables in the script, for example $CERT_PEM. On a service agent they are not exported to programs the script starts. In PowerShell they are bound to the script’s param() by name. On a service agent that is the only way in, so declare them in param() as the example does.
Declare the certificate with source: certificate.pem, certificate.key, certificate.chain, certificate.pfx_base64, certificate.pfx_password, certificate.thumbprint, certificate.previous_thumbprint or certificate.fingerprint_sha256. For binary or PEM data, also set encoding: base64 on the parameter. The value then arrives base64-encoded, and the script decodes it as in the examples above.
The action’s cert_format chooses the certificate’s form. The values reach the script only through declared parameters. Without cert_format, an action that declares CERT_PEM, KEY_PEM or CHAIN_PEM gets the certificate as PEM.
cert_format | Variables |
|---|---|
pem | CERT_PEM, KEY_PEM, and CHAIN_PEM when the chain is delivered separately |
pfx_base64 | PFX_BASE64, PFX_PASSWORD, PFX_ENCRYPTION and CERT_PEM |
A script run over SSH (channel push-ssh, server without a service agent) also gets the values below. On a service agent, the script gets them only if the action declares them as parameters:
| Variables | Content |
|---|---|
HOSTNAME, HOST, SERVER_IP, SERVER_OS_TYPE | The server |
CREDENTIAL_USER, CREDENTIAL_SECRET | The credential on the server, when it has one |
SSLBRAIN_ELEVATE | sudo, when the credential has Elevate via sudo turned on. A service agent runs the action as root and never sets it |
CERTIFICATE_CN, CERTIFICATE_SERIAL, CERTIFICATE_FINGERPRINT_SHA256, CERTIFICATE_NOT_AFTER, CERTIFICATE_ISSUER, NEW_THUMBPRINT, NEW_FRIENDLY_NAME | The certificate being installed |
OLD_THUMBPRINT, OLD_FRIENDLY_NAME, OLD_FINGERPRINT_SHA256, OLD_CERTIFICATE_SERIAL | The certificate being replaced |
ENDPOINT_NAME, ENDPOINT_AGENT_TYPE, DEPLOYMENT_MODE | The service in the installation plan |
CERT_PATH, KEY_PATH, CHAIN_PATH, RELOAD_COMMAND, INIT_SYSTEM, SOFTWARE_VERSION | What discovery found on the service |
Result: the script always writes a JSON object with status set to success or error, and optionally message. The last object with a status counts. The action fails on error, even if the exit code is 0, and on an exit code other than 0.
The appliance signs your own integration with its own ECDSA P-256 key when it is uploaded. The service agent runs the integration only when you have trusted that key on the server and allowed your own integrations as described above.
Integrations from FairSSL have a manifest with the SHA-384 of each file, signed with ECDSA P-384 on a hardware key at FairSSL. The appliance trusts only FairSSL’s fixed production keys.
Appliance › Integrations › Catalogue shows for each version Verified, Invalid or Unsigned.