Skip to content

Commit

Permalink
Create initial version
Browse files Browse the repository at this point in the history
  • Loading branch information
tchellomello committed Mar 13, 2018
1 parent 9a14e89 commit 7011880
Show file tree
Hide file tree
Showing 148 changed files with 28,132 additions and 0 deletions.
20 changes: 20 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
FROM fedora
MAINTAINER http://fedoraproject.org/wiki/Cloud

RUN dnf clean all && \
dnf -y update && \
dnf -y install python3 python3-devel python3-pip git \
python3-virtualenv sqlite python-psycopg2 \
openssl-devel && dnf clean all

COPY mysslcerts /code
RUN pip install -r /code/mysslcerts/requirements.txt

# create directory /code and mount sources there
RUN mkdir /code
WORKDIR /code
VOLUME /code

EXPOSE 8000

CMD python mysslcerts/manage.py runserver 0.0.0.0:8000
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
# my-ssl-certs
Simple based Django application to request and sign custom SSL certificates


### Credentials:
admin: **mysslcerts**
Empty file added mysslcerts/app/__init__.py
Empty file.
28 changes: 28 additions & 0 deletions mysslcerts/app/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from django.contrib import admin
from django import forms
from app.models import Topic, Question, Tag

admin.site.register(Tag)

class QuestionModelForm(forms.ModelForm):
class Meta:
fields = ['enabled', 'text', 'answer', 'sort_order', 'topic', 'tags']
model = Question
widgets = {
'answer' : forms.Textarea(attrs={'rows': 30, 'cols': 100}),
}

class QuestionAdmin(admin.ModelAdmin):
list_display = ['text', 'sort_order', 'answer', 'enabled', 'topic']
list_filter = ['topic', 'sort_order', 'enabled', 'tags']
filter_horizontal = ['tags']
search_fields = ['text', 'answer', 'topic__name', 'tags__word']
form = QuestionModelForm
admin.site.register(Question, QuestionAdmin)

class TopicAdmin(admin.ModelAdmin):
list_display = ['name', 'sort_order', 'created', 'modified']
list_filter = ['created', 'modified']
filter_horizontal = ['related_questions']
search_fields = ['name']
admin.site.register(Topic, TopicAdmin)
5 changes: 5 additions & 0 deletions mysslcerts/app/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from django.apps import AppConfig


class AppConfig(AppConfig):
name = 'app'
37 changes: 37 additions & 0 deletions mysslcerts/app/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from django import forms

class generate_ca_and_certificateForm(forms.Form):
ca_common_name = forms.CharField(label='Common Name (CN)', max_length=50)
ca_country = forms.CharField(label='Country (C)', max_length=2)
ca_state = forms.CharField(label='State (ST)', max_length=30)
ca_city = forms.CharField(label='City (L)', max_length=30)
ca_organization = forms.CharField(label='Organization (O)', max_length=30)
ca_organizational_unit = forms.CharField(label='Organizational Unit (OU)', max_length=30, required=False)
ca_days = forms.IntegerField(label='Days to Expire', min_value=1)
ca_email = forms.EmailField(label='Email')

#certificate
cert_common_name = forms.CharField(label='Common Name (CN)', max_length=50)
cert_country = forms.CharField(label='Country (C)', max_length=2)
cert_state = forms.CharField(label='State (ST)', max_length=30)
cert_city = forms.CharField(label='City (L)', max_length=30)
cert_organization = forms.CharField(label='Organization (O)', max_length=30)
cert_organizational_unit = forms.CharField(label='Organizational Unit (OU)', max_length=30, required=False)
cert_days = forms.IntegerField(label='Days to Expire', min_value=1)
cert_email = forms.EmailField(label='Email')

class generate_certificate_from_uploaded_CAForm(forms.Form):
#ca
ca_certificate = forms.FileField()
ca_key = forms.FileField()

#certificate
cert_common_name = forms.CharField(label='Common Name (CN)', max_length=50)
cert_country = forms.CharField(label='Country (C)', max_length=2)
cert_state = forms.CharField(label='State (ST)', max_length=30)
cert_city = forms.CharField(label='City (L)', max_length=30)
cert_organization = forms.CharField(label='Organization (O)', max_length=30)
cert_organizational_unit = forms.CharField(label='Organizational Unit (OU)', max_length=30, required=False)
cert_days = forms.IntegerField(label='Days to Expire', min_value=1)
cert_email = forms.EmailField(label='Email')

167 changes: 167 additions & 0 deletions mysslcerts/app/libs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
from OpenSSL import crypto, SSL
from socket import gethostname
from pprint import pprint
from random import randint
from time import gmtime, mktime
from datetime import timedelta, datetime
from os.path import exists, join
import zipfile
from io import BytesIO

