You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 11 Next »

Introduction

Jobs might require variables for parameterization that hold secrets. We find a number of requirements for management of such variables:

  • The secret should not be exposed to JS7 logging and to any instance of JS7 products that track variables.
    • For example, if a variable created by some job should be forwarded to a next job executed with a different Agent then the Controller and JOC Cockpit keep track of the variable.
      • The variable is available in the Agent's and Controller's memory.
      • The variable is available in the Controller's journal, in JOC Cockpit's JS7 - History and in the JS7 - Database.
    • At no point in time the secret should be available to involved JS7 products, to the database or to the OS.
  • The secret should not be exposed to OS mechanisms that allow a 3rd-party to identify the secret:
    • For example, the following command to encrypt a secret can be tracked by any account capable of executing a ps -aux command:
       echo "secret" | openssl enc -aes256 -salt -pass pass:"secret-key"
  • We find a number of inadequate approaches that do not make it for a secure solution:
    • Symmetric keys are a No-Go as they are available in two places and leave it up to the implementation where to store the key.
    • Obfuscation is a No-Go as it does not resist to any serious attack.

The preferred solution with JS7 is to use asymmetric keys:

  • Encryption and decryption is performed directly by the related jobs.
  • No JS7 product is involved in encryption/decryption as otherwise the JS7 product would know the keys involved that potentially could be compromised by logging, database persistence etc.
  • Performing encryption/decryption by jobs limits the attack surface to the OS process executing the job. The job implementation is controlled by the user who can verify secure operation. This includes that for encryption/decryption the openssl open source utility is used.

Asymmetric Keys

The basic proceeding works like this:

  • Consider the parties involved and related use cases:
    • A job executed on Agent A should be parameterized by a variable holding a secret.
    • A job executed on Agent B retrieves a secret that should be forwarded to a job on Agent A and possibly to other Agents too.
  • Use of asymmetric keys allows 
    • to create and to store a private key on Agent A.
    • to use Agent A's public key on Agent B or any other system involved.
    • to manage encryption and decryption like this:
      • create a symmetric one-time key and an encrypted copy of the key derived from Agent A's public key.
      • encrypt a variable's value with the one-time key.
      • drop the one-time key and forward the encrypted copy of the one-time key and the variable holding the encrypted value to Agent A.
      • only Agent A will be able to decrypt the encrypted one-time key using its private key which reveals the symmetric key required to decrypt the variable value.

Solution Outline

The solution is provided for download and can be used to automate encryption and decryption of variables.

  • The solution is available for Linux and MacOS® using bash shell.
  • The solution is intended as a baseline example for customization by JS7 users and by SOS within the scope of professional services.

Solution for Unix Shell Jobs

Managing the private/public key pair

Step 1: Create a private/public key pair

The following step is performed on the server hosting the Agent that should decrypt variables using the openssl utility from the command line:

Example how to create private/public key pair
# navigate to the Agent's <agent-data>/config/private directory
cd /var/sos-berlin.com/js7/agent/config/private

# create the private key file using "jobscheduler" as a passphrase, starting with: -----BEGIN RSA PRIVATE KEY-----
openssl genrsa -aes256 -passout pass:"jobscheduler" -out agent-pkcs1.key 2048

# convert key from pkcs#1 to pkcs#8, starting with: -----BEGIN ENCRYPTED PRIVATE KEY-----
openssl pkcs8 -inform PEM -topk8 -in agent-pkcs1.key -out agent.key

# extract the agent.pub public key file from agent.key private key file
openssl rsa -passin pass:"jobscheduler" -in agent.key -pubout > agent.pub

Step 2: Make public key available

Copy the public key to the server(s) hosting the Agent(s) that should encrypt variables:

Example where to copy the public key
# navigate to the Agent's <agent-data>/config directory
cd /var/sos-berlin.com/js7/agent/config

# copy the agent.pub public key file from Step 1 to the current location using scp or a file transfer tool

Setting up the Example

The example introduces a JS7 - Script Include and a workflow holding two jobs to encrypt and to decrypt variables.

First Job: encrypt-variable

The fist job encrypt-variable is implemented like this:

Example how to encrypt variables from a job
#!/bin/bash
set -e

# encrypt variable values using the target Agent's public key
##!include CryptoShell

EncryptVariable myVar1 "secret1"
EncryptVariable myVar2 "secret2"


Explanation:

  • The job makes use of JS7 - Script Includes: the CryptoShell Script Include holds the Shell functions used in the job.
    • The ##!include CryptoShell inserts the Shell code available from the indicated CryptoShell Script Include.
    • The Script Include is invoked once per job and optionally can be parameterized to specify the location of the public key.
      • ##!include CryptoShell --replace="<public-key>","/var/sos-berlin.com/js7/agent/config/agent.pub"
      • The first argument of the --replace option is a placeholder available with the CryptoShell Script Include.
      • The second argument represents the value by which the placeholder will be replaced. The above value corresponds to the default value that will be used if the Script Include is invoked without replacement options: the public key is looked up from a file with the name agent.pub in the Agent's <agent-data>/config directory.
  • The EncryptVariable Shell function expects the name of the variable and the value that should be encrypted:
    • EncryptVariable <name> <value> [<key-name> [<public-key>]]
      • <name>: The name of the variable is required.
      • <value>: The value of the variable that should be encrypted is required.
      • <key-name>: The name of a second variable holding the encrypted symmetric key. Defaults to <name>_key.
      • <public-key>: The path to the public key file is specified. Defaults to <agent-data>/config/agent.pub.
    • The Shell function will encrypt the variable value using the indicated public key.
    • The variable and its encrypted value will be forwarded to subsequent jobs and instructions in the workflow.

