- Setting up TLS certificates for secure plugin communication in Snap
This document provides instructions on how to obtain certficates to evaluate TLS-secured plugin communication in Snap.
The following routines are described:
- Obtaining self-signed certificates for evaluation in local test environment
- Obtaining legitimate certificate from a public CA: Let's Encrypt
- Installing root certificate in OS for validating endpoints' certificates
- Starting telemetry workflow with secured plugin communication.
- This document is not intended to be a definite guide to obtaining certificates. It aims only as a guide for user to understand how Snap works with certificates. Each organization has to review its own requirements prior to obtaining certificates or setting up any secure communication scheme
- Note that this guide doesn't cover how to handle certificate revocation, as that service is not supported yet in Snap. While it is not on our roadmap yet, you are more than welcome to influence the solution by posting a feature request.
This section describes how to obtain certificates signed by a local CA.
In the course of this guide user will establish a local CA, becoming able to establish local chains of trust. Thus the user will be able to generate certificates for Snap plugins and Snap daemon (snapteld
) that share a common trust root.
- CA private key should be protected, possibly on a dedicated machine or media
- Obtained certificates won't be valid outside local setup
- Install certstrap for generating test certificates. Further steps will assume that
certstrap
is available under$PATH
location. - Generate root CA certificate:
Relevant files:
certstrap init --cn "snaptest-ca" --o "snaptest" --ou "ca" --key-bits 2048 --years 1 --passphrase '<ca-secure-passphrase>'
./out/snaptest-ca.key
- CA's private key, encrypted with<ca-secure-passphrase>
; needs to be protected from unauthorized access./out/snaptest-ca.crt
- CA's public certificate, (a certificate root)
- Generate server certificate and key to use by plugins:
These steps will produce a private key certificate file necessary to establish secure TLS channel on server. Server's private key file should not be passphrase-protected (or each plugin would have to ask for passphrase on start), thus the first step specifies empty passphrase expliclitly.
certstrap request-cert --cn "snaptest-srv" --ip "127.0.0.1" --domain "localhost" --passphrase '' --key-bits 2048 --o "snaptest" --ou "server" certstrap sign "snaptest-srv" --CA "snaptest-ca" --passphrase '<ca-secure-passphrase>' --years 1
Note that the second step (signing a private key) passes<ca-secure-passphrase>
to access CA's private key.
Relevant files:./out/snaptest-srv.key
- server's private key./out/snaptest-srv.crt
- server's public certificate
- Generate client certificate and key to be used by framework:
This will produce a private key certificate file necessary to securely connect to plugins. Client's private key file should not be passphrase-protected, thus the first step specifies empty passphrase explicitly. Note that the second step (signing a private key) passes
certstrap request-cert --cn "snaptest-cli" --ip "127.0.0.1" --domain "localhost" --passphrase '' --key-bits 2048 --o "snaptest" --ou "client" certstrap sign "snaptest-cli" --CA "snaptest-ca" --passphrase '<ca-secure-passphrase>' --years 1
<ca-secure-passphrase>
to access CA's private key. Relevant files:./out/snaptest-cli.key
- client's private key./out/snaptest-cli.crt
- client's public certificate
Files that need to be given at plugin startup:
snaptest-ca.crt
- CA's certificatesnaptest-srv.key
- server's private key filesnaptest-srv.crt
- server's certificate file
Files that need to be given at snapteld
startup:
snaptest-ca.crt
- CA's certificatesnaptest-cli.key
- framework's private key filesnaptest-cli.crt
- framework's certificate file
This section describes how to obtain a certificate from CA authority. Example will be based on Let's encrypt public CA service.
In general, obtaining a TLS certificate involves:
- On customer side: issuing request to CA authority, specifying domain name and contact information
- On CA side: validating the customer's title to the requested domain
This guide will show how to obtain certificate for sample domains.
There's no way around the need to register a domain name to use this example. In this walkthrough we'll assume that domains frodo.buthey.net
and bilbo.buthey.net
were registered and their DNS records map to actual machines (VM or physical).
At the moment there's no way to use domain-bound certificates directly in Snap. That's a subject of ongoing implementation, and should be addressed by intelsdi-x/snap-plugin-lib-go#85. As soon as implementation is complete, this document will be updated.
-
Connect via SSH to a machine mapped to the domain
frodo.buthey.net
-
Make sure that machine has WWW ports open for listening:
80
and443
-
Install certbot, as directed by Let's encrypt instructions:
On Ubuntu:sudo add-apt-repository ppa:certbot/certbot sudo apt-get update sudo apt-get install certbot
On CentOS:
wget https://dl.eff.org/certbot-auto chmod a+x certbot-auto
(CentOS)
-
Request a certificate from Let's Encrypt using Certbot:
mkdir -p tmp/certbot/conf.d tmp/certbot/work.d tmp/certbot/log.d sudo certbot certonly -d frodo.buthey.net --standalone --config-dir tmp/certbot/conf.d/ --work-dir tmp/certbot/work.d/ --logs-dir tmp/certbot/log.d/ d=frodo.buthey.net; p=$(sudo find . -wholename "*live/$d"); for f in $(sudo ls -1 $p |grep .pem); do sudo cp $p/$f $(basename $p)-$f; done; sudo chown $(whoami) $d-*.pem
Resulting files:
frodo.buthey.net-privkey.pem
- private key file for domainfrodo.
frodo.buthey.net-cert.pem
- certificate file for domainfrodo.
frodo.buthey.net-chain.pem
- a certificate chain representing Let's encrypt CA (a certificate root)
This guide shows how to install root CA certificates in system. Having root CA certificates installed in system reduces complexity of TLS setup.
- Obtain a certificate root file (e.g.
snaptest-CA.crt
from the guides in this document) - Install the certificate in the system:
Sample output:
sudo cp snaptest-ca.crt /usr/local/share/ca-certificates/ sudo update-ca-certificates --verbose --fresh
Clearing symlinks in /etc/ssl/certs... done. Updating certificates in /etc/ssl/certs... Doing . WARNING: Skipping duplicate certificate ACCVRAIZ1.pem WARNING: Skipping duplicate certificate ACCVRAIZ1.pem 173 added, 0 removed; done.
- Obtain a certificate root file (e.g.
snaptest-ca.crt
from the guides in this document) - Install the certificate tooling and certificate in the system:
yum install ca-certificates update-ca-trust enable cp /opt/snap/certs/snaptest-ca.crt /etc/pki/ca-trust/source/anchors/ update-ca-trust extract
We'll assume the following files are all available:
snaptest-ca.crt
- certificate root - installed in systemsnaptest-srv.key
- server's private key filesnaptest-srv.crt
- server's certificate filesnaptest-cli.key
- framework's private key filesnaptest-cli.crt
- framework's certificate file
-
Start a new shell session and execute
snapteld
with certificate and key generated for client:snapteld -t 0 -l 1 --tls-cert=/tmp/snaptest-cli.crt --tls-key=/tmp/snaptest-cli.key
-
Load a plugin
Start a new shell session and load plugin built with snap-plugin-lib-go, e.g.
snap-plugin-collector-rand
fromsnap-plugin-lib-go
examples:snaptel plugin load --plugin-cert=/tmp/snaptest-srv.crt --plugin-key=/tmp/snaptest-srv.key snap-plugin-collector-rand
-
Create a sample task and watch the output:
snaptel task create -t sample-task.json snaptel task watch <task_id>
Sample output:
snaptel task create -t sample-task.json Task created ID: 167384ad-7643-43ef-930a-18455f5307a0 Name: Task-167384ad-7643-43ef-930a-18455f5307a0 State: Running snaptel task watch 167384ad-7643-43ef-930a-18455f5307a0 Watching Task (167384ad-7643-43ef-930a-18455f5307a0): NAMESPACE DATA TIMESTAMP /random/float 0.4507584997241038 2017-06-02 09:47:48.338103527 +0200 CEST /random/integer 2.79090919e+08 2017-06-02 09:47:48.338098827 +0200 CEST /random/string Yes definitely 2017-06-02 09:47:48.338109312 +0200 CEST Stopping task watch
Example
sample-task.json
is given below:{ "max-failures": 10, "schedule": { "interval": "3s", ` "type": "simple" }, "version": 1, "workflow": { "collect": { "metrics": { "/random/*": {} } } } }