cert_dir = "/tmp"
CA_CERT_FILE = "CA_crt.pem"
CA_KEY_FILE = "CA_key.pem"
CERT_FILE = "cert_crt.pem"
KEY_FILE = "cert_key.pem"
CSR_FILE = "cert_csr.pem"

class CustomSat6Certs():

def __init__(self, zip_filename=None):

# define CA args
self.ca_certificate = None
self.ca_key = None

if zip_filename and isinstance(zip_filename, str) and not zip_filename.endswith('zip'):
self.zip_filename = zip_filename + '.zip'
else:
self.zip_filename = 'certificates.zip'

def create_ca(self, ca_country="", ca_state="", ca_city="",
ca_organization="", ca_organizational_unit="", ca_common_name="", ca_days=365, algo_hash="sha256"):

#create key
k = crypto.PKey()
k.generate_key(crypto.TYPE_RSA, 2048)

#create a self-signed cert for CA use
cert = crypto.X509()
cert.get_subject().C = ca_country
cert.get_subject().ST = ca_state
cert.get_subject().L = ca_city
cert.get_subject().O = ca_organization
cert.get_subject().CN = ca_common_name

#optional
if ca_organizational_unit:
cert.get_subject().OU = ca_organizational_unit

cert.set_serial_number(randint(1,99))
cert.gmtime_adj_notBefore(0)
#notAfter must be in seconds
cert.gmtime_adj_notAfter(int(((datetime.now()+timedelta(days=ca_days))-(datetime.now())).total_seconds()))
cert.set_issuer(cert.get_subject())
cert.set_pubkey(k)
cert.sign(k, algo_hash)

#open(join(cert_dir, CA_CERT_FILE), "wt").write(
# crypto.dump_certificate(crypto.FILETYPE_PEM, cert))

#open(join(cert_dir, CA_KEY_FILE), "wt").write(
# crypto.dump_privatekey(crypto.FILETYPE_PEM, k))

self.ca_certificate = cert
self.ca_key = k
return True

def load_ca_certificate(self, ca_certificate=None):
'''load the CA certificate'''

## type will be str when request.FILES is uploaded to memory
try:
self.ca_certificate = crypto.load_certificate(crypto.FILETYPE_PEM, ca_certificate)
return True
except:
self.ca_certificate = crypto.load_certificate(crypto.FILETYPE_PEM, open(ca_certificate).read())
return True
return False

def load_ca_key(self, ca_key=None):
'''load the CA key'''

## type will be str when request.FILES is uploaded to memory
try:
self.ca_key = crypto.load_privatekey(crypto.FILETYPE_PEM, ca_key)
return True
except:
self.ca_key = crypto.load_privatekey(crypto.FILETYPE_PEM, open(ca_key).read())
return True
return False

def load_certificate(self, certificate=None):
'''load SSL certificate'''

## type will be str when request.FILES is uploaded to memory
try:
c = crypto.load_certificate(crypto.FILETYPE_PEM, certificate)
return c
except:
c = crypto.load_certificate(crypto.FILETYPE_PEM, open(certificate).read())
return c
return False

def verify_certificate_chain(self, ca_certificate=None, trusted_certificate=None):
'''verify SSL trust chain'''
#TODO
pass

def create_cert(self, cert_country="", cert_state="", cert_city="",
cert_organization="", cert_organizational_unit="", cert_common_name="", cert_days=365, algo_hash="sha256"):

if self.ca_certificate == None or self.ca_key == None:
return "Missing CA certificate and key"

#create CSR
req = crypto.X509Req()
req.get_subject().C = cert_country
req.get_subject().ST = cert_state
req.get_subject().L = cert_city
req.get_subject().O = cert_organization
req.get_subject().CN = cert_common_name

#optional
if cert_organizational_unit:
req.get_subject().OU = cert_organizational_unit

#create key
k = crypto.PKey()
k.generate_key(crypto.TYPE_RSA, 2048)

#create csr PEM
req.set_pubkey(k)
req.sign(k, algo_hash)
self.certificate_csr = req

#sign CSR using CA
cert = crypto.X509()
cert.set_serial_number(randint(1,99))
cert.gmtime_adj_notBefore(0)
cert.gmtime_adj_notAfter(int(((datetime.now()+timedelta(days=cert_days))-(datetime.now())).total_seconds()))
cert.set_issuer(self.ca_certificate.get_subject())
cert.set_subject(req.get_subject())
cert.set_pubkey(req.get_pubkey())
cert.sign(self.ca_key, algo_hash)

self.certificate_key = k
self.certificate_crt = cert

#open(join(cert_dir, CERT_FILE), "wt").write(
# crypto.dump_certificate(crypto.FILETYPE_PEM, cert))

#open(join(cert_dir, KEY_FILE), "wt").write(
# crypto.dump_privatekey(crypto.FILETYPE_PEM, k))

