Skip to content

Instantly share code, notes, and snippets.

@justnoise
Created March 9, 2016 01:55
Show Gist options
  • Select an option

  • Save justnoise/00e4bfecb84eeb4013fc to your computer and use it in GitHub Desktop.

Select an option

Save justnoise/00e4bfecb84eeb4013fc to your computer and use it in GitHub Desktop.
Flocker CA using openssl
#!/bin/bash
# README:
# the first time you run this, you'll need to setup your
# certificate store (feel free to create these directories
# whereever you feel is appropriate):
#
# mkdir $HOME/ssl
# cd $HOME/ssl
# mkdir csr newcerts
# touch index.txt
# echo 1000 > serial
#
# you will also need to update the CA_default section of openssl.cnf
# to point at your ssl directory.
#
# most of this was taken from this tutorial:
# https://jamielinux.com/docs/openssl-certificate-authority/index.html
# and combined with the implementation in flocker/flocker/ca/_ca.py
################################################################################
# Config: The user must fill in these variables based on their cluster setup:
#
# fill in one of the following variables with the ip/dns of the
# cluster's control-service
# TODO: these should be command line args
control_service_dns="ec2-52-36-190-217.us-west-2.compute.amazonaws.com"
control_service_ip=""
# fill in the nodes to generate certs for the nodes
nodes[0]=ec2-52-37-214-228.us-west-2.compute.amazonaws.com
nodes[1]=ec2-52-37-216-48.us-west-2.compute.amazonaws.com
# cluster name should be unique for each cluster you have
cluster_name=mycluster
# this is the path to
openssl_cnf_path=./openssl.cnf
################################################################################
# set the CERT_HOST_ID environment variable early on since its used in
# openssl.cnf
if [ $control_service_dns != "" ]; then
export CERT_HOST_ID=DNS:control-service,DNS:$control_service_dns
control_host=$control_service_dns
else
export CERT_HOST_ID=DNS:control-service,IP:$control_service_ip
control_host=$control_service_ip
fi
# ----------------------------------------
# generate the CA:
# ----------------------------------------
cluster_uuid=$(uuidgen)
cluster_key_path=cluster.key
cluster_crt_path=cluster.crt
subject="/CN=$cluster_name/OU=$cluster_uuid"
openssl genrsa -out $cluster_key_path 4096
openssl req -batch -config $openssl_cnf_path -key $cluster_key_path -new -x509 -days 7300 -sha256 -extensions v3_ca -subj "$subject" -out $cluster_crt_path
# ----------------------------------------
# generate the control cert and keypair
# ----------------------------------------
# these end up getting copied to the nodes as control-service.(key|crt)
# but we'll create them like the docs tell us to...
control_key_path=control-$control_host.key
control_csr_path=csr/control-$control_host.csr
control_crt_path=control-$control_host.crt
subject="/CN=control-service/OU=$cluster_uuid"
# key
openssl genrsa -out $control_key_path 4096
# cert request
#openssl req -config $openssl_cnf_path -key $control_key_path -new -days 7300 -sha256 -subj "$subject" -out $control_csr_path
openssl req -config $openssl_cnf_path -key $control_key_path -new -days 7300 -sha256 -subj "$subject" -extensions control_service_extension -out $control_csr_path
# cert
#openssl ca -batch -config $openssl_cnf_path -keyfile $cluster_key_path -cert $cluster_crt_path -days 7300 -notext -md sha256 -extfile $host_extension_path -in $control_csr_path -subj "$subject" -out $control_crt_path
openssl ca -batch -config $openssl_cnf_path -keyfile $cluster_key_path -cert $cluster_crt_path -days 7300 -notext -md sha256 -extensions control_service_extension -in $control_csr_path -subj "$subject" -out $control_crt_path
#----------------------------------------
# Generate the node cert and keypair
#----------------------------------------
# you will need to do this for each node in your cluster
for node_hostname in ${nodes[@]}; do
mkdir $node_hostname
node_uuid=$(uuidgen)
node_key_path=$node_hostname/node-$node_uuid.key
node_csr_path=csr/node-$node_uuid.csr
node_crt_path=$node_hostname/node-$node_uuid.crt
# key
openssl genrsa -out $node_key_path 4096
# cert request
subject="/CN=node-$node_uuid/OU=$cluster_uuid"
openssl req -config $openssl_cnf_path -key $node_key_path -new -sha256 -subj "$subject" -out $node_csr_path
# cert
openssl ca -batch -config $openssl_cnf_path -keyfile $cluster_key_path -cert $cluster_crt_path -days 7300 -notext -md sha256 -in $node_csr_path -subj "$subject" -out $node_crt_path
done
#generate api cert and keypair
#----------------------------------------
api_username=api_user
api_key_path=$api_username.key
api_csr_path=csr/$api_username.csr
api_crt_path=$api_username.crt
subject="/CN=user-$api_username/OU=$cluster_uuid"
# key
openssl genrsa -out $api_key_path 4096
# cert request
openssl req -config $openssl_cnf_path -key $api_key_path -new -sha256 -subj "$subject" -out $api_csr_path
# cert
openssl ca -batch -config $openssl_cnf_path -keyfile $cluster_key_path -cert $cluster_crt_path -days 7300 -notext -md sha256 -in $api_csr_path -subj "$subject" -extensions client_api_ext -out $api_crt_path
[ ca ]
# `man ca`
default_ca = CA_default
[ CA_default ]
# Directory and file locations.
# feel free to change these locations to fit your environment
# while we don't use them, they're (mostly) required
dir = /home/bcox/ssl_test
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
RANDFILE = $dir/private/.rand
unique_subject = no
# For certificate revocation lists.
crlnumber = $dir/crlnumber
crl = $dir/crl/ca.crl.pem
crl_extensions = crl_ext
default_crl_days = 30
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days = 7300
preserve = no
policy = policy_not_strict
# lets be lenient so we can recreate certs
[ policy_not_strict ]
# policy for root CA signing, we're very lax
countryName = optional
stateOrProvinceName = optional
organizationName = optional
organizationalUnitName = supplied
commonName = supplied
emailAddress = optional
[ req ]
# Options for the `req` tool (`man req`).
default_bits = 4096
distinguished_name = req_distinguished_name
string_mask = utf8only
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
# Extension to add when the -x509 option is used.
x509_extensions = v3_ca
[ v3_ca ]
# Extensions used by flocker's CA
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = CA:true, pathlen:0
keyUsage = cRLSign, keyCertSign
[ control_service_extension ]
subjectAltName = $ENV::CERT_HOST_ID
[ client_api_ext ]
# make it a client cert
extendedKeyUsage = clientAuth
[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
organizationalUnitName = Organizational Unit Name
commonName = Common Name
@justnoise
Copy link
Author

Thanks for the feedback!

I certainly don't think this is a professional script for managing your nodes, instead, it's the cheapest script I could write showing HOW to use openssl to generate the certs. It wasn't really meant to be super usable for their purposes. If there's product interest, it can be significantly improved.

To answer your question about nodes: they can be named whatever the user wants. Heck, they don't really even need to be named anything, I simply chose to name the nodes (and put certs in their own directories) because that fits with some of the provisioning scripts I've written for myself.

If I've missed anything, it probably wasn't on purpose, I haven't explored many of the flocker features.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment