Compare commits
31 Commits
Author | SHA1 | Date | |
---|---|---|---|
aa76379d6c | |||
ef72de89b3 | |||
e2962a4b8d | |||
a563986ce4 | |||
a4e294634a | |||
067122f8f4 | |||
6a1a744eff | |||
d3cf273a45 | |||
52e267468a | |||
e80b58899d | |||
25f652c1eb | |||
0dde4c9f80 | |||
a512b82196 | |||
7f119e95e1 | |||
bf957d2509 | |||
1e314b505f | |||
ef9a80ebfd | |||
84d0afae4c | |||
48a53ad436 | |||
2f4aee49e2 | |||
f3f5b9eeb3 | |||
541d5420bb | |||
0383e2a1e1 | |||
084604cf3c | |||
8ab9c06778 | |||
0afd4c94b4 | |||
aaae4d5a1f | |||
9da713ab06 | |||
540d56f0b8 | |||
160eaa6901 | |||
180c8228e1 |
2
AUTHORS
@ -1,2 +1,2 @@
|
||||
- Kevin Glisson (kglisson@netflix.com)
|
||||
- Kevin Glisson <kglisson@netflix.com>
|
||||
- Jeremy Heffner <jheffner@netflix.com>
|
||||
|
4
MANIFEST.in
Normal file
@ -0,0 +1,4 @@
|
||||
include setup.py package.json bower.json gulpfile.js README.rst MANIFEST.in LICENSE AUTHORS
|
||||
recursive-include lemur/plugins/lemur_email/templates *
|
||||
recursive-include lemur/static *
|
||||
global-exclude *~
|
@ -19,8 +19,7 @@ Lemur
|
||||
|
||||
Lemur manages SSL certificate creation. It provides a central portal for developers to issuer their own SSL certificates with 'sane' defaults.
|
||||
|
||||
It works on CPython 2.7, 3.3, 3.4 It is known
|
||||
to work on Ubuntu Linux and OS X.
|
||||
It works on CPython 2.7, 3.3, 3.4. We deploy on Ubuntu and develop on OS X.
|
||||
|
||||
Project resources
|
||||
=================
|
||||
|
@ -74,8 +74,6 @@ Basic Configuration
|
||||
|
||||
The TOKEN_SECRET is the secret used to create JWT tokens that are given out to users. This should be securely generated and be kept private.
|
||||
|
||||
See `SECRET_KEY` for methods on secure secret generation.
|
||||
|
||||
::
|
||||
|
||||
LEMUR_TOKEN_SECRET = 'supersecret'
|
||||
@ -122,7 +120,7 @@ and are used when Lemur creates the CSR for your certificates.
|
||||
|
||||
::
|
||||
|
||||
LEMUR_DEFAULT_STATE = "CA"
|
||||
LEMUR_DEFAULT_STATE = "California"
|
||||
|
||||
|
||||
.. data:: LEMUR_DEFAULT_LOCATION
|
||||
@ -152,15 +150,16 @@ and are used when Lemur creates the CSR for your certificates.
|
||||
Notification Options
|
||||
--------------------
|
||||
|
||||
Lemur currently has very basic support for notifications. Notifications are sent to the certificate creator, owner and
|
||||
security team as specified by the `SECURITY_TEAM_EMAIL` configuration parameter.
|
||||
Lemur currently has very basic support for notifications. Currently only expiration notifications are supported. Actual notification
|
||||
is handling by the notification plugins that you have configured. Lemur ships with the 'Email' notification that allows expiration emails
|
||||
to be sent to subscribers.
|
||||
|
||||
The template for all of these notifications lives under lemur/template/event.html and can be easily modified to fit your
|
||||
needs.
|
||||
Templates for expiration emails are located under `lemur/plugins/lemur_email/templates` and can be modified for your needs.
|
||||
Notifications are sent to the certificate creator, owner and security team as specified by the `LEMUR_SECURITY_TEAM_EMAIL` configuration parameter.
|
||||
|
||||
Certificates marked as in-active will **not** be notified of upcoming expiration. This enables a user to essentially
|
||||
silence the expiration. If a certificate is active and is expiring the above will be notified at 30, 15, 5, 2 days
|
||||
respectively.
|
||||
silence the expiration. If a certificate is active and is expiring the above will be notified according to the `LEMUR_DEFAULT_EXPIRATION_NOTIFICATION_INTERVALS` or
|
||||
30, 15, 2 days before expiration if no intervals are set.
|
||||
|
||||
Lemur supports sending certification expiration notifications through SES and SMTP.
|
||||
|
||||
@ -197,6 +196,16 @@ Lemur supports sending certification expiration notifications through SES and SM
|
||||
LEMUR_SECURITY_TEAM_EMAIL = ['security@example.com']
|
||||
|
||||
|
||||
.. data:: LEMUR_DEFAULT_EXPIRATION_NOTIFICATION_INTERVALS
|
||||
:noindex:
|
||||
|
||||
Lemur notification intervals
|
||||
|
||||
::
|
||||
|
||||
LEMUR_DEFAULT_EXPIRATION_NOTIFICATION_INTERVALS = [30, 15, 2]
|
||||
|
||||
|
||||
Authority Options
|
||||
-----------------
|
||||
|
||||
@ -215,6 +224,35 @@ Verisign/Symantec and CloudCA
|
||||
This is the path to the mutual SSL certificate used for communicating with Verisign
|
||||
|
||||
|
||||
.. data:: VERISIGN_FIRST_NAME
|
||||
:noindex:
|
||||
|
||||
This is the first name to be used when requesting the certificate
|
||||
|
||||
|
||||
.. data:: VERISIGN_LAST_NAME
|
||||
:noindex:
|
||||
|
||||
This is the last name to be used when requesting the certificate
|
||||
|
||||
.. data:: VERISIGN_EMAIL
|
||||
:noindex:
|
||||
|
||||
This is the email to be used when requesting the certificate
|
||||
|
||||
|
||||
.. data:: VERISIGN_INTERMEDIATE
|
||||
:noindex:
|
||||
|
||||
This is the intermediate to be used for your CA chain
|
||||
|
||||
|
||||
.. data:: VERISIGN_ROOT
|
||||
:noindex:
|
||||
|
||||
This is the root to be used for your CA chain
|
||||
|
||||
|
||||
.. data:: CLOUDCA_URL
|
||||
:noindex:
|
||||
|
||||
@ -231,6 +269,7 @@ Verisign/Symantec and CloudCA
|
||||
|
||||
This is the path to the CLOUDCA certificate bundle
|
||||
|
||||
|
||||
Authentication
|
||||
--------------
|
||||
Lemur currently supports Basic Authentication and Ping OAuth2 out of the box, additional flows can be added relatively easily
|
||||
@ -279,9 +318,9 @@ In order for Lemur to manage it's own account and other accounts we must ensure
|
||||
Setting up IAM roles
|
||||
--------------------
|
||||
|
||||
Lemur's aws plugin uses boto heavily to talk to all the AWS resources it manages. By default it uses the on-instance credentials to make the necessary calls.
|
||||
Lemur's AWS plugin uses boto heavily to talk to all the AWS resources it manages. By default it uses the on-instance credentials to make the necessary calls.
|
||||
|
||||
In order to limit the permissions we will create a new two IAM roles for Lemur. You can name them whatever you would like but for example sake we will be calling them LemurInstanceProfile and Lemur.
|
||||
In order to limit the permissions, we will create two new IAM roles for Lemur. You can name them whatever you would like but for example sake we will be calling them LemurInstanceProfile and Lemur.
|
||||
|
||||
Lemur uses to STS to talk to different accounts. For managing one account this isn't necessary but we will still use it so that we can easily add new accounts.
|
||||
|
||||
@ -327,6 +366,11 @@ STS-AssumeRole
|
||||
|
||||
Next we will create the the Lemur IAM role. Lemur
|
||||
|
||||
..note::
|
||||
|
||||
The default IAM role that Lemur assumes into is called `Lemur`, if you need to change this ensure you set `LEMUR_INSTANCE_PROFILE` to your role name in the configuration.
|
||||
|
||||
|
||||
Here is an example policy for Lemur:
|
||||
|
||||
IAM-ServerCertificate
|
||||
@ -584,7 +628,8 @@ that the `Authority` is associated with it Lemur allows that user to user/view/u
|
||||
|
||||
This RBAC is also used when determining which users can access which certificate private key. Lemur's current permission
|
||||
structure is setup such that if the user is a `Creator` or `Owner` of a given certificate they are allow to view that
|
||||
private key.
|
||||
private key. Owners can also be a role name, such that any user with the same role as owner will be allowed to view the
|
||||
private key information.
|
||||
|
||||
These permissions are applied to the user upon login and refreshed on every request.
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# security_monkey documentation build configuration file, created by
|
||||
# lemur documentation build configuration file, created by
|
||||
# sphinx-quickstart on Sat Jun 7 18:43:48 2014.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its
|
||||
|
@ -215,7 +215,7 @@ certificate Lemur does not know about and adding the certificate to it's invento
|
||||
The `SourcePlugin` object has one default option of `pollRate`. This controls the number of seconds which to get new certificates.
|
||||
|
||||
.. warning::
|
||||
Lemur currently has a very basic polling system of running a cron job every 15min to see which source plugins need to be run. A lock file is generated to guarentee that ]
|
||||
Lemur currently has a very basic polling system of running a cron job every 15min to see which source plugins need to be run. A lock file is generated to guarantee that
|
||||
only one sync is running at a time. It also means that the minimum resolution of a source plugin poll rate is effectively 15min. You can always specify a faster cron
|
||||
job if you need a higher resolution sync job.
|
||||
|
||||
|
BIN
docs/guide/certificate_extensions.png
Normal file
After Width: | Height: | Size: 125 KiB |
BIN
docs/guide/create.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
docs/guide/create_authority.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
docs/guide/create_authority_options.png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
docs/guide/create_certificate.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
docs/guide/create_role.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
docs/guide/create_user.png
Normal file
After Width: | Height: | Size: 39 KiB |
@ -1,14 +1,95 @@
|
||||
Creating Users
|
||||
==============
|
||||
User Guide
|
||||
==========
|
||||
|
||||
These guides are quick tutorials on how to perform basic tasks in Lemur.
|
||||
|
||||
Create a New User
|
||||
~~~~~~~~~~~~~~~~~
|
||||
.. figure:: settings.png
|
||||
|
||||
From the settings dropdown select "Users"
|
||||
|
||||
.. figure:: create.png
|
||||
|
||||
In the user table select "Create"
|
||||
|
||||
.. figure:: create_user.png
|
||||
|
||||
Enter the username, email and password for the user. You can also assign any
|
||||
roles that the user will need when they login. While there is no deletion
|
||||
(we want to track creators forever) you can mark a user as 'Inactive' that will
|
||||
not allow them to login to Lemur.
|
||||
|
||||
|
||||
Creating Roles
|
||||
==============
|
||||
Create a New Role
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. figure:: settings.png
|
||||
|
||||
From the settings dropdown select "Roles"
|
||||
|
||||
.. figure:: create.png
|
||||
|
||||
In the role table select "Create"
|
||||
|
||||
.. figure:: create_role.png
|
||||
|
||||
Enter a role name and short description about the role. You can optionally store
|
||||
a user/password on the role. This is useful if your authority require specific roles.
|
||||
You can then accurately map those roles onto Lemur users. Also optional you can assign
|
||||
users to your new role.
|
||||
|
||||
|
||||
Creating Authorities
|
||||
====================
|
||||
Create a New Authority
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. figure:: create.png
|
||||
|
||||
In the authority table select "Create"
|
||||
|
||||
.. figure:: create_authority.png
|
||||
|
||||
Enter a authority name and short description about the authority. Enter an owner,
|
||||
and certificate common name. Depending on the authority and the authority/issuer plugin
|
||||
these values may or may not be used.
|
||||
|
||||
.. figure:: create_authority_options.png
|
||||
|
||||
Again how many of these values get used largely depends on the underlying plugin. It
|
||||
is important to make sure you select the right plugin that you wish to use.
|
||||
|
||||
|
||||
Creating Certificates
|
||||
=====================
|
||||
Create a New Certificate
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. figure:: create.png
|
||||
|
||||
In the certificate table select "Create"
|
||||
|
||||
.. figure:: create_certificate.png
|
||||
|
||||
Enter a owner, short description and the authority you wish to issue this certificate.
|
||||
Enter a common name into the certificate, if no validity range is selected two years is
|
||||
the default.
|
||||
|
||||
You can add notification options and upload the created certificate to a destination, both
|
||||
of these are editable features and can be changed after the certificate has been created.
|
||||
|
||||
.. figure:: certificate_extensions.png
|
||||
|
||||
These options are typically for advanced users, the one exception is the `Subject Alternate Names` or SAN.
|
||||
For certificates that need to include more than one domains, the first domain is the Common Name and all
|
||||
other domains are added here as DNSName entries.
|
||||
|
||||
|
||||
Import an Existing Certificate
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. figure:: upload_certificate.png
|
||||
|
||||
Enter a owner, short description and public certificate. If there are intermediates and private keys
|
||||
Lemur will track them just as it does if the certificate were created through Lemur. Lemur generates
|
||||
a certificate name but you can override that by passing a value to the `Custom Name` field.
|
||||
|
||||
You can add notification options and upload the created certificate to a destination, both
|
||||
of these are editable features and can be changed after the certificate has been created.
|
||||
|
BIN
docs/guide/settings.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
docs/guide/upload_certificate.png
Normal file
After Width: | Height: | Size: 73 KiB |
@ -4,6 +4,8 @@ Quickstart
|
||||
This guide will step you through setting up a Python-based virtualenv, installing the required packages, and configuring the basic web service.
|
||||
This guide assumes a clean Ubuntu 14.04 instance, commands may differ based on the OS and configuration being used.
|
||||
|
||||
Pressed for time? See the Lemur docker file on `Github <https://github.com/Netflix/lemur-docker>`_.
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
@ -18,6 +20,7 @@ Some basic prerequisites which you'll need in order to run Lemur:
|
||||
are largely handled for us. Lemur does **not** require AWS to function. Our guides and documentation try to be
|
||||
be as generic as possible and are not intended to document every step of launching Lemur into a given environment.
|
||||
|
||||
|
||||
Setting up an Environment
|
||||
-------------------------
|
||||
|
||||
@ -194,12 +197,6 @@ You'll use the builtin HttpProxyModule within Nginx to handle proxying
|
||||
index index.html;
|
||||
}
|
||||
|
||||
location / {
|
||||
root /www/lemur/lemur/static/dist;
|
||||
include mime.types;
|
||||
index index.html;
|
||||
}
|
||||
|
||||
See :doc:`../production/index` for more details on using Nginx.
|
||||
|
||||
|
||||
|
@ -17,7 +17,7 @@ from lemur.domains.views import mod as domains_bp
|
||||
from lemur.destinations.views import mod as destinations_bp
|
||||
from lemur.authorities.views import mod as authorities_bp
|
||||
from lemur.certificates.views import mod as certificates_bp
|
||||
from lemur.status.views import mod as status_bp
|
||||
from lemur.defaults.views import mod as defaults_bp
|
||||
from lemur.plugins.views import mod as plugins_bp
|
||||
from lemur.notifications.views import mod as notifications_bp
|
||||
from lemur.sources.views import mod as sources_bp
|
||||
@ -31,7 +31,7 @@ LEMUR_BLUEPRINTS = (
|
||||
destinations_bp,
|
||||
authorities_bp,
|
||||
certificates_bp,
|
||||
status_bp,
|
||||
defaults_bp,
|
||||
plugins_bp,
|
||||
notifications_bp,
|
||||
sources_bp
|
||||
|
@ -125,7 +125,7 @@ class Ping(Resource):
|
||||
|
||||
args = self.reqparse.parse_args()
|
||||
|
||||
# take the information we have received from Meechum to create a new request
|
||||
# take the information we have received from the provider to create a new request
|
||||
params = {
|
||||
'client_id': args['clientId'],
|
||||
'grant_type': 'authorization_code',
|
||||
@ -138,7 +138,7 @@ class Ping(Resource):
|
||||
access_token_url = current_app.config.get('PING_ACCESS_TOKEN_URL')
|
||||
user_api_url = current_app.config.get('PING_USER_API_URL')
|
||||
|
||||
# the secret and cliendId will be given to you when you signup for meechum
|
||||
# the secret and cliendId will be given to you when you signup for the provider
|
||||
basic = base64.b64encode('{0}:{1}'.format(args['clientId'], current_app.config.get("PING_SECRET")))
|
||||
headers = {'Authorization': 'Basic {0}'.format(basic)}
|
||||
|
||||
@ -220,7 +220,7 @@ class Ping(Resource):
|
||||
profile['email'],
|
||||
profile['email'],
|
||||
True,
|
||||
profile.get('thumbnailPhotoUrl'), # Encase profile isn't google+ enabled
|
||||
profile.get('thumbnailPhotoUrl'), # incase profile isn't google+ enabled
|
||||
roles
|
||||
)
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
"""
|
||||
from builtins import str
|
||||
|
||||
from flask import Blueprint, current_app, make_response, jsonify
|
||||
from flask import Blueprint, make_response, jsonify
|
||||
from flask.ext.restful import reqparse, Api, fields
|
||||
|
||||
from cryptography import x509
|
||||
@ -668,58 +668,9 @@ class NotificationCertificatesList(AuthenticatedResource):
|
||||
return service.render(args)
|
||||
|
||||
|
||||
class CertificatesDefaults(AuthenticatedResource):
|
||||
""" Defineds the 'certificates' defaults endpoint """
|
||||
def __init__(self):
|
||||
super(CertificatesDefaults)
|
||||
|
||||
def get(self):
|
||||
"""
|
||||
.. http:get:: /certificates/defaults
|
||||
|
||||
Returns defaults needed to generate CSRs
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /certificates/defaults HTTP/1.1
|
||||
Host: example.com
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"country": "US",
|
||||
"state": "CA",
|
||||
"location": "Los Gatos",
|
||||
"organization": "Netflix",
|
||||
"organizationalUnit": "Operations"
|
||||
}
|
||||
|
||||
:reqheader Authorization: OAuth token to authenticate
|
||||
:statuscode 200: no error
|
||||
:statuscode 403: unauthenticated
|
||||
"""
|
||||
return dict(
|
||||
country=current_app.config.get('LEMUR_DEFAULT_COUNTRY'),
|
||||
state=current_app.config.get('LEMUR_DEFAULT_STATE'),
|
||||
location=current_app.config.get('LEMUR_DEFAULT_LOCATION'),
|
||||
organization=current_app.config.get('LEMUR_DEFAULT_ORGANIZATION'),
|
||||
organizationalUnit=current_app.config.get('LEMUR_DEFAULT_ORGANIZATIONAL_UNIT')
|
||||
)
|
||||
|
||||
|
||||
api.add_resource(CertificatesList, '/certificates', endpoint='certificates')
|
||||
api.add_resource(Certificates, '/certificates/<int:certificate_id>', endpoint='certificate')
|
||||
api.add_resource(CertificatesStats, '/certificates/stats', endpoint='certificateStats')
|
||||
api.add_resource(CertificatesUpload, '/certificates/upload', endpoint='certificateUpload')
|
||||
api.add_resource(CertificatePrivateKey, '/certificates/<int:certificate_id>/key', endpoint='privateKeyCertificates')
|
||||
api.add_resource(NotificationCertificatesList, '/notifications/<int:notification_id>/certificates', endpoint='notificationCertificates')
|
||||
api.add_resource(CertificatesDefaults, '/certificates/defaults', endpoint='certificatesDefault')
|
||||
|
63
lemur/defaults/views.py
Normal file
@ -0,0 +1,63 @@
|
||||
"""
|
||||
.. module: lemur.status.views
|
||||
:copyright: (c) 2015 by Netflix Inc., see AUTHORS for more
|
||||
:license: Apache, see LICENSE for more details.
|
||||
"""
|
||||
from flask import current_app, Blueprint
|
||||
from flask.ext.restful import Api
|
||||
|
||||
from lemur.auth.service import AuthenticatedResource
|
||||
|
||||
|
||||
mod = Blueprint('default', __name__)
|
||||
api = Api(mod)
|
||||
|
||||
|
||||
class LemurDefaults(AuthenticatedResource):
|
||||
""" Defines the 'defaults' endpoint """
|
||||
def __init__(self):
|
||||
super(LemurDefaults)
|
||||
|
||||
def get(self):
|
||||
"""
|
||||
.. http:get:: /defaults
|
||||
|
||||
Returns defaults needed to generate CSRs
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /defaults HTTP/1.1
|
||||
Host: example.com
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"country": "US",
|
||||
"state": "CA",
|
||||
"location": "Los Gatos",
|
||||
"organization": "Netflix",
|
||||
"organizationalUnit": "Operations"
|
||||
}
|
||||
|
||||
:reqheader Authorization: OAuth token to authenticate
|
||||
:statuscode 200: no error
|
||||
:statuscode 403: unauthenticated
|
||||
"""
|
||||
return dict(
|
||||
country=current_app.config.get('LEMUR_DEFAULT_COUNTRY'),
|
||||
state=current_app.config.get('LEMUR_DEFAULT_STATE'),
|
||||
location=current_app.config.get('LEMUR_DEFAULT_LOCATION'),
|
||||
organization=current_app.config.get('LEMUR_DEFAULT_ORGANIZATION'),
|
||||
organizationalUnit=current_app.config.get('LEMUR_DEFAULT_ORGANIZATIONAL_UNIT')
|
||||
)
|
||||
|
||||
api.add_resource(LemurDefaults, '/defaults', endpoint='default')
|
@ -263,18 +263,23 @@ class InitializeApp(Command):
|
||||
Additionally a Lemur user will be created as a default user
|
||||
and be used when certificates are discovered by Lemur.
|
||||
"""
|
||||
def run(self):
|
||||
option_list = (
|
||||
Option('-p', '--password', dest='password'),
|
||||
)
|
||||
|
||||
def run(self, password):
|
||||
create()
|
||||
user = user_service.get_by_username("lemur")
|
||||
|
||||
if not user:
|
||||
sys.stdout.write("We need to set Lemur's password to continue!\n")
|
||||
password1 = prompt_pass("Password")
|
||||
password2 = prompt_pass("Confirm Password")
|
||||
if not password:
|
||||
sys.stdout.write("We need to set Lemur's password to continue!\n")
|
||||
password = prompt_pass("Password")
|
||||
password1 = prompt_pass("Confirm Password")
|
||||
|
||||
if password1 != password2:
|
||||
sys.stderr.write("[!] Passwords do not match!\n")
|
||||
sys.exit(1)
|
||||
if password != password1:
|
||||
sys.stderr.write("[!] Passwords do not match!\n")
|
||||
sys.exit(1)
|
||||
|
||||
role = role_service.get_by_name('admin')
|
||||
|
||||
@ -285,16 +290,16 @@ class InitializeApp(Command):
|
||||
role = role_service.create('admin', description='this is the lemur administrator role')
|
||||
sys.stdout.write("[+] Created 'admin' role\n")
|
||||
|
||||
user_service.create("lemur", password1, 'lemur@nobody', True, None, [role])
|
||||
user_service.create("lemur", password, 'lemur@nobody', True, None, [role])
|
||||
sys.stdout.write("[+] Added a 'lemur' user and added it to the 'admin' role!\n")
|
||||
|
||||
else:
|
||||
sys.stdout.write("[-] Default user has already been created, skipping...!\n")
|
||||
|
||||
sys.stdout.write("[+] Creating expiration email notifications!\n")
|
||||
sys.stdout.write("[!] Using {recipients} as specified by LEMUR_SECURITY_TEAM_EMAIL for notifications\n")
|
||||
sys.stdout.write("[!] Using {0} as specified by LEMUR_SECURITY_TEAM_EMAIL for notifications\n".format("LEMUR_SECURITY_TEAM_EMAIL"))
|
||||
|
||||
intervals = current_app.config.get("LEMUR_DEFAULT_EXPIRATION_NOTIFICATION_INTERVALS")
|
||||
intervals = current_app.config.get("LEMUR_DEFAULT_EXPIRATION_NOTIFICATION_INTERVALS", [])
|
||||
sys.stdout.write(
|
||||
"[!] Creating {num} notifications for {intervals} days as specified by LEMUR_DEFAULT_EXPIRATION_NOTIFICATION_INTERVALS\n".format(
|
||||
num=len(intervals),
|
||||
@ -569,11 +574,11 @@ class ProvisionELB(Command):
|
||||
'authority': authority,
|
||||
'owner': owner,
|
||||
# defaults:
|
||||
'organization': u'Netflix, Inc.',
|
||||
'organizationalUnit': u'Operations',
|
||||
'country': u'US',
|
||||
'state': u'California',
|
||||
'location': u'Los Gatos'
|
||||
'organization': current_app.config.get('LEMUR_DEFAULT_ORGANIZATION'),
|
||||
'organizationalUnit': current_app.config.get('LEMUR_DEFAULT_ORGANIZATIONAL_UNIT'),
|
||||
'country': current_app.config.get('LEMUR_DEFAULT_COUNTRY'),
|
||||
'state': current_app.config.get('LEMUR_DEFAULT_STATE'),
|
||||
'location': current_app.config.get('LEMUR_DEFAULT_LOCATION')
|
||||
}
|
||||
|
||||
return options
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
"""
|
||||
import ssl
|
||||
import socket
|
||||
|
||||
import arrow
|
||||
|
||||
@ -114,8 +113,9 @@ def _get_domain_certificate(name):
|
||||
try:
|
||||
pub_key = ssl.get_server_certificate((name, 443))
|
||||
return cert_service.find_duplicates(pub_key.strip())
|
||||
except socket.gaierror as e:
|
||||
except Exception as e:
|
||||
current_app.logger.info(str(e))
|
||||
return []
|
||||
|
||||
|
||||
def _find_superseded(cert):
|
||||
|
@ -96,7 +96,7 @@ def convert_date_to_utc_time(date):
|
||||
:return:
|
||||
"""
|
||||
d = arrow.get(date)
|
||||
return arrow.utcnow().replace(day=d.naive.day).replace(month=d.naive.month).replace(year=d.naive.year)\
|
||||
return arrow.utcnow().replace(year=d.naive.year).replace(month=d.naive.month).replace(day=d.naive.day)\
|
||||
.replace(microsecond=0)
|
||||
|
||||
|
||||
|
@ -53,7 +53,7 @@
|
||||
<hr />
|
||||
</div>
|
||||
<p>
|
||||
Lemur, Netflix's SSL management portal has noticed that the following certificates are expiring soon, if you rely on these certificates
|
||||
Lemur, has noticed that the following certificates are expiring soon, if you rely on these certificates
|
||||
you should create new certificates to replace the certificates that are expiring.
|
||||
</p>
|
||||
<p>
|
||||
|
@ -1,57 +0,0 @@
|
||||
VERISIGN_INTERMEDIATE = """-----BEGIN CERTIFICATE-----
|
||||
MIIFFTCCA/2gAwIBAgIQKC4nkXkzkuQo8iGnTsk3rjANBgkqhkiG9w0BAQsFADCB
|
||||
yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
|
||||
ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMTk5OSBWZXJp
|
||||
U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
|
||||
ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
|
||||
aG9yaXR5IC0gRzMwHhcNMTMxMDMxMDAwMDAwWhcNMjMxMDMwMjM1OTU5WjB+MQsw
|
||||
CQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNV
|
||||
BAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxLzAtBgNVBAMTJlN5bWFudGVjIENs
|
||||
YXNzIDMgU2VjdXJlIFNlcnZlciBDQSAtIEc0MIIBIjANBgkqhkiG9w0BAQEFAAOC
|
||||
AQ8AMIIBCgKCAQEAstgFyhx0LbUXVjnFSlIJluhL2AzxaJ+aQihiw6UwU35VEYJb
|
||||
A3oNL+F5BMm0lncZgQGUWfm893qZJ4Itt4PdWid/sgN6nFMl6UgfRk/InSn4vnlW
|
||||
9vf92Tpo2otLgjNBEsPIPMzWlnqEIRoiBAMnF4scaGGTDw5RgDMdtLXO637QYqzu
|
||||
s3sBdO9pNevK1T2p7peYyo2qRA4lmUoVlqTObQJUHypqJuIGOmNIrLRM0XWTUP8T
|
||||
L9ba4cYY9Z/JJV3zADreJk20KQnNDz0jbxZKgRb78oMQw7jW2FUyPfG9D72MUpVK
|
||||
Fpd6UiFjdS8W+cRmvvW1Cdj/JwDNRHxvSz+w9wIDAQABo4IBQDCCATwwHQYDVR0O
|
||||
BBYEFF9gz2GQVd+EQxSKYCqy9Xr0QxjvMBIGA1UdEwEB/wQIMAYBAf8CAQAwawYD
|
||||
VR0gBGQwYjBgBgpghkgBhvhFAQc2MFIwJgYIKwYBBQUHAgEWGmh0dHA6Ly93d3cu
|
||||
c3ltYXV0aC5jb20vY3BzMCgGCCsGAQUFBwICMBwaGmh0dHA6Ly93d3cuc3ltYXV0
|
||||
aC5jb20vcnBhMC8GA1UdHwQoMCYwJKAioCCGHmh0dHA6Ly9zLnN5bWNiLmNvbS9w
|
||||
Y2EzLWczLmNybDAOBgNVHQ8BAf8EBAMCAQYwKQYDVR0RBCIwIKQeMBwxGjAYBgNV
|
||||
BAMTEVN5bWFudGVjUEtJLTEtNTM0MC4GCCsGAQUFBwEBBCIwIDAeBggrBgEFBQcw
|
||||
AYYSaHR0cDovL3Muc3ltY2QuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQBbF1K+1lZ7
|
||||
9Pc0CUuWysf2IdBpgO/nmhnoJOJ/2S9h3RPrWmXk4WqQy04q6YoW51KN9kMbRwUN
|
||||
gKOomv4p07wdKNWlStRxPA91xQtzPwBIZXkNq2oeJQzAAt5mrL1LBmuaV4oqgX5n
|
||||
m7pSYHPEFfe7wVDJCKW6V0o6GxBzHOF7tpQDS65RsIJAOloknO4NWF2uuil6yjOe
|
||||
soHCL47BJ89A8AShP/U3wsr8rFNtqVNpT+F2ZAwlgak3A/I5czTSwXx4GByoaxbn
|
||||
5+CdKa/Y5Gk5eZVpuXtcXQGc1PfzSEUTZJXXCm5y2kMiJG8+WnDcwJLgLeVX+OQr
|
||||
J+71/xuzAYN6
|
||||
-----END CERTIFICATE-----
|
||||
"""
|
||||
|
||||
VERISIGN_ROOT = """-----BEGIN CERTIFICATE-----
|
||||
MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw
|
||||
CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
|
||||
cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
|
||||
LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
|
||||
aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
|
||||
dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD
|
||||
VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT
|
||||
aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ
|
||||
bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu
|
||||
IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
|
||||
LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b
|
||||
N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t
|
||||
KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu
|
||||
kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm
|
||||
CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ
|
||||
Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu
|
||||
imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te
|
||||
2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe
|
||||
DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
|
||||
/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p
|
||||
F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt
|
||||
TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
|
||||
-----END CERTIFICATE-----
|
||||
"""
|
@ -13,9 +13,8 @@ import xmltodict
|
||||
|
||||
from flask import current_app
|
||||
|
||||
from lemur.plugins.bases import IssuerPlugin
|
||||
from lemur.plugins.bases import IssuerPlugin, SourcePlugin
|
||||
from lemur.plugins import lemur_verisign as verisign
|
||||
from lemur.plugins.lemur_verisign import constants
|
||||
from lemur.common.utils import get_psuedo_random_string
|
||||
|
||||
|
||||
@ -132,7 +131,7 @@ class VerisignIssuerPlugin(IssuerPlugin):
|
||||
version = verisign.VERSION
|
||||
|
||||
author = 'Kevin Glisson'
|
||||
author_url = 'https://github.com/netflix/lemur'
|
||||
author_url = 'https://github.com/netflix/lemur.git'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.session = requests.Session()
|
||||
@ -147,7 +146,7 @@ class VerisignIssuerPlugin(IssuerPlugin):
|
||||
:param issuer_options:
|
||||
:return: :raise Exception:
|
||||
"""
|
||||
url = current_app.config.get("VERISIGN_URL") + '/enroll'
|
||||
url = current_app.config.get("VERISIGN_URL") + '/rest/services/enroll'
|
||||
|
||||
data = process_options(issuer_options)
|
||||
data['csr'] = csr
|
||||
@ -156,7 +155,7 @@ class VerisignIssuerPlugin(IssuerPlugin):
|
||||
|
||||
response = self.session.post(url, data=data)
|
||||
cert = handle_response(response.content)['Response']['Certificate']
|
||||
return cert, constants.VERISIGN_INTERMEDIATE,
|
||||
return cert, current_app.config.get('VERISIGN_INTERMEDIATE'),
|
||||
|
||||
@staticmethod
|
||||
def create_authority(options):
|
||||
@ -168,7 +167,7 @@ class VerisignIssuerPlugin(IssuerPlugin):
|
||||
:return:
|
||||
"""
|
||||
role = {'username': '', 'password': '', 'name': 'verisign'}
|
||||
return constants.VERISIGN_ROOT, "", [role]
|
||||
return current_app.config.get('VERISIGN_ROOT'), "", [role]
|
||||
|
||||
def get_available_units(self):
|
||||
"""
|
||||
@ -177,6 +176,35 @@ class VerisignIssuerPlugin(IssuerPlugin):
|
||||
|
||||
:return:
|
||||
"""
|
||||
url = current_app.config.get("VERISIGN_URL") + '/getTokens'
|
||||
url = current_app.config.get("VERISIGN_URL") + '/rest/services/getTokens'
|
||||
response = self.session.post(url, headers={'content-type': 'application/x-www-form-urlencoded'})
|
||||
return handle_response(response.content)['Response']['Order']
|
||||
|
||||
|
||||
class VerisignSourcePlugin(SourcePlugin):
|
||||
title = 'Verisign'
|
||||
slug = 'verisign-source'
|
||||
description = 'Allows for the polling of issued certificates from the VICE2.0 verisign API.'
|
||||
version = verisign.VERSION
|
||||
|
||||
author = 'Kevin Glisson'
|
||||
author_url = 'https://github.com/netflix/lemur.git'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.session = requests.Session()
|
||||
self.session.cert = current_app.config.get('VERISIGN_PEM_PATH')
|
||||
super(VerisignSourcePlugin, self).__init__(*args, **kwargs)
|
||||
|
||||
def get_certificates(self):
|
||||
url = current_app.config.get('VERISIGN_URL') + '/reportingws'
|
||||
end = arrow.now()
|
||||
start = end.replace(years=-5)
|
||||
data = {
|
||||
'reportType': 'detail',
|
||||
'startDate': start.format("MM/DD/YYYY"),
|
||||
'endDate': end.format("MM/DD/YYYY"),
|
||||
'structuredRecord': 'Y',
|
||||
'certStatus': 'Valid',
|
||||
}
|
||||
current_app.logger.debug(data)
|
||||
response = self.session.post(url, data=data)
|
||||
|
1
lemur/plugins/lemur_verisign/tests/conftest.py
Normal file
@ -0,0 +1 @@
|
||||
from lemur.tests.conftest import * # noqa
|
5
lemur/plugins/lemur_verisign/tests/test_verisign.py
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
def test_get_certificates(app):
|
||||
from lemur.plugins.base import plugins
|
||||
p = plugins.get('verisign-source')
|
||||
p.get_certificates()
|
9
lemur/static/app/angular/app.js
vendored
@ -60,6 +60,15 @@ lemur.controller('datePickerController', function ($scope, $timeout){
|
||||
};
|
||||
});
|
||||
|
||||
lemur.service('DefaultService', function (LemurRestangular) {
|
||||
var DefaultService = this;
|
||||
DefaultService.get = function () {
|
||||
return LemurRestangular.all('defaults').customGET().then(function (defaults) {
|
||||
return defaults;
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
lemur.factory('LemurRestangular', function (Restangular, $location, $auth) {
|
||||
return Restangular.withConfig(function (RestangularConfigurer) {
|
||||
RestangularConfigurer.setBaseUrl('http://localhost:5000/api/1');
|
||||
|
@ -30,6 +30,9 @@ angular.module('lemur')
|
||||
.controller('AuthorityCreateController', function ($scope, $modalInstance, AuthorityService, LemurRestangular, RoleService, PluginService, WizardHandler) {
|
||||
$scope.authority = LemurRestangular.restangularizeElement(null, {}, 'authorities');
|
||||
|
||||
// set the defaults
|
||||
AuthorityService.getDefaults($scope.authority);
|
||||
|
||||
$scope.loading = false;
|
||||
$scope.create = function (authority) {
|
||||
WizardHandler.wizard().context.loading = true;
|
||||
|
@ -10,7 +10,7 @@
|
||||
Owner
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="email" name="owner" ng-model="authority.owner" placeholder="owner@netflix.com"
|
||||
<input type="email" name="owner" ng-model="authority.owner" placeholder="owner@example.com"
|
||||
class="form-control" required/>
|
||||
|
||||
<p ng-show="editForm.owner.$invalid && !editForm.owner.$pristine" class="help-block">Enter a valid
|
||||
|
@ -16,7 +16,7 @@
|
||||
Owner
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="email" name="ownerEmail" ng-model="authority.ownerEmail" placeholder="TeamDL@netflix.com" tooltip="This is the authorities team distribution list or the main point of contact for this authority" class="form-control" required/>
|
||||
<input type="email" name="ownerEmail" ng-model="authority.ownerEmail" placeholder="TeamDL@example.com" tooltip="This is the authorities team distribution list or the main point of contact for this authority" class="form-control" required/>
|
||||
<p ng-show="trackingForm.ownerEmail.$invalid && !trackingForm.ownerEmail.$pristine" class="help-block">You must enter an Certificate Authority owner</p>
|
||||
</div>
|
||||
</div>
|
||||
|
12
lemur/static/app/angular/authorities/services.js
vendored
@ -56,7 +56,7 @@ angular.module('lemur')
|
||||
});
|
||||
return LemurRestangular.all('authorities');
|
||||
})
|
||||
.service('AuthorityService', function ($location, AuthorityApi, toaster) {
|
||||
.service('AuthorityService', function ($location, AuthorityApi, DefaultService, toaster) {
|
||||
var AuthorityService = this;
|
||||
AuthorityService.findAuthorityByName = function (filterValue) {
|
||||
return AuthorityApi.getList({'filter[name]': filterValue})
|
||||
@ -117,6 +117,16 @@ angular.module('lemur')
|
||||
});
|
||||
};
|
||||
|
||||
AuthorityService.getDefaults = function (authority) {
|
||||
return DefaultService.get().then(function (defaults) {
|
||||
authority.caDN.country = defaults.country;
|
||||
authority.caDN.state = defaults.state;
|
||||
authority.caDN.location = defaults.location;
|
||||
authority.caDN.organization = defaults.organization;
|
||||
authority.caDN.organizationalUnit = defaults.organizationalUnit;
|
||||
});
|
||||
};
|
||||
|
||||
AuthorityService.getRoles = function (authority) {
|
||||
return authority.getList('roles').then(function (roles) {
|
||||
authority.roles = roles;
|
||||
|
@ -4,7 +4,7 @@
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<input type="text" ng-model="certificate.selectedDestination" placeholder="AWS, TheSecret..."
|
||||
<input type="text" ng-model="certificate.selectedDestination" placeholder="AWS..."
|
||||
typeahead="destination.label for destination in destinationService.findDestinationsByName($viewValue)" typeahead-loading="loadingDestinations"
|
||||
class="form-control input-md" typeahead-on-select="certificate.attachDestination($item)" typeahead-min-wait="50"
|
||||
tooltip="Lemur can upload certificates to any pre-defined destination"
|
||||
|
@ -10,7 +10,7 @@
|
||||
Owner
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="email" name="owner" ng-model="certificate.owner" placeholder="owner@netflix.com"
|
||||
<input type="email" name="owner" ng-model="certificate.owner" placeholder="owner@example.com"
|
||||
class="form-control" required/>
|
||||
|
||||
<p ng-show="editForm.owner.$invalid && !editForm.owner.$pristine" class="help-block">Enter a valid
|
||||
|
@ -6,7 +6,7 @@
|
||||
Owner
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="email" name="ownerEmail" ng-model="certificate.owner" placeholder="TeamDL@netflix.com" tooltip="This is the certificates team distribution list or main point of contact" class="form-control" required/>
|
||||
<input type="email" name="ownerEmail" ng-model="certificate.owner" placeholder="TeamDL@example.com" tooltip="This is the certificates team distribution list or main point of contact" class="form-control" required/>
|
||||
<p ng-show="trackingForm.ownerEmail.$invalid && !trackingForm.ownerEmail.$pristine" class="help-block">You must enter an Certificate owner</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -11,7 +11,7 @@
|
||||
</label>
|
||||
|
||||
<div class="col-sm-10">
|
||||
<input type="email" name="owner" ng-model="certificate.owner" placeholder="owner@netflix.com"
|
||||
<input type="email" name="owner" ng-model="certificate.owner" placeholder="owner@example.com"
|
||||
class="form-control" required/>
|
||||
|
||||
<p ng-show="uploadForm.owner.$invalid && !uploadForm.owner.$pristine" class="help-block">Enter a valid
|
||||
@ -24,7 +24,7 @@
|
||||
Custom Name <span class="glyphicon glyphicon-question-sign"></span>
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<input name="name" ng-model="certificate.name" placeholder="example.netflix.net-SymantecCorporation-20150828-20160830" class="form-control"/>
|
||||
<input name="name" ng-model="certificate.name" placeholder="the.example.net-SymantecCorporation-20150828-20160830" class="form-control"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group"
|
||||
|
@ -89,7 +89,7 @@ angular.module('lemur')
|
||||
});
|
||||
return LemurRestangular.all('certificates');
|
||||
})
|
||||
.service('CertificateService', function ($location, CertificateApi, LemurRestangular, toaster) {
|
||||
.service('CertificateService', function ($location, CertificateApi, LemurRestangular, DefaultService, toaster) {
|
||||
var CertificateService = this;
|
||||
CertificateService.findCertificatesByName = function (filterValue) {
|
||||
return CertificateApi.getList({'filter[name]': filterValue})
|
||||
@ -207,7 +207,7 @@ angular.module('lemur')
|
||||
};
|
||||
|
||||
CertificateService.getDefaults = function (certificate) {
|
||||
return certificate.customGET('defaults').then(function (defaults) {
|
||||
return DefaultService.get().then(function (defaults) {
|
||||
certificate.country = defaults.country;
|
||||
certificate.state = defaults.state;
|
||||
certificate.location = defaults.location;
|
||||
|
@ -8,12 +8,5 @@
|
||||
<div class="row featurette">
|
||||
<div class="col-md-10">
|
||||
<h2 class="featurette-heading">SSL In The Cloud <span class="text-muted">Encrypt it all </span></h2>
|
||||
|
||||
<p class="lead">The Security Operations team manages all of the SSL certificate generation at Netflix. This
|
||||
portal was created to serve as both a self service application so that application owners can provision
|
||||
their own certificates and to help enforce some key naming and security conventions, in order provide
|
||||
Netflix with scalable and manageable SSL security.</p>
|
||||
|
||||
<p>See <a href="http://go/ssl">go/ssl</a> for more info.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,33 +0,0 @@
|
||||
"""
|
||||
.. module: lemur.status.views
|
||||
:copyright: (c) 2015 by Netflix Inc., see AUTHORS for more
|
||||
:license: Apache, see LICENSE for more details.
|
||||
"""
|
||||
import os
|
||||
|
||||
from flask import app, Blueprint, jsonify
|
||||
from flask.ext.restful import Api
|
||||
|
||||
from lemur.auth.service import AuthenticatedResource
|
||||
|
||||
|
||||
mod = Blueprint('status', __name__)
|
||||
api = Api(mod)
|
||||
|
||||
|
||||
class Status(AuthenticatedResource):
|
||||
""" Defines the 'accounts' endpoint """
|
||||
def __init__(self):
|
||||
super(Status, self).__init__()
|
||||
|
||||
def get(self):
|
||||
if not os.path.isdir(os.path.join(app.config.get("KEY_PATH"), "decrypted")):
|
||||
return jsonify({
|
||||
'environment': app.config.get('ENVIRONMENT'),
|
||||
'status': 'degraded',
|
||||
'message': "This Lemur instance is in a degraded state and is unable to issue certificates, please alert secops@netflix.com"})
|
||||
else:
|
||||
return jsonify({
|
||||
'environment': app.config.get('ENVIRONMENT'),
|
||||
'status': 'healthy',
|
||||
'message': "This Lemur instance is healthy"})
|
@ -8,6 +8,7 @@ from lemur.roles import service as role_service
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption("--lemurconfig", help="override the default test config")
|
||||
parser.addoption("--runslow", action="store_true", help="run slow tests")
|
||||
|
||||
|
||||
@ -29,12 +30,15 @@ def pytest_runtest_makereport(item, call):
|
||||
|
||||
|
||||
@pytest.yield_fixture(scope="session")
|
||||
def app():
|
||||
def app(request):
|
||||
"""
|
||||
Creates a new Flask application for a test duration.
|
||||
Uses application factory `create_app`.
|
||||
"""
|
||||
_app = create_app(os.path.dirname(os.path.realpath(__file__)) + '/conf.py')
|
||||
if request.config.getoption('--lemurconfig'):
|
||||
_app = create_app(request.config.getoption('--lemurconfig'))
|
||||
else:
|
||||
_app = create_app(os.path.dirname(os.path.realpath(__file__)) + '/conf.py')
|
||||
ctx = _app.app_context()
|
||||
ctx.push()
|
||||
|
||||
|
@ -10,3 +10,6 @@ exclude = .tox,.git,*/migrations/*,lemur/static/*,docs/*
|
||||
|
||||
[wheel]
|
||||
universal = 1
|
||||
|
||||
[metadata]
|
||||
description-file = README.rst
|
||||
|
30
setup.py
@ -9,14 +9,16 @@ Is an SSL management and orchestration tool.
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
import json
|
||||
import os.path
|
||||
import datetime
|
||||
|
||||
from distutils import log
|
||||
from distutils.core import Command
|
||||
from setuptools.command.develop import develop
|
||||
from setuptools.command.install import install
|
||||
from setuptools.command.sdist import sdist
|
||||
from setuptools import setup
|
||||
from setuptools import setup, find_packages
|
||||
from subprocess import check_output
|
||||
|
||||
ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__)))
|
||||
@ -39,7 +41,7 @@ install_requires = [
|
||||
'six==1.9.0',
|
||||
'gunicorn==19.3.0',
|
||||
'pycrypto==2.6.1',
|
||||
'cryptography==1.0',
|
||||
'cryptography==1.0.1',
|
||||
'pyopenssl==0.15.1',
|
||||
'pyjwt==1.0.1',
|
||||
'xmltodict==0.9.2',
|
||||
@ -87,9 +89,18 @@ class DevelopWithBuildStatic(develop):
|
||||
|
||||
|
||||
class SdistWithBuildStatic(sdist):
|
||||
def make_distribution(self):
|
||||
def make_release_tree(self, *a, **kw):
|
||||
dist_path = self.distribution.get_fullname()
|
||||
|
||||
sdist.make_release_tree(self, *a, **kw)
|
||||
|
||||
self.reinitialize_command('build_static', work_path=dist_path)
|
||||
self.run_command('build_static')
|
||||
return sdist.make_distribution(self)
|
||||
|
||||
with open(os.path.join(dist_path, 'lemur-package.json'), 'w') as fp:
|
||||
json.dump({
|
||||
'createdAt': datetime.datetime.utcnow().isoformat() + 'Z',
|
||||
}, fp)
|
||||
|
||||
|
||||
class BuildStatic(Command):
|
||||
@ -100,7 +111,8 @@ class BuildStatic(Command):
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
log.info("running [npm install --quiet]")
|
||||
log.info("running [npm install --quiet] in {0}".format(ROOT))
|
||||
|
||||
check_output(['npm', 'install', '--quiet'], cwd=ROOT)
|
||||
|
||||
log.info("running [gulp build]")
|
||||
@ -110,11 +122,14 @@ class BuildStatic(Command):
|
||||
|
||||
setup(
|
||||
name='lemur',
|
||||
version='0.1',
|
||||
version='0.1.3',
|
||||
author='Kevin Glisson',
|
||||
author_email='kglisson@netflix.com',
|
||||
url='https://github.com/netflix/lemur',
|
||||
download_url='https://github.com/Netflix/lemur/archive/0.1.3.tar.gz',
|
||||
description='Certificate management and orchestration service',
|
||||
long_description=open(os.path.join(ROOT, 'README.rst')).read(),
|
||||
packages=['lemur'],
|
||||
packages=find_packages(),
|
||||
include_package_data=True,
|
||||
zip_safe=False,
|
||||
install_requires=install_requires,
|
||||
@ -127,7 +142,6 @@ setup(
|
||||
'build_static': BuildStatic,
|
||||
'sdist': SdistWithBuildStatic,
|
||||
'install': SmartInstall
|
||||
|
||||
},
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
|