Bootstrap CA¶
Now we'll actually create the CA.
Prepare the YubiKey¶
Insert the YubiKey and make sure it's detected:
ykman list
You should see something similar to the following:
YubiKey 5 Nano (5.4.3) [OTP+FIDO+CCID] Serial: 01234567
Check that all YubiKey PIV slots are empty and all of the secrets are default.
ykman piv info
If the YubiKey is ready, you should see no Slot
information, and there should
be a WARNING
notifying you that you are using the default PIN
, PUK
, and
Management Key
.
PIV version: 5.4.3
PIN tries remaining: 3/3
PUK tries remaining: 3/3
Management key algorithm: TDES
WARNING: Using default PIN!
WARNING: Using default PUK!
WARNING: Using default Management key!
CHUID: No data available
CCC: No data available
If the YubiKey has any occupied slots or any of the secrets are not set to the default values, it will need to be reset.
ykman piv reset
The YubiKey should now be prepared for use as the store for the CA private key.
Note
Leave the YubiKey connected for the remainder of this process.
Setup ca-boostrap
Toolkit¶
Create a suitable empty working directory and clone the
ca-bootstrap
toolkit into it:
git clone https://github.com/doubleu-labs/ca-bootstrap .
Run the setup script:
./scripts/setup.sh
This will create all of the required directories for CA initialization.
Copy the Github App private key that was downloaded earlier to the ./secrets
directory.
Configure ca.env
¶
CA Configuration:
CA_KEY_SPEC
: Choose between an RSA or ECDSA CA private key algorithm. Key sizes are restricted here for simplicity. - Valid RSA key sizes are: -RSA-3072
-RSA-4096
- Valid ECDSA key sizes are: -P-384
CA_YEARS
: The number of years your CA should be valid for.20
should be a good value as it will probably outlive your infrastructure if you're a Homelab user.
CA_SUBJECT
: An OpenSSL-format Distinguished Name (DN).- Must begin and end with, as well as each field delimited by, a
/
. - Example:
/CN=My Root CA 01/L=New York/S=New York/C=US/O=My Org/
- Must begin and end with, as well as each field delimited by, a
Deployment Configuration:
DEPLOY_APP_ID
: The App ID or Client ID of your Github AppDEPLOY_APP_KEY
: The file name of your App's private key within the./secrets
directory.DEPLOY_REPO_OWNER
: The owner (user or organization) of the CA repositoryDEPLOY_REPO_NAME
: The name of the CA repositoryDEPLOY_REPO_BRANCH
: The branch that CA assets will be deployed to- Also the branch that Github Pages will deploy from.
DEPLOY_PAGES_CUSTOM_DOMAIN
: (Optional) The custom domain CA assets will be accessed from. - Leave this variable blank if you'll be using the default Github Pages URL<OWNER>.github.io/<REPOSITORY>
DEPLOY_AIA_FILE
: The file name of your CA certificate as it will appear in the repository.DEPLOY_CDP_FILE
: The file name of your CA CRL as it will appear in the repository.
(Optional) Modify openssl.template.cnf
¶
There are a few options in the OpenSSL configuration file that you may want to change.
By default, Intermediate/Issuing CA certificates will be valid for 10 years
(3652 days). If you chose a CA_YEARS
values less than that, you will want to
change this to be less than the value that you chose in days.
[root_ca]
. . .
default_days = 3652
By default, the CA CRL will expire every 6 months (180 days). If you want to change this, then modify the following key:
[root_ca]
. . .
default_crl_days = 180
The final section you should consider is the DN Match Policy. This will restrict or modify the DN of Intermediate/Issuing Certificates that this CA will sign.
Valid values are:
optional
: This field, if contained in a CSR DN, will be copied to the signed certificate.supplied
: This field MUST be present in the CSR DNmatch
: This field MUST MATCH the corresponding field of the Root CA certiciate.
Any fields not present on the match policy will be stripped from the signed certificate if present in the CSR DN.
Example
If you have the Locality (L
), State (S
), and Country (C
) set on your
Root Certificate, and want these fields to match:
[match_pol]
commonName = supplied
localityName = match
stateOrProvinceName = match
organizationName = optional
organizationalUnitName = optional
countryName = match
domainComponent = optional
Example
If you have a Domain Component (DC
) set on your Root Certificate, such as
/CN=My Root CA 01/DC=example/DC=com/
, and you want ALL CSRs to
specify the same DC
(eg. /CN=My Sub CA 01/DC=example/DC=com
):
[match_pol]
commonName = supplied
localityName = optional
stateOrProvinceName = optional
organizationName = optional
organizationalUnitName = optional
countryName = optional
domainComponent = match
Initialize the CA¶
All that needs to be done now is to run the initialization script:
./scripts/initialize.sh
The script will verify that all required applications are available in your
$PATH
, verify that the YubiKey is in a default state, verfiy that all
all directories are empty, validate variables defined in the ca.env
file,
and finally verify that the the Github App has access to the target repository.
When everything is ready, you'll see a confirmation dialog similar to the following:
==========================
= Ready to initialize! =
==========================
!!! Confirm CA Attributes and Deployment Environment!
!!! Your new Root Certificate Authority (CA) is ready to be created.
!!! Subject:
!!! CN: My Root CA 01
!!! C: US
!!! Key: P-384
!!! Valid from: 01 January 2025 @ 00:00:00
!!! Valid to: 01 January 2045 @ 00:00:00
!!! AIA URL: http://wranders.github.io/test/My_Root_CA_01.crt
!!! CDP URL: http://wranders.github.io/test/My_Root_CA_01.crl
Do you want to continue? Type 'CONFIRM': CONFIRM
Type CONFIRM
to create the CA.
When everything is complete, you will see a large dialog giving you instructions on what to do next.
Next¶
Next, we'll need to modify the security settings of the secrets databases.