Your own scripts
Copy link to the page “Your own scripts”For a platform the catalogue does not cover, you write the script yourselves and upload it as a custom agent under Agents › Catalogue. The appliance signs it with its own key, and it runs only on the target server, never on the appliance.
Upload a custom agent
Copy link to the section “Upload a custom agent”- Only an Owner can turn on custom agents and upload them.
- The licence decides how many custom agents the appliance can have: Free 1, Basic 3, Professional and Enterprise unlimited. A later version of a custom agent you already have does not take another slot.
- A custom agent cannot call an API from the appliance. All actions run on the target server.
-
Package the agent as a zip file:
agent.ymland scripts (.sh,.ps1or.py). See agent.yml and the examples for Windows and Linux. -
Open Agents › Catalogue and turn on Allow custom agents under Custom agents.
-
Choose the file under Zip file with the agent and click Upload and approve.
-
Use the agent in a rule: in the rule’s Summary step, each service has an Agent chain for …. Which service to choose on a server where discovery does not know the application is described in Servers sslbrain does not know. Click Add agent, choose your custom agent under Eligible agents, and choose the action. The parameters from
agent.ymlare filled in on that step. -
If the target is a server with a service agent, the agent must be allowed to run custom scripts (script policy).
If you turn off Allow custom agents, no more can be uploaded, but the custom agents already approved keep running.
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.
agent.yml
Copy link to the section “agent.yml”agent.yml describes the agent and its actions. The appliance refuses the agent if any of these requirements is not met:
agent.channelis set:push-winrmfor Windows andpush-sshfor Linux. On a Windows server the script runs through the service agent, whatever the channel is called.agent.tieriscustom.agent.nameis not used by a package from FairSSL or by a built-in package.- Each action has
runtime.location: target, aruntime.interpreterand aruntime.delivery.modethat matches the channel:winrm-streamforpush-winrm,stdinorscp-tmpforpush-ssh. - Each action’s
scriptis a.sh,.ps1or.pyfile in the zip file.
| Field | Meaning |
|---|---|
agent.channel | push-winrm for Windows, push-ssh for Linux |
actions.<name> | The action, for example deploy |
runtime.interpreter | powershell or bash |
runtime.delivery.mode | winrm-stream for Windows, stdin for Linux |
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: the form the certificate is delivered in (variables) |
parameters | Your own fields, filled in on the rule |
Your own script on a Windows server
Copy link to the section “Your own script on a Windows server”The script runs in PowerShell on the server, through the service agent. The example imports the certificate into the computer’s certificate store and restarts a service.
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: push-winrm
actions: deploy: description: "Import the certificate and restart the service" script: deploy.ps1 runtime: location: target interpreter: powershell delivery: mode: winrm-stream category: write timeout: 180 cert_format: pfx_base64deploy.ps1:
$ErrorActionPreference = 'Stop'try { $flags = [Security.Cryptography.X509Certificates.X509KeyStorageFlags]'MachineKeySet,PersistKeySet' $cert = [Security.Cryptography.X509Certificates.X509Certificate2]::new( [Convert]::FromBase64String($PFX_BASE64), $PFX_PASSWORD, $flags) $store = [Security.Cryptography.X509Certificates.X509Store]::new('My', 'LocalMachine') $store.Open('ReadWrite'); $store.Add($cert); $store.Close()
# Bind the certificate to the service here, for example with $cert.Thumbprint Restart-Service -Name 'IntranetApp'
@{ status = 'success'; message = "Installed $($cert.Thumbprint)" } | ConvertTo-Json -Compress} catch { @{ status = 'error'; message = $_.Exception.Message } | ConvertTo-Json -Compress exit 1}Your own script on a Linux server
Copy link to the section “Your own script on a Linux server”The script runs in bash on the 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 runtime: location: target interpreter: bash delivery: mode: stdin category: write timeout: 120 cert_format: pemdeploy.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\n' "$CERT_PEM" | $SUDO tee /etc/intranet-app/tls/cert.pem >/dev/nullprintf '%s\n' "$KEY_PEM" | $SUDO tee /etc/intranet-app/tls/key.pem >/dev/null$SUDO systemctl reload intranet-app
echo '{"status":"success"}'SSLBRAIN_ELEVATE is set to sudo when the credential has Elevate via sudo turned on.
What the script gets
Copy link to the section “What the script gets”The certificate is delivered in the form the action’s cert_format names:
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 |
An action that declares the parameters CERT_PEM, KEY_PEM or CHAIN_PEM without cert_format gets the certificate as PEM.
The script also always gets:
| 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 |
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 rule |
CERT_PATH, KEY_PATH, CHAIN_PATH, RELOAD_COMMAND, INIT_SYSTEM, SOFTWARE_VERSION | What discovery found on the service, when it found it |
A parameter with source: certificate.pem, certificate.key, certificate.chain, certificate.pfx_base64, certificate.pfx_password, certificate.thumbprint, certificate.previous_thumbprint or certificate.fingerprint_sha256 gets the value under the parameter’s own name. That is useful in PowerShell, where the variables are also bound to param() by name.
In bash the values are environment variables. In PowerShell they are session variables, for example $PFX_BASE64.
Result: the script writes a JSON object with status set to success or error, and optionally message. The last object with a status counts. error makes the action fail even if the exit code is 0, and an exit code other than 0 makes it fail. Always write the JSON result.
The service agent’s script policy
Copy link to the section “The service agent’s script policy”The service agent on the server decides for itself which scripts it runs. The default is FairSSL’s packages and the community packages, not custom agents. The appliance cannot change this.
The policy is a number, the sum of what the agent may run:
| Value | May run |
|---|---|
| 1 | FairSSL packages that read |
| 2 | FairSSL packages that write |
| 4 | Community packages that read |
| 8 | Community packages that write |
| 16 | Custom agents |
The default is 15. To run custom agents, the value must be 31. On a Windows server it is set in one of two ways:
- At installation, with the MSI property
SCRIPTPOLICY=31(silent install). - With Group Policy: the value
ScriptPolicy(REG_DWORD, 31) underHKLM\SOFTWARE\Policies\SSLBrain. It takes precedence over the value from the installation. The agent rereads its configuration during its cycle; restart theSSLBrainAgentservice if the value should apply at once.
Without a service agent there is no script policy on the server. The Policy and audit › Script policy page on the appliance does not decide what the agents run (policy).
Every package from FairSSL has a signed manifest with the SHA-384 of each file and its category, type and path. The signature is ECDSA P-384 and is made on a hardware key at FairSSL, never in a build pipeline. The appliance trusts only FairSSL’s fixed production keys.
A custom agent is signed by the appliance with its own key when it is uploaded. The service agents get the appliance’s key when they register, and trust it for custom agents.
Agents › Catalogue shows for each version whether the signature is Verified, Invalid or Unsigned.