The CAW driver is our native certificate authority driver. In essence, it is a shell script encompassing ordinary OpenSSL certificate authority. This has many pros:
It also has some cons:
CAW is a shell wrapper above the OpenSSL-based certificate authority (abbreviated: OSSL CA). It allows you to use the OSSL CA in a similar way the EasyRSA does. CAW is primarily created as a CA backend for the CzechIdM Certificate Authority module but it is possible to extend/incorporate it somewhere else. It also provides an user-friendly CA implementation which can be used right away from the command line.
For the list of capabilities and input/output formats, please refer to the CAW shell script. Simply run CAW to get the usage screen where you can find everything you will ever need. :)
./caw
Unknown command '' specified.
Usage: ./caw command [--param1 value1 --param2 value2 ...]
...
COMMAND create-key-and-cert - generates new private key, CSR and signs a certificate
OUTPUT
Success: Serial number of the issued certificate written onto STDOUT. Return code 0.
Error: Error message on STDERR. Return code 1.
PARAMETERS
--country countryName. Mandatory.
--state stateOrProvinceName. Mandatory.
--locality localityName. Mandatory.
--org organizationName. Mandatory.
--ou organizationalUnitName. Mandatory.
--cn commonName. Mandatory.
--mail emailAddress. Mandatory.
--pass private key passphrase. Mandatory.
... and so on ...
In its core, CAW uses a well-known OSSL CA all with its openssl.cnf file and such. Therefore every configuration which can be specified in openssl.cnf can be made available in the CAW. CAW makes use of openssl.cnf as often as possible (i.e. with defaults for the openssl req command) and very often invokes openssl using -batch argument.
But beware, CAW has also its own configuration file caw\_settings.source. This file contains some options that need to be in sync with options in ca\_openssl.cnf. So if you are fiddling with ca\_openssl.cnf, always also check caw\_settings.source.
Additional information can be found in one of those three places:
./caw.caw\_settings.source file./etc/openssl.cnf, it brings its own ca\_openssl.cnf along. That means, your CA is completely separated from others.openssl ca …) must not be invoked in multiple instances at the same time. CAW uses lockdir to prevent that.ca\_openssl.cnf and caw\_settings.source (and there is already a template for that).STDOUT) or an error (on STDERR).0, for error it is 1.policy_match in heterogenous environments../caw create-crl. Another user can then publish the CRL into public destination by calling ./caw publish-crl../caw housekeep.users group which encompasses all users.[root@ca ~]# useradd -r -m -s /bin/bash authority1
[root@ca ~]# mv caw.tgz /home/authority1/ [root@ca authority1]# tar xzf caw.tgz [root@ca authority1]# ll total 28 drwxr-xr-x 4 1000 users 4096 Aug 24 14:36 caw -rw-r--r-- 1 root root 24563 Aug 24 15:16 caw.tgz [root@ca authority1]# chown -Rf authority1:authority1 caw/ [root@ca authority1]# chmod 750 caw
caw script is runnable.[root@ca authority1]# cd caw/ [root@ca caw]# chmod 750 caw
01 but there is a caveat attached to this - OpenSSL then works with 8bit serial mode (this is potentially dangerous). Better way is to create truly random 128bit serial number as the example shows.[root@ca caw]# cd ca/ [root@ca ca]# openssl rand -hex 16 > serial
b1676557ad077ef7144c227d16a55025. Then we simply edit the starting serial to have our desired prefix (say, aaaccc000). Total length of the serial number must remain 128b, so our new serial will be aaaccc000d077ef7144c227d16a55025. Write it into the serial file. We can, possibly, overflow to the prefix aaaccc001 so be aware of it - our "prefix" is not a real prefix. It is merely a cleverly chosen starting number.ca\_crt.extensions file. Edit them (and command line parameters in the example below) according to your needs.[root@ca ca]# su - authority1 [authority1@ca ~]$ cd caw/ca/ [authority1@ca ca]$ pwd /home/authority1/caw/ca [authority1@ca ca]$ openssl genrsa -out private/ca.key 2048 [authority1@ca ca]$ chmod 400 private/ca.key [authority1@ca ca]$ openssl req -new -in private/ca.key -out ca.csr -key private/ca.key [authority1@ca ca]$ openssl x509 -req -in ca.csr -signkey private/ca.key -days 1000 -out ca.crt -sha256 -extfile ../ca_crt.extensions [authority1@ca ca]$ rm ca.csr
caw script for managing the authority. Do not delete them.ca\_openssl.cnf configuration file and configure your authority. This file is an ordinary openssl.cnf, but is realized in local variant. This enables multiple caw-based CAs to coexist one along the other just by separating their directories. The ca\_openssl.cnf contains preconfigured CA so only small adjustments should be necessary. Follow the comments in the file itself. The most important things to set up are:default\_days and default\_crl\_days and other certificate-related settings.req stanza - those are used for generating new keys and requests.issued\_cert\_ext stanza. Do not forget to set up the crlDistributionPoints correctly.caw\_settings.source configuration file and configure it accordingly. The tricky part there is that some settings have to have the same values as in ca\_openssl.cnf. Again, the comments in the file will help you. The most important things to set up are:CA\_OSSL\_ENGINE\_PARAM if you want to use PKCS11 token. Set it to an empty string if you store the CA's private key in the file.CA\_OSSL\_ROOT\_CHAIN if your CAW authority is not the root authority.SubjectDN and CSR validation prefixes. This also lets you set a basic policy for user's passphrase complexity. Also, set allowed signature algorithms.ca.key), deconfigure PKCS11 engine template according to this howto.[authority1@ca caw]$ ./caw create-crl
[root@ca ~]# ./caw create-key-and-cert --country CZ --state "Czech Republic" --locality Prague --org BCV --ou TEST --cn user.test.bcv --pass demodemo 0C0774BACDF2CA2A52BEEF68A0F1D411
[root@ca ~]# ./caw prolong-cert --serial 0C0774BACDF2CA2A52BEEF68A0F1D411 0C0774BACDF2CA2A52BEEF68A0F1D412
[root@ca ~]# ./caw get-cert --serial 0C0774BACDF2CA2A52BEEF68A0F1D411 --with-pkey --pass demodemo --with-chain MIIKoQIBAzCCCmcGCSqGSIb3DQEHAaCCClgEggpUMIIKUDCCBQcGCSqGSIb3DQEHBqCCBPgwggT0 ... FbAM6nS5jJYQ4s4VKDElMCMGCSqGSIb3DQEJFTEWBBRGj5/LUBZtcz/k+N96L7RzdleanDAxMCEw CQYFKw4DAhoFAAQUCqImx0Un2qmtSACpEWD4i2ivunMECFJnEuzDIEtHAgIIAA==
[root@ca ~]# ./caw revoke-cert --serial 0C0774BACDF2CA2A52BEEF68A0F1D411 --reason keyCompromise
[root@ca ~]# ./caw create-crl
[root@ca ~]# mkdir /data/volumes/czechidm/cert-authority
[root@ca ~]# unzip caw-master.zip -d /data/volumes/czechidm/cert-authority/ [root@ca ~]# mv /data/volumes/czechidm/cert-authority/caw-master /data/volumes/czechidm/cert-authority/caw
[root@ca ~]# cp customerCa.key /data/volumes/czechidm/cert-authority/caw/ca/private/ca.key [root@ca ~]# cp customerCa.pem /data/volumes/czechidm/cert-authority/caw/ca/ca.pem
[root@ca ~]# cd /data/volumes/czechidm/cert-authority/caw/ca/ [root@ca ca]# openssl rand -hex 16 > serial
[root@ca czechidm]# chown -Rf 999:998 cert-authority/ [root@ca czechidm]# chmod 400 cert-authority/caw/ca/private/ca.key [root@ca czechidm]# chmod 750 cert-authority/ [root@ca czechidm]# cd cert-authority/caw/ [root@ca caw]# chmod 750 caw
- type: bind
source: /data/volumes/czechidm/cert-authority
target: /opt/cert-authority
read_only: false
[Unit] Description=CRL refreshing After=network.target docker.service [Service] Type=simple ExecStart=/usr/bin/docker exec czechidm /opt/cert-authority/caw/caw create-crl
[Unit] Description=CzechIdM refresh CRL After=network.target docker.service [Timer] OnCalendar=*-*-* *:00:00 [Install] WantedBy=multi-user.target
[root@ca czechidm]# systemctl enable iam-crl-refresh.service iam-crl-refresh.timer
- type: bind
source: /data/volumes/czechidm/cert-authority/caw/ca/crl/ca.crl
target: /etc/nginx/crl/ca.crl
read_only: true
- location /crl/ca.crl {
root /etc/nginx/;
}
Then the crl file is available at URL:https://iam.appliance.tld/crl/ca.crl
By default, CAW comes with a preconfigured template for the PKCS11-enabled crypto engine. In some deployments, this is not necessary and the goal is to have CA's private key and certificate stored on the machine's filesystem. This short howto will show you how to swap preconfigured PKCS11 engine for the more usual setup.
The ca\_openssl.cnf file has several sections, referred as "stanzas". Stanza starts with [stanza name] and ends when another stanza starts.
To deconfigure the PKCS11 template:
ca\_openssl.cnf file.openssl\_conf = openssl\_init at the top of the file.[openssl\_init] stanza.[engine\_section] stanza.[pkcs11\_engine] stanza.[CA\_default] stanza, uncomment the private\_key = … line. Set it to a path to your private key or create private key in the $dir/private/ca.key path. The key has to have at most 600 (-rw\-\-\-\-\-\-\-) privileges.caw\_settings.source file.CA\_OSSL\_ENGINE\_PARAM="…" to CA\_OSSL\_ENGINE\_PARAM="" (empty variable).If you modify the example below according to those remarks, then your setup should be secure enough.
[root@ca ~]# openssl genrsa -out ca.key 4096
[root@ca ~]# openssl req -new -key ca.key -out ca.csr -sha512
[root@ca ~]# openssl x509 -req -days 3650 -in ca.csr -signkey ca.key -out ca.crt -sha512 -extfile ca_extensions.txt
-nocrypt option is a bad idea. But, again, we should be generating private key directly on the token.[root@ca ~]# openssl pkcs8 -in ca.key -topk8 -out ca_pk8.key -nocrypt
[root@ca ~]# softhsm2-util --init-token --slot 0 --label ca --so-pin 123456 --pin 1234 The token has been initialized. [root@ca ~]# softhsm2-util --pin 1234 --so-pin 123456 --import ca_pk8.key --label ca --id A1B2 --no-public-key --slot 0 The key pair has been imported.
[root@ca ~]# openssl engine -t dynamic -pre SO_PATH:/usr/lib64/openssl/engines/pkcs11.so -pre ID:pkcs11 -pre LIST_ADD:1 -pre LOAD -pre MODULE_PATH:/usr/lib64/pkcs11/libsofthsm2.so -pre VERBOSE -pre PIN:1234 (dynamic) Dynamic engine loading support Success: SO_PATH:/usr/lib64/openssl/engines/pkcs11.so Success: ID:pkcs11 Success: LIST_ADD:1 Success: LOAD Success: MODULE_PATH:/usr/lib64/pkcs11/libsofthsm2.so Success: PIN:1234 Loaded: (pkcs11) pkcs11 engine [ available ]
softhsm2-util –show-slots. Certificate signing should look basically like this (we used openssl shell in this snippet):[root@ca usercert]# openssl OpenSSL> engine -t dynamic -pre SO_PATH:/usr/lib64/openssl/engines/pkcs11.so -pre ID:pkcs11 -pre LIST_ADD:1 -pre LOAD -pre MODULE_PATH:/usr/lib64/pkcs11/libsofthsm2.so -pre VERBOSE -pre PIN:1234 (dynamic) Dynamic engine loading support Success: SO_PATH:/usr/lib64/openssl/engines/pkcs11.so Success: ID:pkcs11 Success: LIST_ADD:1 Success: LOAD Success: MODULE_PATH:/usr/lib64/pkcs11/libsofthsm2.so Success: VERBOSE Success: PIN:1234 Loaded: (pkcs11) pkcs11 engine PKCS#11: Initializing the engine Found 2 slots [ available ] OpenSSL> x509 -req -engine pkcs11 -CAkeyform engine -CAkey slot_0-label_ca -CA ca.crt -days 1000 -set_serial 15 -sha256 -in user.csr -out user.crt PKCS#11: Initializing the engine Found 2 slots engine "pkcs11" set. Signature ok subject=/C=CZ/ST=Czech Republic/L=Prague/O=BCV/OU=TEST/CN=user.test.bcv Getting CA Private Key Loading private key "slot_0-label_ca" Looking in slot 0 for key: label=ca [0] SoftHSM slot 0 login (ca) [1] SoftHSM slot 1 uninitialized, login (no label) Found slot: SoftHSM slot 0 Found token: ca Found 0 certificate: No private keys found. Loading private key "slot_0-label_ca" Looking in slot 0 for key: label=ca [0] SoftHSM slot 0 login (ca) [1] SoftHSM slot 1 uninitialized, login (no label) Found slot: SoftHSM slot 0 Found token: ca Found 0 certificate: Found 1 private key: 1 P id=ffffffa2ffffffb2 label=ca ^C
[root@ca usercert]# openssl verify -CAfile ca.crt user.crt user.crt: OK
[engine] section in the ca_openssl.cnf and supply the values you just used on the command line.CA\_OSSL\_ENGINE\_PARAM variable in the caw\_settings.source file. There is already template for that, the only value that needs changing should be an identifier of the PKCS11 slot.We are installing SoftHSM on CentOS 7 operating system. Then, we will configure it to run under authority1 OS user.
[root@ca ~]# yum install epel-release [root@ca ~]# yum install softhsm opensc engine_pkcs11
[root@ca ~]# cat /etc/softhsm2.conf # SoftHSM v2 configuration file directories.tokendir = /var/lib/softhsm/tokens/ objectstore.backend = file # ERROR, WARNING, INFO, DEBUG log.level = INFO
authority1 user can access.[root@ca ~]# su - authority1 [authority1@ca ~]$ pwd /home/authority1 [authority1@ca ~]$ mkdir -pv softhsm/tokens mkdir: created directory ‘softhsm’ mkdir: created directory ‘softhsm/tokens’ [authority1@ca ~]$ chmod 750 softhsm [authority1@ca ~]$ vim softhsm/softhsm2.conf [authority1@ca ~]$ cat softhsm/softhsm2.conf directories.tokendir = /home/authority1/softhsm/tokens/ objectstore.backend = file # ERROR, WARNING, INFO, DEBUG log.level = INFO
softhsm2-util program. This program reads environment variable SOFTHSM2\_CONF. When the variable is not defined, it uses configuration /etc/softhsm2.conf. We will export the variable with proper path to config file. If you modified the system-wide config, you can skip this step.[authority1@ca ~]$ export SOFTHSM2_CONF=/home/authority1/softhsm/softhsm2.conf
softhsm2-util and initialize a new token. Please DO NOT use PINs like 1234 or 123456 in the real world scenarios.[authority1@ca ~]$ softhsm2-util --init-token --slot 0 --label test_slot --pin 1234 --so-pin 123456
[authority1@ca ~]$ find /home/authority1/softhsm/tokens/ -type f /home/authority1/softhsm/tokens/ee48c4b2-b28e-8c2d-7921-59236dda0866/token.lock /home/authority1/softhsm/tokens/ee48c4b2-b28e-8c2d-7921-59236dda0866/generation /home/authority1/softhsm/tokens/ee48c4b2-b28e-8c2d-7921-59236dda0866/token.object
caw\_settings.source and append the export SOFTHSM2_CONF… line to it. This will make CAW use the configured store. If you modified the system-wide config, you can skip this step.