Second Job: decrypt-variable

The second job decrypt-variable maps workflow variables to environment variables like this:


Explanation:

  • MY_VAR1: environment variable that holds the encrypted value of the myVar1 workflow variable created by the encrypt-variable job.
  • MY_VAR1_KEY: environment variable that holds the encrypted value of the symmetric key. The variable is implicitly created by the encrypt-variable job.
  • MY_VAR2, MY_VAR2_KEY: similar to above variables.


The second job decrypt-variable is implemented like this:

Example how to decrypt variables in a job
#!/bin/bash
set -e

# decrypt variable values using the Agent's private key
##!include CryptoShell

echo "$(DecryptVariable "${MY_VAR1}" "${MY_VAR1_KEY}")"
echo "$(DecryptVariable "${MY_VAR2}" "${MY_VAR2_KEY}")"


Explanation:

  • The job makes use of JS7 - Script Includes: the CryptoShell Script Include holds the Shell functions used in the job.
    • The ##!include CryptoShell inserts the Shell code available from the indicated CryptoShell Script Include.
    • The Script Include can be invoked with repeated --replace=<what>,<with> options.
      • The Script Include optionally can be parameterized to specify the location of the private key.
        • ##!include CryptoShell --replace="<private-key>","/var/sos-berlin.com/js7/agent/config/private/agent.key"
        • The first argument of the --replace option is a placeholder available with the CryptoShell Script Include.
        • The second argument represents the value by which the placeholder will be replaced. The above value represents the default value that will be used of the Script Include is invoked without replacement options.
      • The Script Include can be parameterized to specify a passphrase required by the private key.
        • ##!include CryptoShell --replace="<passphrase>","jobscheduler"
        • The Script Include holds the above passphrase as a default value. Users should consider to change or to drop the default passphrase.
  • The DecryptVariable function expects the encrypted value of the variable and the encrypted value of the symmetric key:
    • DecryptVariable <value> <key> [<private-key> [<passphrase>]]
      • <value>: The encrypted value of the variable is required.
      • <key>: The value of the variable holding the encrypted symmetric key is required.
      • <private-key>: The path to the private key file is specified. Defaults to <agent-data>/config/private/agent.key.
      • <passphrase>: The passphrase of the private key is specified.
    • The function will decrypt the encrypted symmetric key and will decrypt the encrypted value using the decrypted symmetric key.
  • The DecryptVariable function returns the secret that can be assigned an environment variable or other function.
  • It is recommended not to write the secret to a file or to perform any operation that will expose the secret to logging of output in the stdout and stderr channels.

Script Include: CryptoShell

The CryptoShell Script Include is located in the related inventory folder:

The CryptoShell Script Include is implemented like this:


Explanation:

  • The CryptoShell Script Include implements the EncryptVariable and DecryptVariable Shell functions.
  • Both functions create a temporary file for the symmetric key in the Agent's work directory. The Script Include implements a trap to remove the symmetric key file on termination of the job.
  • Encryption and decryption is performed using the openssl utility.

Solution for PowerShell Jobs on Unix/Windows

Managing the private/public key pair

Step 1: Create a private/public key pair

The following step is performed on the server hosting the Agent that should decrypt variables using the openssl utility from the command line:

Example how to create private/public key pair
# navigate to the Agent's <agent-data>/config/private directory
cd /var/sos-berlin.com/js7/agent/config/private

# create the private key file using "jobscheduler" as a passphrase, starting with: -----BEGIN RSA PRIVATE KEY-----
openssl genrsa -aes256 -passout pass:"jobscheduler" -out agent-pkcs1.key 2048

# convert key from pkcs#1 to pkcs#8, starting with: -----BEGIN ENCRYPTED PRIVATE KEY-----
openssl pkcs8 -inform PEM -topk8 -in agent-pkcs1.key -out agent.key

# extract the agent.pub public key file from agent.key private key file
openssl rsa -passin pass:"jobscheduler" -in agent.key -pubout > agent.pub

Step 2: Make public key available


Setting up the Example

The example introduces a JS7 - Script Include and a workflow holding two jobs to encrypt and to decrypt variables.

First Job: encrypt-variable

The fist job encrypt-variable is implemented like this:

Example how to encrypt variables from a job
@@setlocal enabledelayedexpansion & @@findstr/v "^@@[fs].*&" "%~f0" | pwsh.exe -NonInteractive -Command - & exit !errorlevel!/b&

$ErrorActionPreference = "stop"

