Skip to content

Commit

Permalink
Merge pull request #12 from kaysond/develop
Browse files Browse the repository at this point in the history
Improved automation support, java truststore, CI
  • Loading branch information
kaysond authored Dec 23, 2019
2 parents 9b7e966 + e023e95 commit 1a8fdd9
Show file tree
Hide file tree
Showing 6 changed files with 1,648 additions and 641 deletions.
11 changes: 11 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
language: bash
dist: bionic
before_install:
- sudo apt-get update
- sudo apt-get -y install aptitude
- sudo aptitude -y install nodejs npm openjdk-11-jdk shellcheck
- sudo npm install -g bats http-server
install: skip
script:
- bats ./test/test.bats
- shellcheck -e SC2015 -e SC2016 ./spki
124 changes: 117 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
[![Build Status](https://travis-ci.com/kaysond/spki.svg?branch=master)](https://travis-ci.com/kaysond/spki)
# Simple PKI
`spki` is a bash script wrapper for [OpenSSL](https://github.com/openssl/openssl) that generates and manages a simple PKI suitable for small deployments. It supports both CRL's and OCSP.

The wrapper is based on Jamie Nguyen's guide: [OpenSSL Certificate Authority](https://jamielinux.com/docs/openssl-certificate-authority/ )
## Installation
Copy `spki` to a location in your path. [Releases](https://github.com/kaysond/spki/releases) use [semantic versioning](https://semver.org/) to identify backwards-incompatible changes.
Copy the latest release of `spki` to a location in your path. [Releases](https://github.com/kaysond/spki/releases) use [semantic versioning](https://semver.org/) to identify backwards-incompatible changes.

## Configuration
The top of the script contains several configuration variables; the defaults correspond to the guide. External configuration methods that do not require script modification are also supported (see below).
Expand All @@ -14,8 +15,6 @@ The top of the script contains several configuration variables; the defaults cor

`INTRMDT_PREFIX` - Prefix for all Intermediate CA files

`CLIENT_ENCRYPTION` - Default encryption for client keys

### Certificate Revocation List (CRL)
CRL's are automatically generated during initialization if either or both of the DP variables are set. The Intermedate CA Certificate will use the Root CRL DP; all other generated certificates use the Intermediate CRL DP. CRL's are automatically updated on revocation. CRL's served over http should **not** use https. Since the CRL files are frequently regenerated, it is recommended to serve the file directly from the spki root folder, for example by using a soft link. Furthermore, the CRL's are checked during initialization and certificate creation, so it is recommended to prepare the server in advance.

Expand All @@ -30,6 +29,18 @@ OCSP signing keys are automatically generated during initialization if either or

`INTRMDT_OCSP`- Intermediate CA OCSP (e.g. 'URI:http://ocsp.domain.com')

### OpenSSL DN Defaults
`spki init` prompts for the default values for certificate Distinguished Name parts and stores them in the OpenSSL configuration file. These can also be specified programmatically by using the following variables:

* `countryName`
* `stateOrProvinceName`
* `localityName`
* `organizationalUnitName`
* `organizationName`
* `emailAddress`

(or set them to '.' to prevent prompting that field)

### External Configuration
Configuration can be specified externally, without modifying the script, via environment variables. The precedence order of the configuration methods is:
1. Configuration File
Expand All @@ -41,15 +52,17 @@ The configuration file can be specified in the environment variable `SPKI_CONFIG
```
ROOT_DIR=/root/ca
ROOT_PREFIX=root
countryName=US
```

Note: If this file is loaded, all other environment variables are ignored.

#### Environment Variables
The variables in the script itself can be overriden by environment variables. The environment variable name should be those in the script but prefixed with `SPKI_` (e.g. `SPKI_ROOT_DIR` and `SPKI_ROOT_CRL_DP`).
Variables defined in the script itself can be overriden by environment variables. The environment variable name should be those in the script but prefixed with `SPKI_` (e.g. `SPKI_ROOT_DIR` and `SPKI_ROOT_CRL_DP`).

## Usage
* `spki init` - Initialize the PKI. This process first sets up the default Subject fields in the OpenSSL configuration files, then generates the Root CA, Intermediate CA, and a combined CA chain file. CRL's and OCSP certificates are also generated
* `spki create (server | user) <file-prefix>` - Create and sign a key pair with the Intermediate CA. `server` or `user` specifies particular extensions to use. These can be modified by changing the configuration files after initialization. The `file-prefix` is prepended to various file extensions (`.key.pem`, `.cert.pem`, `.csr.pem`)
* `spki create (server | user | client_server) <file-prefix>` - Create and sign a key pair with the Intermediate CA. `server`, `user` or `client_server` specifies particular extensions to use. These can be modified by changing the configuration files after initialization. The `file-prefix` is prepended to various file extensions (`.key.pem`, `.cert.pem`, `.csr.pem`)
* `server`
* `nsCertType = server`
* `authorityKeyIdentifier = keyid,issuer:always`
Expand All @@ -60,13 +73,21 @@ The variables in the script itself can be overriden by environment variables. Th
* `nsCertType = client, email`
* `authorityKeyIdentifier = keyid,issuer`
* `keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment`
* `extendedKeyUsage = clientAuth, emailProtection`
* `extendedKeyUsage = clientAuth, emailProtection`

* `client_server`
* `nsCertType = client, server`
* `authorityKeyIdentifier = keyid,issuer`
* `keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment`
* `extendedKeyUsage = clientAuth, serverAuth`

* `spki create-intermediate` - Recreate the Intermediate CA key and certificate. This command also regenerates the Intermediate CRL if necessary
* `spki sign (server | user) <CSR> <certificate>` - Sign a specified `CSR` file with the `server` or `user` extensions (see above). `certificate` specifies the output file
* `spki sign (server | user | client_server) <CSR> <certificate>` - Sign a specified `CSR` file with the `server`, `user` or `client_server` extensions (see above). `certificate` specifies the output file
* `spki list` - List all of the certificates signed by the Intermediate CA, including expiration times and revocation times
* `spki verify-intermediate` - Dump the intermediate CA certificate information and verify the chain of trust using the Root CA certificate
* `spki verify (certificate | file-prefix)` - Dump the certificate information and verify the chain of trust using the Root CA->Intermediate CA chain. Can be specified as a file or as the prefix used in `spki create`
* `spki export-pkcs12 <file-prefix>` - Export the key, certificate, and CA chain file to pkcs12 format
* `spki export-truststore <file-prefix>` - Export CA chain file to pkcs12 format compatible with java expectations. Requires keytool (bundled with java)
* `spki revoke (certificate | file-prefix) [reason]` - Revoke the specified certificate. `reason` can be one of: `unspecified`, `keyCompromise`, `CACompromise`, `affiliationChanged`, `superseded`, `cessationOfOperation`, `certificateHold`. This command automatically regenerates the Intermediate CRL
* `spki revoke-intermediate [reason]` - Revoke the Intermediate CA certificate. `reason` can be one of the options above. This command automatically regenerates the Root CRL
* `spki list-crl` - Dump information about the CRL's and the revoked certificates
Expand All @@ -76,10 +97,99 @@ The variables in the script itself can be overriden by environment variables. Th
* `spki ocsp-query <url> (certificate | file-prefix) [-rootca]` - Send an OCSP query for the specified certificate to the specified url (e.g. http://127.0.0.1:12345). The command uses the full chain file by default, suitable for verifying certificates signed by the Intermediate CA. Specify `-rootca` to use just the Root CA, suitable for verifying the Intermediate CA certificate.
* `spki update-config` - Regenerate the openssl configuration files. This allows the configuration variables, such as CRL or OCSP to be updated. It re-prompts for the certificate defaults.

## Automating `spki init`

You can automate the PKI initialization by doing the following.

Prepare a configuration file named `config`, making sure to specify default DN parts (`countryName`, `stateOrProvinceName`, `localityName`, etc.) i.e.:
```
ROOT_DIR=/tmp/spki/
countryName=PL
stateOrProvinceName=Warsaw
localityName=Warsaw
organizationalUnitName=Developers
organizationName=Company Ltd
[email protected]
```

Then use following script to create the PKI and a certificate in one go:
```bash
SPKI_CONFIG_FILE=$(pwd)/config
export SPKI_CONFIG_FILE

source $SPKI_CONFIG_FILE

ROOT_PRIVATE_KEY_PASSWORD="<INSERT PASSWORD HERE>"
ROOT_COMMON_NAME="Root CA"
ROOT_COUNTRY_NAME="$countryName"
ROOT_PROVINCE_NAME="$stateOrProvinceName"
ROOT_LOCALITY_NAME="$localityName"
ROOT_ORGANIZATION_NAME="$organizationName"
ROOT_ORGANIZATIONAL_UNIT_NAME="$organizationalUnitName"
ROOT_MAIL="$emailAddress"

INTERMEDIATE_COMMON_NAME="Intermediate CA"
INTERMEDIATE_COUNTRY_NAME="$countryName"
INTERMEDIATE_PROVINCE_NAME="$stateOrProvinceName"
INTERMEDIATE_LOCALITY_NAME="$localityName"
INTERMEDIATE_ORGANIZATION_NAME="$organizationName"
INTERMEDIATE_ORGANIZATIONAL_UNIT_NAME="$organizationalUnitName"
INTERMEDIATE_MAIL="$emailAddress"

INTERMEDIATE_PRIVATE_KEY_PASSWORD="<INSERT PASSWORD HERE>"

ANYKEY="k"
YES="y"

./spki init <<EOF
$ROOT_PRIVATE_KEY_PASSWORD
$ROOT_PRIVATE_KEY_PASSWORD
$ROOT_COMMON_NAME
$ROOT_COUNTRY_NAME
$ROOT_PROVINCE_NAME
$ROOT_LOCALITY_NAME
$ROOT_ORGANIZATION_NAME
$ROOT_ORGANIZATIONAL_UNIT_NAME
$ROOT_MAIL
$ANYKEY$INTERMEDIATE_PRIVATE_KEY_PASSWORD
$INTERMEDIATE_PRIVATE_KEY_PASSWORD
$INTERMEDIATE_COMMON_NAME
$INTERMEDIATE_COUNTRY_NAME
$INTERMEDIATE_PROVINCE_NAME
$INTERMEDIATE_LOCALITY_NAME
$INTERMEDIATE_ORGANIZATION_NAME
$INTERMEDIATE_ORGANIZATIONAL_UNIT_NAME
$INTERMEDIATE_MAIL
$YES
$YES
$ANYKEY
EOF

CERT_PRIVATE_KEY_PASSWORD="<INSERT PASSWORD HERE>"
CERT_COMMON_NAME="Test client_server"
./spki create client_server test <<EOF
$CERT_PRIVATE_KEY_PASSWORD
$CERT_PRIVATE_KEY_PASSWORD
$CERT_COMMON_NAME
$ROOT_COUNTRY_NAME
$ROOT_PROVINCE_NAME
$ROOT_LOCALITY_NAME
$ROOT_ORGANIZATION_NAME
$ROOT_ORGANIZATIONAL_UNIT_NAME
$ROOT_MAIL
$INTERMEDIATE_PRIVATE_KEY_PASSWORD
$YES
$YES
$ANYKEY
EOF
```

## Examples
* [`spki init`](https://asciinema.org/a/238438)

* [`spki create, spki revoke`](https://asciinema.org/a/238544)

* [`spki ocsp-responder, spki ocsp-query`](https://asciinema.org/a/238767)

## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md)
Loading

0 comments on commit 1a8fdd9

Please sign in to comment.