SSH keys management at scale !
A client / server app to ease management of PKI based SSH keys.
Developped for @leboncoin
https://nicolasbeguier.shost.ca/cassh.html
Table of Contents generated with DocToc
Server:
Python
Postgres
as backendopenssh-client
(ssh-keygen
)
CLI:
Python
OR docker
Add new key to cassh-server :
cassh add
Sign pub key :
cassh sign [--display-only] [--force]
Get public key status :
cassh status
Get ca public key :
cassh ca
Get ca krl :
cassh krl
Active Client username key :
cassh admin <username> active
Revoke Client username key :
cassh admin <username> revoke
Delete Client username key :
cassh admin <username> delete
Status Client username key :
cassh admin <username> status
Set Client username key :
cassh admin <username> set --set='expiry=+7d'
cassh admin <username> set --set='principals=username,root'
[user]
# name : this is the username you will use to log on every server
name = user
# key_path: This key path won\'t be used to log in, a copy will be made for the certificate.
# We assume that `${key_path}` exists and `${key_path}.pub` as well.
# WARNING: Never delete these keys
key_path = ~/.ssh/id_rsa
# key_signed_path: Every signed key via cassh will be put in this path.
# At every sign, `${key_signed_path}` and `${key_signed_path}.pub` will be created
key_signed_path = ~/.ssh/id_rsa-cert
# url : URL of cassh server-side backend.
url = https://cassh.net
# [OPTIONNAL] timeout : requests timeout parameter in second. (timeout=2)
# timeout = 2
# [OPTIONNAL] verify : verifies SSL certificates for HTTPS requests. (verify=True)
# verify = True
[ldap]
# realname : this is the LDAP/AD login user
realname = ursula.ser@domain.fr
# Python Pip
sudo apt-get install \
python-pip \
python-dev \
libsasl2-dev \
libldap2-dev \
libssl-dev \
libpq-dev
pip install -r src/server/requirements.txt
OR
# Debian packages
sudo apt-get install \
python-psycopg2 \
python-webpy \
python-ldap \
python-configparser \
python-requests \
python-openssl
OR
docker pull leboncoin/cassh-server:VERSION
# Generate CA ssh key and revocation key file
mkdir test-keys
ssh-keygen -C CA -t rsa -b 4096 -o -a 100 -N "" -f /etc/cassh-server/ca/id_rsa_ca # without passphrase
ssh-keygen -k -f /etc/cassh-server/krl/revoked-keys
# cassh.conf
[main]
ca = /etc/cassh-server/ca/id_rsa_ca
krl = /etc/cassh-server/krl/revoked-keys
port = 8080
# Optionnal : admin_db_failover is used to bypass db when it fails.
# admin_db_failover = False
[postgres]
host = cassh.domain.fr
dbname = casshdb
user = cassh
password = xxxxxxxx
# Highly recommended
[ldap]
host = ldap.domain.fr
bind_dn = OU=User,DC=domain,DC=fr
admin_cn = CN=Admin,OU=Group,DC=domain,DC=fr
# Key in user result to get his LDAP realname
filterstr = userPrincipalName
# Optionnal
[ssl]
private_key = /etc/cassh-server/ssl/cert.key
public_key = /etc/cassh-server/ssl/cert.pem
- You need a database and a user's credentials
- Init the database with this sql statement: SQL Model
- Update the
cassh-server
config with the user's credentials
python src/server/server.py --config "/etc/cassh-server/cassh.conf"
or
docker run --rm \
--volume=/etc/cassh-server/cassh.conf:/opt/cassh/server/conf/cassh.conf \
--volume=${CASSH_KEYS_DIR}:${CASSH_KEYS_DIR} \
--publish "8080:8080" \
leboncoin/cassh-server
A webui based on flask
is also available for client not familiar with CLI.
It must run on the same OS than the cassh-server
.
pip3 insall -r src/server/web/requirements.txt
python3 src/server/web/cassh_web.py
Python 3
sudo apt-get install python3-pip
pip3 install -r src/client/requirements.txt
alias cassh="${PWD}/src/client/cassh"
Python 2
sudo apt-get install python-pip
pip install -r src/client/requirements.txt
alias cassh="${PWD}/src/client/cassh"
Docker
./contrib/cassh_docker.sh
Put in your Shell rc file alias cassh="PATH_TO/contrib/cassh_docker.sh"
Sample available at ./src/client/cassh-client.conf
[ssl]
private_key = __CASSH_PATH__/ssl/server.key
public_key = __CASSH_PATH__/ssl/server.pem
[ldap]
host = ldap.domain.fr
bind_dn = OU=User,DC=domain,DC=fr
admin_cn = CN=Admin,OU=Group,DC=domain,DC=fr
# Key in user result to get his LDAP realname
filterstr = userPrincipalName
Needed:
docker
: https://docs.docker.com/engine/installation/docker-compose
: https://docs.docker.com/compose/installation/invoke
: http://www.pyinvoke.org/
If installed and run locally:
bats
: https://github.com/sstephenson/batscurl
,jq
&openssh-client
with your distro packages manager
Start the server and its dependencies:
$ cd tests/
$ docker-compose up cassh-server
In an other shell, submit cassh
CLI commands:
$ cd tests/
$ docker-compose run cassh-cli
Starting tests_db_1 ... done
Starting tests_cassh-server_1 ... done
usage: cassh [-h] [--version] {admin,add,sign,status,ca,krl} ...
positional arguments:
{admin,add,sign,status,ca,krl}
commands
admin Administrator command : active - revoke - delete -
status - set keys
add Add a key to remote ssh ca server.
sign Sign its key by remote ssh ca server.
status Display key current status on remote ssh ca server.
ca Display CA public key.
krl Display CA KRL.
optional arguments:
-h, --help show this help message and exit
--version show program's version number and exit
Some redondent tasks are automated using invoke
.
They are defined in the tasks/
directory.
$ invoke -l
Available tasks:
build.all Build cassh & cassh-server docker images
build.cassh Build cassh CLI
build.cassh-server Build cassh-server
release.all Push cassh & cassh-server docker images to Docker hub
release.cassh Push cassh CLI docker image to Docker hub
release.cassh-server Push cassh-server docker image to Docker hub
test.e2e End to End tests of CASSH-server and CASSH cli
test.lint-client pylint cassh
test.lint-server pylint cassh-server
$ invoke test.e2e
- CI jobs are configured on Travis-ci.org.
- You can configure and see what is run by reading .travis.yml.
- On successful tests, docker images are published on docker hub