Skip to main content

SSH CA Server

Project description

# SSH CA Server

Simple web service to provide SSH key signing.


## Purpose

The SSH CA Server provides a central service for authorizing SSH certificate signing requests. LDAP groups are used to determine a users authorization level. [ca-client](https://github.com/commercehub-oss/ssh-ca-client) can be deployed to workstations for interacting with the SSH CA Server.


## SSH Background:

SSH permits the use of signed certificates for authenticating. This simplifies the distribution of SSH keys because only the public key of the CA needs to be deployed to remote hosts. All new users just need their public keys signed by the CA to allow access to any remote host authorizing the CA.

Create a new CA
```
ssh-keygen -f MyCA
```

Sign key with CA:
```
ssh-keygen -V +1h -s MyCA -I username -n principal ~/.ssh/id_rsa.pub
```

*-V +1h:* Amount of time certificate is valid

*-s MyCA:* Certificate authority used to sign key

*-I username:* Signs the certificate with an identifier that will be logged to auth.log by sshd. This allows signing a certificate with a username and allows for uniquely identifying users (helpful for meeting audit requirments).

*-n principal:* Comma delimited list of principals included in certificate. The signed certificate can only be used for the designated principals. This is helpful when using a single CA for many different teams by using different principals and singing accordingly.


To view the certificate:
```
ssh-keygen -L -f ~/.ssh/id_rsa-cert.pub
```

On remote host update /etc/ssh/sshd_config to include:
TrustedUserCAKeys /etc/ssh/MyCA.pub

Upload MyCA.pub to /etc/ssh

This approach will grant access to any principal a cert is signed for. The principal must exist on the remote host or access will be denied.

Alternatively you can allow access per principal by updating the authorized_keys for the specific principal.

On remote host update ~/.ssh/authorized_keys for the signed principal. Add the public key of the CA preceded with cert-authority

An example ~/.ssh/authorized_keys:
```
cert-authority ssh-rsa AAAA5Adk8.....
```


You can now login to the remote host using your new certificate

While CA signing is a great feature there is an obvious need to protect the CA. The goal of this project is to protect your CA and authorize signing requests using an LDAP directory.


## Installation instructions for Ubuntu

1. Install ssh-ca-server
```
pip install ssh-ca-server
```

2. Create service account and required directories

```
# Service account for running ssh-ca-server
useradd ssh-ca-server

# Required configuration directory
mkdir /etc/ssh-ca-server
chown ssh-ca-server:ssh-ca-server /etc/ssh-ca-server

# Location to store all CA public and private keys
mkdir /etc/ssh-ca-server/cas
chown ssh-ca-server:ssh-ca-server /etc/ssh-ca-server/cas
chmod 600 /etc/ssh-ca-server/cas

# Location for log file
mkdir /var/log/ssh-ca-server
chown ssh-ca-server:ssh-ca-server /var/log/ssh-ca-server

```


3. Create configuration under /etc/ssh-ca-server/config.json (See server configuration section for available options)

Example /etc/ssh-ca-server/config.json:
```json
{
"ldap_server": "ldap-server.mydomain.com",
"ldap_domain": "mydomain.com",
"bind_user": "bind-user",
"bind_password": "bind-password",
"base_dn": "DC=mydomain,DC=com",
"group_dn": "OU=MyGroups,DC=mydomain,DC=com",
"role_attribute": "extensionAttribute1",
"role_description": "description",
"ca_attribute": "extensionAttribute2",
"principal_attribute": "extensionAttribute3",
"ca_path": "/etc/ssh-ca-server/cas",
"cas":
[
{
"name": "production",
"max_duration": "24h"
},
{
"name": "nonproduction",
"max_duration": "30d"
}
]
}
```

4. Install gunicorn
```
apt-get install gunicorn
```

5. Create upstart script /etc/init/ssh-ca-server
```
setuid ssh-ca-server
setgid ssh-ca-server

start on runlevel [2345]
stop on runlevel [06]
respawn
respawn limit 20 5

script
gunicorn -w 4 ssh_ca_server:app -b 0.0.0.0
end script
```

6. Start service
```
service ssh-ca-server start
```



## Server Configuration

By default configuration is loaded from /etc/ca-server/config.json. To change this behavior set environment variable SSHCA_CONFIG_PATH to the full path of the configuration file.

Parameter | Default |Description
--------------------|-----------------------|------------------
ldap_server | - |FQDN of LDAP server
ldap_domain | - |Domain name of LDAP server used to derive UPN for bind_user
bind_user | - |Username of LDAP service account for validating group membership
bind_password | - |Password for bind_user
base_dn | - |Base DN used to find authenticating user
group_dn | - |Base DN used to find groups with role definitions
role_attribute | extensionAttribute1 |LDAP attribute that must be set to ca-role to filter groups
role_description | description |LDAP attribute that stores the role description
ca_attribute | extensionAttribute2 |LDAP attribute that stores a comma delimited list of allowed CA names
principal_attribute | extensionAttribute3 |LDAP attribute that stores a comma delimited list of allowed principals
ca_path | /etc/ca-server/certs |Location to store CA public and private keys
cas | - |List of supported CAs (See available CA parameters below)
log_level | INFO |Log level (ERROR, INFO, DEBUG)
log_file |/var/log/ca-server/server.log |Location of log file


cas is a list of certificate authorities supported by the CA server and supports the following parameters:

Parameter | Default |Description
--------------------|-----------------------|------------------
name | - |Name of CA
max_duration | 7d |Expriation for key signing


## HTTP Endpoint

#### /

This endpoint can be used to validate the basic health of the service and returns an empty payload.

All responses include the following attributes:
* message: String value of an error response
* version: The API version
* payload: The payload returned by a successful request
* error: Boolean value indicating an error occurred, if True message should always have a user friendly message.

It returns a JSON body like this:
```json
{
"message": "",
"version": "1.01",
"payload": "",
"error": false
}
```

#### /list/cas

This endpoint is hit with a GET and returns a complete list of available certificate authorities.

It returns a json body like this:
```json
{
"message": "",
"version": "1.01",
"payload":
[
{
"max_duration": "24h",
"name": "production"
},
{
"max_duration": "30d",
"name": "nonproduction"
}
],
"error": false
}
```
#### /list/roles

This endpoint is hit with a GET and returns a complete list of roles for a given user. Use the **?user=** query parameter to filter the role list to a given user.

It returns a json body like this:
```json
{
"message": "",
"version": "1.01",
"payload":
[
{
"allowed_principals": "admin",
"allowed_cas": "nonproduction,production",
"ldap_group": "ssh-admin-group",
"description": "Super Admin Role",
"name": "ssh-admin-group"
}
],
"error": false
}
```
#### /get/\<ca_name\>

This endpoint is hit with a GET and returns the certificate authority public key for the ca_name provided in the path.

```json
{
"message": "",
"version": "1.01",
"payload": "94ABaQZ....",
"error": false
}
```
#### /sign

This endpoint is hit with a POST and returns a signed certificate. The desired certificate authority is provided using the **?ca=** query parameter.

Basic HTTP Authentication is used and requires the users LDAP username and password.

The **file** POST field should contain the users public key as multipart/form-data


Example request:
```
curl -u username -F file=@my_ssh_key.pub https://ca-server.mydomain.com/sign?ca=nonproduction
```

It returns a json body like this:
```json
{
"message": "",
"version": "1.01",
"payload": "ssh-rsa-cert-v01@openssh.com AC1Et...",
"error": false
}
```

The returned signed SSH certificate will include all authorized principals plus the requesters username. The Key ID value is what will appears in the authlog of the remote node.

The below examples shows the result of a successfully signed SSH certificate:

```
$ ssh-keygen -L -f ~/.ssh/nonproduction_rsa-cert.pub

~/.ssh/nonproduction_rsa-cert.pub:
Type: ssh-rsa-cert-v01@openssh.com user certificate
Public key: RSA-CERT 3c:3d:47:...
Signing CA: RSA 2b:2a:23:...
Key ID: "username"
Serial: 12515602213705584981
Valid: from 2017-02-06T17:03:00 to 2017-03-08T17:04:44
Principals:
username
admin
Critical Options: (none)
Extensions:
permit-X11-forwarding
permit-agent-forwarding
permit-port-forwarding
permit-pty
permit-user-rc
```



Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ssh-ca-server-0.1.3.tar.gz (10.7 kB view details)

Uploaded Source

Built Distribution

ssh_ca_server-0.1.3-py2.py3-none-any.whl (14.3 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file ssh-ca-server-0.1.3.tar.gz.

File metadata

File hashes

Hashes for ssh-ca-server-0.1.3.tar.gz
Algorithm Hash digest
SHA256 c40697443e8add669bbd09fc5e1ce83c42086c02ec9f59147d9f831c21c27291
MD5 9ff8c4b4ce4a190dc284bcc9d298d947
BLAKE2b-256 416a57b4206ef92e13518c83ebcbe4a0244329c4171934985005441edd5a0681

See more details on using hashes here.

File details

Details for the file ssh_ca_server-0.1.3-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for ssh_ca_server-0.1.3-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 9ad10d28115a58ea7694e86a067dfbcb78466e6b46359df34ad8fb9488c4e8ec
MD5 41fd7f9387300cf100191df415bb1cd5
BLAKE2b-256 a5caa014b6e6ad2b77aac52c3c5a9e8da70a2a207701266e58eb71025ce9cd86

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page