From 6e4a4614558a252b81dc56a7b9ada3c07d27b26d Mon Sep 17 00:00:00 2001 From: helgi Date: Mon, 29 Aug 2016 17:58:07 -0700 Subject: [PATCH] fix(certs): allow empty Common Name in certificates Fixes #1000 --- .../api/migrations/0016_auto_20160830_0104.py | 20 +++++++++++ rootfs/api/models/certificate.py | 2 +- rootfs/api/tests/certs/self-signed.cert | 21 ++++++++++++ rootfs/api/tests/certs/self-signed.csr | 17 ++++++++++ rootfs/api/tests/certs/self-signed.key | 27 +++++++++++++++ rootfs/api/tests/test_certificate.py | 33 +++++++++++++++++++ 6 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 rootfs/api/migrations/0016_auto_20160830_0104.py create mode 100644 rootfs/api/tests/certs/self-signed.cert create mode 100644 rootfs/api/tests/certs/self-signed.csr create mode 100644 rootfs/api/tests/certs/self-signed.key diff --git a/rootfs/api/migrations/0016_auto_20160830_0104.py b/rootfs/api/migrations/0016_auto_20160830_0104.py new file mode 100644 index 000000000..d73124ca0 --- /dev/null +++ b/rootfs/api/migrations/0016_auto_20160830_0104.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10 on 2016-08-30 01:04 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0015_auto_20160822_2103'), + ] + + operations = [ + migrations.AlterField( + model_name='certificate', + name='common_name', + field=models.TextField(editable=False, null=True), + ), + ] diff --git a/rootfs/api/models/certificate.py b/rootfs/api/models/certificate.py index efac963e0..bcdf812e5 100644 --- a/rootfs/api/models/certificate.py +++ b/rootfs/api/models/certificate.py @@ -81,7 +81,7 @@ class Certificate(AuditedModel): certificate = models.TextField(validators=[validate_certificate]) key = models.TextField() # X.509 certificates allow any string of information as the common name. - common_name = models.TextField(editable=False, unique=False) + common_name = models.TextField(editable=False, unique=False, null=True) # A list of DNS records if certificate has SubjectAltName san = ArrayField(models.CharField(max_length=253), null=True) # SHA256 fingerprint diff --git a/rootfs/api/tests/certs/self-signed.cert b/rootfs/api/tests/certs/self-signed.cert new file mode 100644 index 000000000..a5779b0be --- /dev/null +++ b/rootfs/api/tests/certs/self-signed.cert @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDZjCCAk4CCQDeqDhK+PmamDANBgkqhkiG9w0BAQsFADB1MQswCQYDVQQGEwJV +UzELMAkGA1UECBMCQ0ExCzAJBgNVBAcTAlNGMREwDwYDVQQKEwhEZWlzIEluYzEU +MBIGA1UECxMLRW5naW5lZXJpbmcxIzAhBgkqhkiG9w0BCQEWFGVuZ2luZWVyaW5n +QGRlaXMuY29tMB4XDTE2MDgzMDAwNTE1NFoXDTE3MDgzMDAwNTE1NFowdTELMAkG +A1UEBhMCVVMxCzAJBgNVBAgTAkNBMQswCQYDVQQHEwJTRjERMA8GA1UEChMIRGVp +cyBJbmMxFDASBgNVBAsTC0VuZ2luZWVyaW5nMSMwIQYJKoZIhvcNAQkBFhRlbmdp +bmVlcmluZ0BkZWlzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AKMjs+IP0V1Fwgn4FNLvsGn1d4TlshXBEFeLUxFVPBKIRSy3TiVNpIFmkJfV+Car +JH26e1I65oX0r58w1OvhCmepzGsvij63+u81XPx0xe6CffUiy36Sv6M6ezVF3mrC +e4FvdM2eCCMYJvKYoQKpUFyIPOyfX6lZSjhDjcVdw6mLgboWh5hz9k3Vu1U7mwQd +l2FJTuwXnexQ5cRU9HzcEnA3RJAhlzcw/Ns11HVKuDZHdbvqIy5hKF99bxf5XnNg +QSI6KKALsFFKqCJsJ0MRXXQPuGK87meqjGnRbXVYh8/splN6DkCicTQ6pPrl0zRo +XikRxxE6VviOHpHD6KDrR/8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAQjsDk1Bc ++/fSM2ksuue+MPnXfpqTW+yZZ6HvyCsODt3R8Z5cHtsesBywWxtGXPGYAFuUKcHJ +eibo7z2o71eO0vx0tQQH/+y6Dw+5h8RHb/XTj/vMvnYSeQ2R+yVbGP/v/PWfeni/ +13QlEZmW2Bi4v8D/z+FacumZ4nZF6LrXG/OmygoTA/UDB5yAiH0G8L2xHfS5xy8s +gRNXFXIUScA1iTFQgYEPRorzLwYtKBlGsr6wEbehkbq4D+1KjJa7aEukAakxGHAR +000i9TMno4EDivZUC0xfQaXvBFfCHu/hrj1H3Obw1gWTKjsCe6QZwb+mWgbOcL4U +2Ul1nLoBiMR6Kg== +-----END CERTIFICATE----- diff --git a/rootfs/api/tests/certs/self-signed.csr b/rootfs/api/tests/certs/self-signed.csr new file mode 100644 index 000000000..fc88e1da5 --- /dev/null +++ b/rootfs/api/tests/certs/self-signed.csr @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICujCCAaICAQAwdTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMQswCQYDVQQH +EwJTRjERMA8GA1UEChMIRGVpcyBJbmMxFDASBgNVBAsTC0VuZ2luZWVyaW5nMSMw +IQYJKoZIhvcNAQkBFhRlbmdpbmVlcmluZ0BkZWlzLmNvbTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAKMjs+IP0V1Fwgn4FNLvsGn1d4TlshXBEFeLUxFV +PBKIRSy3TiVNpIFmkJfV+CarJH26e1I65oX0r58w1OvhCmepzGsvij63+u81XPx0 +xe6CffUiy36Sv6M6ezVF3mrCe4FvdM2eCCMYJvKYoQKpUFyIPOyfX6lZSjhDjcVd +w6mLgboWh5hz9k3Vu1U7mwQdl2FJTuwXnexQ5cRU9HzcEnA3RJAhlzcw/Ns11HVK +uDZHdbvqIy5hKF99bxf5XnNgQSI6KKALsFFKqCJsJ0MRXXQPuGK87meqjGnRbXVY +h8/splN6DkCicTQ6pPrl0zRoXikRxxE6VviOHpHD6KDrR/8CAwEAAaAAMA0GCSqG +SIb3DQEBBQUAA4IBAQB9yz4nqA1akJX+AtNZP/xDXgsfBB35zfOrzvuLVOU4S0kG +Y488FwrhwI62HbOi6rRADQ0mCrgH4H2l+6seH8OEB12hI9KIPIBQCK+TJJPBlhgY +rFDpG05n3M0oq86FQ0iOxSdDZ562E5fPVi3YaQZvgrWnX6S/YGB37m9Dblf5gzGz +TftjOi34LA0LWkJCwMTARUGR943LURufYyduotQw8/3oKbQSOAWCub7beEPQenBB +OXR3hBfQCtOPY0NbuBGSRqBuJbfoFJbMlK5TNI0bYBH+w7RHzw3y36cogHVz8ioT +EMch2kgSeUTsKyjCIp3BS2hyk2PqHYvu2Eud++Er +-----END CERTIFICATE REQUEST----- diff --git a/rootfs/api/tests/certs/self-signed.key b/rootfs/api/tests/certs/self-signed.key new file mode 100644 index 000000000..9172e0274 --- /dev/null +++ b/rootfs/api/tests/certs/self-signed.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAoyOz4g/RXUXCCfgU0u+wafV3hOWyFcEQV4tTEVU8EohFLLdO +JU2kgWaQl9X4Jqskfbp7UjrmhfSvnzDU6+EKZ6nMay+KPrf67zVc/HTF7oJ99SLL +fpK/ozp7NUXeasJ7gW90zZ4IIxgm8pihAqlQXIg87J9fqVlKOEONxV3DqYuBuhaH +mHP2TdW7VTubBB2XYUlO7Bed7FDlxFT0fNwScDdEkCGXNzD82zXUdUq4Nkd1u+oj +LmEoX31vF/lec2BBIjoooAuwUUqoImwnQxFddA+4YrzuZ6qMadFtdViHz+ymU3oO +QKJxNDqk+uXTNGheKRHHETpW+I4ekcPooOtH/wIDAQABAoIBACi2STbaIbJ4LSNV +wMSfQlQ/CNOmitm4834Va+aAcdxiG3k8SYkvpiUQ1na91A66WQHzXsE3p724QXel +tQ0kfPc/vZ7mH0blnP7DP3BVJ+wMrqhVRZlRv/dZKdQymn3kCPRVPz3s+TTg2x9h +jZTfcgmVija20yWs/cOqwB+H9cNCgkwC86DQOLVOL67+nKXt4lDra23gEf9lqNJB +XtHQZhSFJQEGGetu6wTFTVw7nzKbtAnepwLGyG/mDm0z3rygzFmtw80jkEuhAALZ +wwBVKVsKKMHow4VQi6mKEtZjEG42UxXIeWXOSiKNlq7pd9QZrxdH8CVSvNeV+aAT +IMxXn4ECgYEA1CjLh2yvYPyB7FDoEObEcR+2uedIbOTKufTLLN8u6eDcQ+FtJwPb +AP1s1TmoOcRDlvzTbFZj+PL3dZyakCqUY8QFIFL1viGVVhfYDGIfEFMQ5gFDibJI +acGt3hvQvkCHxZgREWtLDkP8Oa8mHR/BVjKAHPB6nBwy9An/uIzSysECgYEAxNnC +1+p3mFiXhb5mrDaieoCIKueL7w/DRqAHfEbM61/0oDJPpsHrPbDbWwcWwWdveOqn +sQOhySd0tFsC9OhOAGwu55qnonbQW7uRNijuRIxNYsqi9dLTNfyO3neJxzE3LtZe +95HWDJG8s5J/Kd7Ymai6RtK01UMGa0josSCwgr8CgYBP92hvjPm1trdJ2Vz/MdwN +P4TiIVjdIod++9OxABZwtP6Q32EC+aMMhnkFDYxo6Z8IRBd0mENqTDoVrIddm47+ +452DB4H0vjfJkYcvc7R9tLGD4CoSto4wvn3IX/eYHj6OrbiRNj2+DMX/ABN/mr6G +vNYpEkNEoCRcc4BdkUbKgQKBgCbIgIrptwZc7f17td7YJMrd5/YMCJXhFSgk/1SM +3nLBRQEK6IaCTkapQY59pw4TwvKfyMonXQi0rVmbVMnLuxJ6PgODhOONZR+tpL52 +8fqvac+8/L5R+yr3x24tPwfvul+P/MXqBbIURIlco5EsRqB/jbPGb7pUqj8Y7j93 +oU8hAoGBAM2MnUkMY2in824b2qLZladhy+ng15tUpuyUjYNPkhW9OHcu69SzLjc4 +efHltxLv5rWh2U7++8T2wUx1wBywcMqfqBgCyXQSBvWgFsJlc2OXyrsdk+xzY+Le +FhwsVy9OL/X2SHCxMersB/9wjaumjtIkehpONhDh/6h71VTkSfQa +-----END RSA PRIVATE KEY----- diff --git a/rootfs/api/tests/test_certificate.py b/rootfs/api/tests/test_certificate.py index a2102e1c2..8d6732161 100644 --- a/rootfs/api/tests/test_certificate.py +++ b/rootfs/api/tests/test_certificate.py @@ -99,6 +99,39 @@ def test_get_certificate_screens_data(self): for key, value in list(expected.items()): self.assertEqual(response.data[key], value, key) + def test_get_certificate_self_signed(self): + """ + Load a certificate without Common Name (self signed most likely) + """ + with open('{}/certs/{}.key'.format(TEST_ROOT, 'self-signed')) as f: + key = f.read() + + with open('{}/certs/{}.cert'.format(TEST_ROOT, 'self-signed')) as f: + cert = f.read() + + response = self.client.post( + self.url, + { + 'name': 'random-test-cert-self', + 'certificate': cert, + 'key': key + } + ) + self.assertEqual(response.status_code, 201, response.data) + + response = self.client.get('{}/{}'.format(self.url, 'random-test-cert-self')) + self.assertEqual(response.status_code, 200, response.data) + + expected = { + 'common_name': None, + 'expires': '2017-08-30T00:51:54Z', + 'fingerprint': 'AD:F7:AF:C2:E1:3D:F5:26:47:4E:B9:2D:1C:75:AD:26:6F:05:2C:A7:6F:24:84:A2:8C:39:B3:3F:97:AB:2C:B3', # noqa + 'san': [], + 'domains': [], + } + for key, value in list(expected.items()): + self.assertEqual(response.data[key], value, key) + def test_certficate_denied_requests(self): """Disallow put/patch requests""" response = self.client.put(self.url)