Implements the KES api(s) required by Minio in KES mode. It uses then github.com/ThalesIgnite/crypto11 by Thales that uses pkcs#11 to interface to HSM (SoftHSM or Thales Luna).
The following is a toy created to explore the possibility to connect Minio (in GW mode, and a rather old version circa 2020 I believe) directly to an HSM. At the time I had the possibility to play with a Thales HSM so the support is for that and SoftHSM.Given my limited knowledge of encryption, it might contains subtle (or not so subtle) errors, so don't use it.
Also:
- No unit/integration tests.
- No crypto engineering analysis on how this was implemented.
- No crypto engineering analysis done to be 100% sure of 3rd party libraries (altough it is a Thales official library).
- No analysis of failure modes (since there are no tests); the code uses a fail-fast approach.
If you want to use a software HSM install the SoftHSM library https://github.com/opendnssec/SoftHSMv2
If you want to use Thales Luna HSM you need to install and configure the Luna network Client and the SDK on the same machine.
Install and configure GO Sdk, then make will generate the executable
Execute the binary with the relevant env variables
The service is configured via ENV variables and config files that modify the behaviour.
All the ENV variables must be placed in .env file passed as argument to the executable with -env.
KES_MODEput the web server indebugorproductionmode, default is:debugKES_HTTP_PORTport for HTTP endpoint, default8080, format:8080KES_HTTP_DISABLEdisable HTTP localhost server, default isnoKES_HTTPSif set the port for HTTPS endpoint, format:0.0.0.0:3000KES_HTTPS_CApath to ca pem (optional indebugmode)KES_HTTPS_CA_CLIENTSpath to client ca pem (optional indebugmode)KES_HTTPS_CA_SELFSIGNEDspecify if ca is selfsigned (cannot verify client certs of a selfsigned CA), default isnoselfsignedKES_HTTPS_CERTpath to certificate pemKES_HTTPS_KEYpath to key pemKES_HTTPS_FIPS_CYPHERSifonthe HTTPS endpoint will use only FIPS approved algorithms for TLS 1.2 and 1.3KES_HTTPS_AUTH_DISABLED(ONLY INdebug) ifondisable authentication based on mTLS certificatesKES_METRICSifonPrometheus metrics are available on/metrics(on any web server port)KES_CONFIG_AUTHpath to json containing auth mapsKES_CONFIG_HSMpath to json containing HSM config (crypto11library config file )KES_CONFIG_HSM_PINpin for the HSM config to override the json content (useful for fast debug)KES_CONFIG_KEYSpath to json containing keys id to internal id config
When started with KES_MODE=production the following behaviour is enforced by default:
- The HTTP server will not have the KES api endpoints
- The HTTPS server will always use authentication for the KES api endpoints
- No system CA will be used, only the one provided in the
KES_HTTPS_CAvariable - No system CA will be used, only the one provided in the
KES_HTTPS_CA_CLIENTSvariable KES_CONFIG_HSM_PINwill not be used
They can be anywhere, we've three types:
Controlled by KES_CONFIG_HSM
This is the config directly read by the Thales library, refer to https://github.com/ThalesIgnite/crypto11 for details
{
"Path": "/usr/safenet/lunaclient/lib/libCryptoki2_64.so",
"TokenSerial": "", // Token slot serial
"Pin": "", // Pin
"MaxSessions": 0 // Number of sessions, 0 means unlimited
}
Controlled by KES_CONFIG_KEYS
This is the config to define the relation between the key id requested by Minio and the id of the key on the HSM. It supports many aliases and keys to make rotation easily.
{
"keys": [
{
"name": "", // The key id requested by minio
"data": [
{
"id": "", // A unique name for the key, saved in minio headers
"internalid": "1994ce294ee025ace83271abc8a62257741eb6e7", // The id in HSM (a string of bytes in string form)
"valid": true // This is to mark this key for current encryption use
},
{
"id": "",
"internalid": "",
"valid": false // This mark the key for decryption use only, you can have one encryption key, but many decryption (rotation)
},
...
]
}
]
}
Controlled by KES_CONFIG_AUTH
This is the config to define the relation between the key id requested by Minio and the id of the certificate requesting it.
{
"certificates": [
{
"id": "", // The "Signature" parth of the client certificate, you can get it via openssl x509 -in key.pem -text -noout
"name": "", // Friendly name for this certificate
"keys": [
{
"id": "", // The key id requested by minio ("NAME" field in the keys config file)
"encrypt": true, // Can call encrypt endpoint for this key
"decrypt": true, // Can call decrypt endpoint for this key
"generate": true // Can call generate endpoint for this key
},
... // The list of object key requested by minio, for this client
]
}
],
"tlsproxy": {
"enabled": false,
"fingerprint": "----",
"header": "X-SSL-Client-Certificate",
"caverifier": "/home/furio/git/kes-hsm-go/self-signed-keys/chain.pem"
}
}
The TLS proxy section is used if reverse HTTPS proxy is being used.
In this case you must setup the reverse proxy to verify the certificates and send the public one over the header (in base64) specified in the header section: it will be loaded and verified against the caverifier root certificate, if valid it's fingerprint will be used as usual in the certificates section.
Since Minio in KES mode allows only mTLS connections also the reverse proxy should have a valid client certificate and it's fingerprint will be checked against the one in the field fingerprint.