return True

def get_zip(self):
zipIO = BytesIO()
with zipfile.ZipFile(zipIO, mode='w', compression=zipfile.ZIP_DEFLATED) as zf:
zf.writestr(CA_CERT_FILE, crypto.dump_certificate(crypto.FILETYPE_PEM, self.ca_certificate))
zf.writestr(CA_KEY_FILE, crypto.dump_privatekey(crypto.FILETYPE_PEM, self.ca_key))
zf.writestr(KEY_FILE, crypto.dump_privatekey(crypto.FILETYPE_PEM, self.certificate_key))
zf.writestr(CERT_FILE, crypto.dump_certificate(crypto.FILETYPE_PEM, self.certificate_crt))
zf.writestr(CSR_FILE, crypto.dump_certificate_request(crypto.FILETYPE_PEM, self.certificate_csr))
zf.close()
zipIO.seek(0)
return zipIO.read()
70 changes: 70 additions & 0 deletions mysslcerts/app/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Generated by Django 2.0.3 on 2018-03-12 22:02

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

initial = True

dependencies = [
]

operations = [
migrations.CreateModel(
name='Question',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('enabled', models.BooleanField(default=True, verbose_name='Enabled?')),
('text', models.CharField(help_text='What is the question?', max_length=200, unique=True)),
('answer', models.CharField(blank=True, help_text='Enter the answer.', max_length=50000)),
('sort_order', models.IntegerField(default=0, help_text='The order you would like the question to be displayed.', verbose_name='sort order')),
],
options={
'verbose_name': 'Question',
'verbose_name_plural': 'Questions',
'ordering': ['sort_order', 'text'],
},
),
migrations.CreateModel(
name='Tag',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('word', models.CharField(max_length=35, unique=True)),
('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')),
('modified', models.DateTimeField(auto_now=True, verbose_name='Modified')),
],
options={
'verbose_name': 'Tag',
'verbose_name_plural': 'Tags',
'ordering': ['word'],
},
),
migrations.CreateModel(
name='Topic',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=200, unique=True)),
('sort_order', models.IntegerField(default=0, help_text='The order you would like the topic to be displayed.', verbose_name='sort order')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')),
('modified', models.DateTimeField(auto_now=True, verbose_name='Modified')),
('related_questions', models.ManyToManyField(blank=True, related_name='related_questions', to='app.Question')),
],
options={
'verbose_name': 'Topic',
'verbose_name_plural': 'Topics',
'ordering': ['sort_order', 'name'],
},
),
migrations.AddField(
model_name='question',
name='tags',
field=models.ManyToManyField(default='', related_name='related_tags', to='app.Tag'),
),
migrations.AddField(
model_name='question',
name='topic',
field=models.ForeignKey(default='', on_delete=django.db.models.deletion.CASCADE, related_name='related_topic', to='app.Topic'),
),
]
Empty file.
49 changes: 49 additions & 0 deletions mysslcerts/app/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from __future__ import unicode_literals
from django.db import models
from django.utils.translation import ugettext_lazy as _

class Tag(models.Model):
word = models.CharField(max_length=35, unique=True)
created = models.DateTimeField('Created', auto_now_add=True)
modified = models.DateTimeField('Modified', auto_now=True)

class Meta:
verbose_name = _("Tag")
verbose_name_plural = _("Tags")
ordering = ['word']

def __unicode__(self):
return u'%s' % (self.word)

class Topic(models.Model):
name = models.CharField(max_length=200, unique=True)
sort_order = models.IntegerField(_('sort order'), default=0,
help_text=_('The order you would like the topic to be displayed.'))
related_questions = models.ManyToManyField('Question', related_name="related_questions", blank=True)
created = models.DateTimeField('Created', auto_now_add=True)
modified = models.DateTimeField('Modified', auto_now=True)

class Meta:
verbose_name = _("Topic")
verbose_name_plural = _("Topics")
ordering = ['sort_order', 'name']

def __unicode__(self):
return u'%s' % (self.name)

class Question(models.Model):
enabled = models.BooleanField('Enabled?', default=True)
text = models.CharField(max_length=200, unique=True, help_text=_('What is the question?'))
answer = models.CharField(max_length=50000, blank=True, help_text=_('Enter the answer.'))
sort_order = models.IntegerField(_('sort order'), default=0, help_text=_('The order you would like the question to be displayed.'))
topic = models.ForeignKey('Topic', related_name="related_topic", default='', on_delete=models.CASCADE)
tags = models.ManyToManyField(Tag, related_name="related_tags", default='')

class Meta:
verbose_name = _("Question")
verbose_name_plural = _("Questions")
ordering = ['sort_order', 'text']

def __unicode__(self):
return u'%s' % (self.text)

Loading

0 comments on commit 7011880

Please sign in to comment.