# encrypt variable values using the target Agent's public key
##!include CryptoPowerShell

# optionally specify the location of the public key
## include CryptoPowerShell --replace="<public-key>","$env:JS7_AGENT_CONFIG_DIR/agent.pub"

Encrypt-Variable -Name myVar1 -Value "secret1"
Encrypt-Variable -Name myVar2 -Value "secret2"


Explanation:

  • The job makes use of JS7 - Script Includes: the CryptoPowerShell Script Include holds the PowerShell functions used in the job.
    • The ##!include CryptoPowerShell inserts the PowerShell code available from the indicated CryptoPowerShell Script Include.
    • The Script Include is invoked once per job and optionally can be parameterized to specify the location of the public key.
      • ##!include CryptoPowerShell --replace="<public-key>","/var/sos-berlin.com/js7/agent/config/agent.pub"
      • The first argument of the --replace option is a placeholder available with the CryptoPoserShell Script Include.
      • The second argument represents the value by which the placeholder will be replaced. The above value corresponds to the default value that will be used if the Script Include is invoked without replacement options: the public key is looked up from a file with the name agent.pub in the Agent's <agent-data>/config directory.
  • The Encrypt-Variable PowerShell function expects the name of the variable and the value that should be encrypted:
    • Encrypt-Variable -Name <name> -Value <value> [-KeyName <key-name>] [-PublicKey <public-key>]
      • <name>: The name of the variable is required.
      • <value>: The value of the variable that should be encrypted is required.
      • <key-name>: The name of a second variable holding the encrypted symmetric key. Defaults to <name>_key.
      • <public-key>: The path to the public key file is specified. Defaults to <agent-data>/config/agent.pub.
    • The PowerShell function will encrypt the variable value using the indicated public key.
    • The variable and its encrypted value will be forwarded to subsequent jobs and instructions in the workflow.

Second Job: decrypt-variable

The second job decrypt-variable maps workflow variables to environment variables like this:


Explanation:

  • MY_VAR1: environment variable that holds the encrypted value of the myVar1 workflow variable created by the encrypt-variable job.
  • MY_VAR1_KEY: environment variable that holds the encrypted value of the symmetric key. The variable is implicitly created by the encrypt-variable job.
  • MY_VAR2, MY_VAR2_KEY: similar to above variables.


The second job decrypt-variable is implemented like this:

Example how to decrypt variables in a job
@@setlocal enabledelayedexpansion & @@findstr/v "^@@[fs].*&" "%~f0" | pwsh.exe -NonInteractive -Command - & exit !errorlevel!/b&

$ErrorActionPreference = "stop"

# decrypt variable values using the Agent's private key
##!include CryptoPowerShell

Write-Output (Decrypt-Variable -Value $env:MY_VAR1 -Key $env:MY_VAR1_KEY)
Write-Output (Decrypt-Variable -Value $env:MY_VAR2 -Key $env:MY_VAR2_KEY)


Explanation:

  • The job makes use of JS7 - Script Includes: the CryptoPowerShell Script Include holds the PowerShell functions used in the job.
    • The ##!include CryptoPowerShell inserts the PowerShell code available from the indicated CryptoPowerShell Script Include.
    • The Script Include can be invoked with repeated --replace=<what>,<with> options.
      • The Script Include optionally can be parameterized to specify the location of the private key.
        • ##!include CryptoPowerShell --replace="<private-key>","/var/sos-berlin.com/js7/agent/config/private/agent.key"
        • The first argument of the --replace option is a placeholder available with the CryptoPowerShell Script Include.
        • The second argument represents the value by which the placeholder will be replaced. The above value represents the default value that will be used of the Script Include is invoked without replacement options.
      • The Script Include can be parameterized to specify a passphrase required by the private key.
        • ##!include CryptoPowerShell --replace="<passphrase>","jobscheduler"
        • The Script Include holds the above passphrase as a default value. Users should consider to change or to drop the default passphrase.
  • The Decrypt-Variable function expects the encrypted value of the variable and the encrypted value of the symmetric key:
    • Decrypt-Variable -Value  <value> -Key <key> [-PrivateKey <private-key> [-Passphrase <passphrase>]]
      • <value>: The encrypted value of the variable is required.
      • <key>: The value of the variable holding the encrypted symmetric key is required.
      • <private-key>: The path to the private key file is specified. Defaults to <agent-data>/config/private/agent.key.
      • <passphrase>: The passphrase of the private key is specified.
    • The function will decrypt the encrypted symmetric key and will decrypt the encrypted value using the decrypted symmetric key.
  • The Decrypt-Variable function returns the secret that can be assigned an environment variable or other function.
  • It is recommended not to write the secret to a file or to perform any operation that will expose the secret to logging of output in the stdout and stderr channels.

Script Include: CryptoPowerhell

The CryptoPowerShell Script Include is located in the related inventory folder:

The CryptoPowershell Script Include is implemented like this:


Explanation:

  • The CryptoPowershell Script Include implements the Encrypt-Variable and Decrypt-Variable Powershell functions.
  • Encryption and decryption is performed without external utilities.



  • No labels