Destination Plugin/Lemur_linuxdst (#736)

* Added lemur_linuxdst

* Revert "Added lemur_linuxdst"

This reverts commit 010c19bd1937320189ee5a0660f9e356221121f3.

* added plugin\lemur_linuxdst

Destination plugin for a target linux host

* Update remote_host.py

* Update plugin.py

* Update remote_host.py

* Update plugin.py

* Update plugin.py

* chaning var and funct names

* Write data with local temp

* .

* .

* typo

* tested plugin successfully

* Update plugin.py

* Update remote_host.py

* removed whitespace

* set permissions on exported keys to 600

sftp.chmod(dst_dir_cn + '/' + dst_file, (stat.S_IRUSR))

* Update plugin.py

* Update remote_host.py

* Update plugin.py

* added 'paramiko==2.1.2'

required for lemur_linuxdst plugin

* data stored in clear text at rest

* Update plugin.py

* Update plugin.py

* Update remote_host.py
This commit is contained in:
Rick Breidenstein 2017-04-27 12:19:49 -04:00 committed by kevgliss
parent 604cd60dbe
commit e86954e8ea
5 changed files with 161 additions and 1 deletions

View File

@ -0,0 +1,5 @@
try:
VERSION = __import__('pkg_resources') \
.get_distribution(__name__).version
except Exception as e:
VERSION = 'unknown'

View File

@ -0,0 +1,83 @@
#!/usr/bin/python
from lemur.plugins.bases import DestinationPlugin
from lemur.plugins.lemur_linuxdst import remote_host
class LinuxDstPlugin(DestinationPlugin):
title = 'Linux Destination Plugin'
slug = 'linux-destination'
description = 'Allow the distribution of certificates to a Linux host'
version = 1
author = 'Rick Breidenstein '
author_url = 'https://github.com/RickB17/'
options = [
{
'name': 'dstHost',
'type': 'str',
'required': True,
'helpMessage': 'This is the host you will be sending the certificate to',
},
{
'name': 'dstPort',
'type': 'int',
'required': True,
'helpMessage': 'This is the port SSHD is running on',
'default': '22'
},
{
'name': 'dstUser',
'type': 'str',
'required': True,
'helpMessage': 'The user name to use on the remote host. Hopefully not root.',
'default': 'root',
},
{
'name': 'dstPriv',
'type': 'str',
'required': True,
'helpMessage': 'The private key to use for auth',
'default': '/root/.shh/id_rsa',
},
{
'name': 'dstPrivKey',
'type': 'str',
'required': False,
'helpMessage': 'The password for the destination private key',
'default': 'somethingsecret',
},
{
'name': 'dstDir',
'type': 'str',
'required': True,
'helpMessage': 'This is the directory on the host you want to send the certificate to',
'default': '/etc/nginx/certs/'
},
{
"available": [
"NGINX",
"3File"
],
"name": "exportType",
"required": True,
"value": "NGINX",
"helpMessage": "Reference the docs for an explaination of each export type",
"type": "select"
}
]
requires_key = False
def upload(self, name, body, private_key, cert_chain, options, **kwargs):
export_type = self.get_option('exportType', options)
dst_host = self.get_option('dstHost', options)
dst_host_port = self.get_option('dstPort', options)
dst_user = self.get_option('dstUser', options)
dst_priv = self.get_option('dstPriv', options)
dst_priv_key = self.get_option('dstPrivKey', options)
if dst_priv_key:
dst_priv_key = None
dst_dir = self.get_option('dstDir', options)
remote_host.create_cert(name, dst_dir, export_type, dst_user, dst_priv, dst_priv_key, dst_host, int(dst_host_port))

View File

@ -0,0 +1,6 @@
NOTE: AS OF 4/25/2017 DATA IN THIS PLUGIN IS NOT ENCRYPTED AT REST
example: If you input a password for a private key, it is stored in clear text
add this to the lemur.plugins entry_points in /www/lemur/setup.py
'linux_destination = lemur.plugins.lemur_linuxdst.plugin:LinuxDstPlugin',

View File

@ -0,0 +1,65 @@
#!/usr/bin/python
from lemur.certificates import service
import paramiko
import stat
def copy_cert(cert_cn, dst_user, dst_priv, dst_priv_key, dst_host, dst_port, dst_dir, dst_file, dst_data):
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
#include the private key password if required
if dst_priv_key is None:
priv_key = paramiko.RSAKey.from_private_key_file(dst_priv)
else:
priv_key = paramiko.RSAKey.from_private_key_file(dst_priv, dst_priv_key)
#open the sftp connection
ssh.connect(dst_host, username=dst_user, port=dst_port, pkey=priv_key)
sftp = ssh.open_sftp()
#make the directory on the desitination server
#files will be in a a folder based on the cert_cn
#example:
#destination folder: /etc/nginx/certs/
#files will go in: /etc/nginx/certs/your.cn.com/cert.pem
try:
sftp.mkdir(dst_dir)
except IOError:
pass
try:
dst_dir_cn = dst_dir + '/' + cert_cn
sftp.mkdir(dst_dir_cn)
except IOError:
pass
cert_out = sftp.open(dst_dir_cn + '/' + dst_file, 'w')
cert_out.write(dst_data)
cert_out.close()
sftp.chmod(dst_dir_cn + '/' + dst_file, (stat.S_IRUSR))
ssh.close()
def create_cert(name, dst_dir, export_type, dst_user, dst_priv, dst_priv_key, dst_host, dst_host_port):
lem_cert = service.get_by_name(name)
dst_file = 'cert.pem'
chain_req = False
if export_type == 'NGINX':
#This process will result in a cert.pem file with the body and chain in a single file
if lem_cert.chain is None:
dst_data = lem_cert.body
else:
dst_data = lem_cert.body + '\n' + lem_cert.chain
chain_req = False
elif export_type == '3File':
#This process will results in three files. cert.pem, priv.key, chain.pem
dst_data = lem_cert.body
chain_req = True
else:
dst_data = lem_cert.body
copy_cert(lem_cert.cn, dst_user, dst_priv, dst_priv_key, dst_host, dst_host_port, dst_dir, dst_file, dst_data)
if chain_req is True:
dst_file = 'chain.pem'
dst_data = lem_cert.chain_req
copy_cert(lem_cert.cn, dst_user, dst_priv, dst_priv_key, dst_host, dst_host_port, dst_dir, dst_file, dst_data)
dst_file = 'priv.key'
dst_data = lem_cert.private_key
copy_cert(lem_cert.cn, dst_user, dst_priv, dst_priv_key, dst_host, dst_host_port, dst_dir, dst_file, dst_data)

View File

@ -62,7 +62,8 @@ install_requires = [
'acme==0.13.0', 'acme==0.13.0',
'retrying==1.3.3', 'retrying==1.3.3',
'tabulate==0.7.7', 'tabulate==0.7.7',
'pem==16.1.0' 'pem==16.1.0',
'paramiko==2.1.2' #required for lemur_linuxdst plugin
] ]
tests_require = [ tests_require = [