Created
March 9, 2016 01:55
-
-
Save justnoise/00e4bfecb84eeb4013fc to your computer and use it in GitHub Desktop.
Flocker CA using openssl
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| [ 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 |
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
Not saying we need to make these changes right now but a few comments.
For https://gist.github.com/justnoise/00e4bfecb84eeb4013fc#file-generate_flocker_certs-sh-L30 maybe we should allow them to pass a json,csv,yml file containing their nodes. Also can these be generic names? (node1, node2, node3) as I know the DNS names of nodes may be unknown until provisioned. This could be a non issue if they run this during creation time.
For https://gist.github.com/justnoise/00e4bfecb84eeb4013fc#file-generate_flocker_certs-sh-L26 +1
Also, maybe the cluster name and openssl.cnf are arguments too, but seems excessive.
Overall this is awesome @justnoise , having the commands is generally what they asked for, so this is great. More feedback once i try it out.