Step CA setups
Sub CA usage as ACME endpoint
- Setup smallstep repository:
cat <<EOF > /etc/yum.repos.d/smallstep.repo
[smallstep]
name=Smallstep
baseurl=https://packages.smallstep.com/stable/fedora/
enabled=1
repo_gpgcheck=0
gpgcheck=1
gpgkey=https://packages.smallstep.com/keys/smallstep-0x889B19391F774443.gpg
EOF
- Install
step-caandstepwithdnf install step-ca step-cli - Init the step-ca with
step ca init - Use
Standalone - Name the CA i.e.
subca01 - Add all the FQDNs the CA should listen on i.e.
subca01.example.com - To bind on 443 on every IP use
:443 - Define the mail address of the first provisioner i.e.
subca01@example.com - Let it generate a password with
[enter]and a second time to save (this password is not used and will be deleted soon again) - Delete the root_ca_key with
rm ~/.step/secrets/* - Change the
root_ca.crtto the public certificate of your root_ca withvi ~/.step/certs/root_ca.crt - Add a safe enough password to the
key.passfile withvi ~/.step/key.pass(you can use the generated cert from the init) - Create the CSR for the intermediate_ca:
step certificate create <subject-of-cert> intermediate.csr ~/.step/secrets/intermediate_ca_key --csr [--san subca01.example.com [--san subca01.example.com]] --password-file ~/.step/key.pass
- Copy the CSR to the root_ca and sign it
-
For ADCS it looks like that for signing:
batch certreq -submit -attrib "CertificateTemplate:SubCA" intermediate.csr intermediate.crt -
Copy the signed public cert back to the machine with
vi ~/.step/certs/intermediate_ca.crt - Add the ACME endpoint with
step ca provisioner add acme --type ACME - Remove the JWK endpoint with
step ca provisioner remove subca01@example.com --type JWK(with the mail address from the init) - Move the whole configuration to the
/etcwithmv ~/.step /etc/step-ca - Create a folder in
/var/libwithmkdir /var/lib/step-ca - Move the database to that folder with
mv /etc/step-ca/db /var/lib/step-ca - Change the paths from
~/.stepto/etc/step-cain the two filesconfig/defaults.jsonandconfig/ca.json - And change the
db.dataSourcepath to/var/lib/step-ca/dbin theconfig/ca.jsonfile - Create an account for the service with
useradd --system --home /etc/step-ca --shell /bin/false step - Fix the permissions for both directories:
chown -R step:step /etc/step-ca
restorecon -R /etc/step-ca
chmod u=r,g=,o= /etc/step-ca/key.pass
chown -R step:step /var/lib/step-ca
restorecon -R /var/lib/step-ca
- Create the systemd config with
vi /etc/systemd/system/step-ca.serviceand the content:
[Unit]
Description=step-ca service
Documentation=https://smallstep.com/docs/step-ca
Documentation=https://smallstep.com/docs/step-ca/certificate-authority-server-production
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=30
StartLimitBurst=3
ConditionFileNotEmpty=/etc/step-ca/config/ca.json
ConditionFileNotEmpty=/etc/step-ca/key.pass
[Service]
Type=simple
User=step
Group=step
Environment=STEPPATH=/etc/step-ca
WorkingDirectory=/etc/step-ca
ExecStart=/usr/local/bin/step-ca config/ca.json --password-file key.pass
ExecReload=/bin/kill --signal HUP $MAINPID
Restart=on-failure
RestartSec=5
TimeoutStopSec=30
StartLimitInterval=30
StartLimitBurst=3
; Process capabilities & privileges
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
SecureBits=keep-caps
NoNewPrivileges=yes
; Sandboxing
ProtectSystem=full
ProtectHome=true
RestrictNamespaces=true
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
PrivateTmp=true
PrivateDevices=true
ProtectClock=true
ProtectControlGroups=true
ProtectKernelTunables=true
ProtectKernelLogs=true
ProtectKernelModules=true
LockPersonality=true
RestrictSUIDSGID=true
RemoveIPC=true
RestrictRealtime=true
SystemCallFilter=@system-service
SystemCallArchitectures=native
MemoryDenyWriteExecute=true
ReadWriteDirectories=/var/lib/step-ca/db
[Install]
WantedBy=multi-user.target
- Reload systemd with
systemctl daemon-reload - Start the systemd service with
systemctl enable --now step-ca.service - And finally open the firewall:
firewall-cmd --add-service=https --permanent
firewall-cmd --reload
- To use some
stepcommands after the move you will need to add some variables to your profile (like the~/.bashrc):
export STEPPATH=/etc/step-ca
export STEP_CA_URL=https://subca01.example.com
export STEP_ROOT=/etc/step-ca/certs/root_ca.crt
Production considerations
PostgreSQL as database
- Before installing setup a PostgreSQL database:
dnf install postgresql-server
postgresql-setup initdb
- Change the 2
host all alllines from ident tomd5(unfortunatelyscram-sha-256does not work)
systemctl enable --now postgresql
sudo -u postgres psql
- And inside psql run:
create database stepca;
create user stepca with encrypted password '<strong-password>';
grant all privileges on database stepca to stepca;
- After the init, change the db settings in
~/.step/config/ca.json:
"db": {
"type": "postgresql",
"dataSource": "postgresql://stepca:<strong-password>@127.0.0.1:5432/",
"database": "stepca"
}
Active revocation
For all CRLs provided in the certificates, the crlDistributionPoints variable has to exactly match the CDP variable in the CRL!
By default the idpURL is https://<ca-fqdn>/1.0/crl.
Intermediate CA certificates
- Before creating the CSR create a template file in
~/.step/templates/intermediate.tplwith the following content:
{
"subject": {{ toJson .Subject }},
"keyUsage": ["certSign", "crlSign"],
"basicConstraints": {
"isCA": true,
"maxPathLen": 0
},
"issuingCertificateURL": "http://crl.example.com/rootca.crt",
"crlDistributionPoints": ["http://subca01.example.com/1.0/crl"]
}
- After that run the this command instead of the other CSR create:
step certificate create <subject-of-cert> intermediate.csr ~/.step/secrets/intermediate_ca_key --csr [--san <subject-of-cert>.example.com [--san subca01.example.com]] --password-file ~/.step/key.pass --template intermediate.tpl
Client certificates
For custom client certificates for either all or specific providers setup a template for each case.
- Create a template like
templates/server.tpl:
{
"subject": {{ toJson .Subject }},
"sans": {{ toJson .SANs }},
{{- if typeIs "*rsa.PublicKey" .Insecure.CR.PublicKey }}
"keyUsage": ["keyEncipherment", "digitalSignature"],
{{- else }}
"keyUsage": ["digitalSignature"],
{{- end }}
"extKeyUsage": ["serverAuth", "clientAuth"],
"issuingCertificateURL": "http://crl.example.com/subca01.crt",
"crlDistributionPoints": ["http://subca01.example.com/1.0/crl"]
}
- And then reference the templates relative path in the
ca.jsonconfig file