-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9a14e89
commit 7011880
Showing
148 changed files
with
28,132 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from django.apps import AppConfig | ||
|
||
|
||
class AppConfig(AppConfig): | ||
name = 'app' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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') | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
|
Oops, something went wrong.