├── PROCESS.md ├── README.md ├── __init__.py ├── config ├── __init__.py ├── admin.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_auto__chg_field_certificate_ca.py │ ├── 0003_auto__del_certificate__add_certficate__add_certificateauthority.py │ ├── 0004_auto__del_certficate__add_certificate__del_field_certificateauthority_.py │ ├── 0005_auto__add_field_certificate_date_created__add_field_certificate_device.py │ ├── 0006_auto__add_field_certificate_md5.py │ ├── 0007_auto__add_field_certificate_serial.py │ └── __init__.py ├── models.py ├── templates │ └── config │ │ ├── generateCA.html │ │ └── index.html ├── tests.py ├── urls.py └── views.py ├── manage.py ├── managedmacadmin ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py ├── mdm ├── NOTES ├── ProfileList.plist ├── __init__.py ├── admin.py ├── commands.py ├── geo.py ├── groups_views.py ├── management │ ├── __init__.py │ └── commands │ │ ├── __init__.py │ │ └── cron.py ├── mcx.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_auto__del_unique_device_serial_number.py │ ├── 0003_auto__add_field_device_model_name.py │ ├── 0004_auto__del_field_command_command__add_field_command_data__chg_field_com.py │ ├── 0005_auto__del_managedpreference__del_unique_managedpreference_application_.py │ ├── 0006_auto__add_inventoryitem.py │ ├── 0007_auto__del_inventoryitem__add_appinventoryitem.py │ ├── 0008_auto__add_lastdevicestatus.py │ ├── 0009_auto__del_lastdevicestatus__add_lastcommandstatus.py │ ├── 0010_auto__del_command__add_devicecommand.py │ ├── 0011_auto__add_devicecheckin.py │ ├── 0012_auto__add_field_devicecheckin_ip.py │ ├── 0013_auto__add_deviceprofile.py │ ├── 0014_auto__add_field_deviceprofile_payload_uuid__add_unique_deviceprofile_d.py │ ├── 0015_auto__del_field_deviceprofile_description__del_field_deviceprofile_rem.py │ ├── 0016_auto__add_profileinventoryitem.py │ ├── 0017_auto__chg_field_profileinventoryitem_uuid.py │ ├── 0018_auto__add_field_devicecommand_attempts__add_field_devicecommand_date_c.py │ ├── 0019_auto__del_field_devicecheckin_date__add_field_devicecheckin_start_date.py │ ├── 0020_auto__del_lastcommandstatus.py │ ├── 0021_auto__add_devicegroup__add_devicegroupmanagedpreference__add_unique_de.py │ ├── 0022_auto__del_field_devicegroupmanagedpreference_frequency__del_unique_dev.py │ ├── 0023_auto__del_field_devicegroupmanagedpreference_application__add_field_de.py │ ├── 0024_auto__del_field_devicemanagedpreference_application__del_field_devicem.py │ ├── 0025_auto__add_field_devicegroup_priority.py │ ├── 0026_auto__add_field_device_last_notification__add_field_device_type__add_f.py │ ├── 0027_auto.py │ ├── 0028_auto.py │ ├── 0029_auto.py │ └── __init__.py ├── models.py ├── plistlib.py ├── preferences_views.py ├── push.py ├── pushcli.py ├── standard_commands.py ├── static │ └── mdm │ │ ├── jquery.plist.css │ │ ├── jquery.plist.js │ │ ├── mdm.js │ │ ├── selectize.bootstrap2.css │ │ ├── selectize.min.js │ │ └── style.css ├── templates │ └── mdm │ │ ├── battery_level.html │ │ ├── detail.html │ │ ├── enroll.html │ │ ├── groups │ │ ├── detail.html │ │ └── index.html │ │ ├── index.html │ │ └── preferences │ │ ├── device.html │ │ └── devicegroup.html ├── templatetags │ ├── __init__.py │ └── mdm_extras.py ├── urls.py └── views.py ├── reports ├── __init__.py ├── admin.py ├── models.py ├── tests.py ├── urls.py └── views.py ├── static ├── admin │ ├── css │ │ ├── base.css │ │ ├── changelists.css │ │ ├── dashboard.css │ │ ├── forms.css │ │ ├── ie.css │ │ ├── login.css │ │ ├── rtl.css │ │ └── widgets.css │ ├── img │ │ ├── changelist-bg.gif │ │ ├── changelist-bg_rtl.gif │ │ ├── chooser-bg.gif │ │ ├── chooser_stacked-bg.gif │ │ ├── default-bg-reverse.gif │ │ ├── default-bg.gif │ │ ├── deleted-overlay.gif │ │ ├── gis │ │ │ ├── move_vertex_off.png │ │ │ └── move_vertex_on.png │ │ ├── icon-no.gif │ │ ├── icon-unknown.gif │ │ ├── icon-yes.gif │ │ ├── icon_addlink.gif │ │ ├── icon_alert.gif │ │ ├── icon_calendar.gif │ │ ├── icon_changelink.gif │ │ ├── icon_clock.gif │ │ ├── icon_deletelink.gif │ │ ├── icon_error.gif │ │ ├── icon_searchbox.png │ │ ├── icon_success.gif │ │ ├── inline-delete-8bit.png │ │ ├── inline-delete.png │ │ ├── inline-restore-8bit.png │ │ ├── inline-restore.png │ │ ├── inline-splitter-bg.gif │ │ ├── nav-bg-grabber.gif │ │ ├── nav-bg-reverse.gif │ │ ├── nav-bg-selected.gif │ │ ├── nav-bg.gif │ │ ├── selector-icons.gif │ │ ├── selector-search.gif │ │ ├── sorting-icons.gif │ │ ├── tool-left.gif │ │ ├── tool-left_over.gif │ │ ├── tool-right.gif │ │ ├── tool-right_over.gif │ │ ├── tooltag-add.gif │ │ ├── tooltag-add_over.gif │ │ ├── tooltag-arrowright.gif │ │ └── tooltag-arrowright_over.gif │ └── js │ │ ├── LICENSE-JQUERY.txt │ │ ├── SelectBox.js │ │ ├── SelectFilter2.js │ │ ├── actions.js │ │ ├── actions.min.js │ │ ├── admin │ │ ├── DateTimeShortcuts.js │ │ └── RelatedObjectLookups.js │ │ ├── calendar.js │ │ ├── collapse.js │ │ ├── collapse.min.js │ │ ├── core.js │ │ ├── inlines.js │ │ ├── inlines.min.js │ │ ├── jquery.init.js │ │ ├── jquery.js │ │ ├── jquery.min.js │ │ ├── prepopulate.js │ │ ├── prepopulate.min.js │ │ ├── timeparse.js │ │ └── urlify.js ├── css │ ├── bootstrap-responsive.min.css │ ├── bootstrap.min.css │ ├── datatables-bootstrap.css │ ├── font-awesome.min.css │ ├── site.css │ ├── smoothness │ │ ├── images │ │ │ ├── animated-overlay.gif │ │ │ ├── ui-bg_flat_0_aaaaaa_40x100.png │ │ │ ├── ui-bg_flat_75_ffffff_40x100.png │ │ │ ├── ui-bg_glass_55_fbf9ee_1x400.png │ │ │ ├── ui-bg_glass_65_ffffff_1x400.png │ │ │ ├── ui-bg_glass_75_dadada_1x400.png │ │ │ ├── ui-bg_glass_75_e6e6e6_1x400.png │ │ │ ├── ui-bg_glass_95_fef1ec_1x400.png │ │ │ ├── ui-bg_highlight-soft_75_cccccc_1x100.png │ │ │ ├── ui-icons_222222_256x240.png │ │ │ ├── ui-icons_2e83ff_256x240.png │ │ │ ├── ui-icons_454545_256x240.png │ │ │ ├── ui-icons_888888_256x240.png │ │ │ └── ui-icons_cd0a0a_256x240.png │ │ └── jquery-ui-1.10.3.custom.min.css │ └── style.css ├── fonts │ ├── FontAwesome.otf │ ├── fontawesome-webfont.eot │ ├── fontawesome-webfont.svg │ ├── fontawesome-webfont.ttf │ └── fontawesome-webfont.woff ├── img │ ├── arrow-down.gif │ ├── arrow-up.gif │ ├── glyphicons-halflings-white.png │ ├── glyphicons-halflings.png │ └── loading.gif ├── js │ ├── bootstrap.min.js │ ├── datatables-bootstrap.js │ ├── jquery-1.9.1.js │ ├── jquery-ui-1.10.3.custom.min.js │ └── jquery.dataTables.min.js └── mdm │ ├── jquery.plist.css │ ├── jquery.plist.js │ ├── mdm.js │ ├── selectize.bootstrap2.css │ ├── selectize.min.js │ └── style.css └── templates ├── base.html └── registration └── login.html /PROCESS.md: -------------------------------------------------------------------------------- 1 | # Do something to get the data from the pkcs7 wrapper 2 | b = BIO.openfile('test.csr') 3 | p7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(b._ptr()), 1) 4 | s = SMIME.SMIME() 5 | sk = X509.X509_Stack() 6 | s.set_x509_stack(sk) 7 | st = X509.X509_Store() 8 | s.set_x509_store(st) 9 | data = s.verify(p7, None, SMIME.PKCS7_NOVERIFY) 10 | 11 | 12 | # Decrypt the data 13 | b = BIO.MemoryBuffer(pkcs-data-from-above) 14 | p7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(b._ptr()), 1) 15 | k = BIO.MemoryBuffer(cakey) 16 | c = BIO.MemoryBuffer(cacrt) 17 | sender = SMIME.SMIME() 18 | sender.load_key_bio(k, c) 19 | data = sender.decrypt(p7) 20 | 21 | data == CSR to sign 22 | 23 | 24 | 25 | ----- 26 | 27 | CSR in PEM format: 28 | openssl crl2pkcs7 -nocrl -certfile client.pem -outform DER -out client-deg.der 29 | 30 | Now we have the degenerate PKCS7. We need to encrypt it with the 31 | original request certificate. Cipher is des-ede3-cbc (des3). 32 | openssl smime -encrypt -in client-deg.der -des3 -binary -outform DER request.crt >client-enc.der 33 | 34 | Finally, we need to pkcs7 sign the data with our CA cert & key. 35 | openssl smime -sign -in client-enc.der -signer ca.crt -inkey ca.key -outform DER -nodetach >client.p7 36 | 37 | Verify: 38 | openssl smime -verify -in client.p7 -inform DER -CAfile ca.crt 39 | 40 | Send client.p7 back with Content-Type: application/x-pki-message 41 | 42 | 43 | https://github.com/nolanbrown/ios-cert-enrollment/blob/master/lib/ios-cert-enrollment/sign.rb 44 | 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Managed Mac Admin is a Python/VirtualEnv based MDM server. 2 | 3 | This was a project I worked on a few years ago. In the end we decided 4 | to move to a 3rd party commercial MDM solution. Not because this one 5 | did not work well but because my position changed and I was no longer 6 | going to be doing programming and wouldn't be able to keep the system 7 | maintained. We ran this system for about 9 months with no functional 8 | problems, so it does work, though it still needs a lot of TLC if you 9 | plan to use it in a production environment. 10 | 11 | 12 | To get up and running (no promises, most of this is from memory): 13 | 14 | Needed manual update to APNSWrapper to support TLS. 15 | in connection.py change PROTOCOL_SSLv3 to PROTOCOL_SSLv23 16 | 17 | From your virtual environment, run: 18 | 19 | python manage.py syncdb 20 | chmod a+w db.sqlite3 (web server needs write access) 21 | python manage.py migrate 22 | python manage.py collectstatic 23 | 24 | You should now be able to login to the MDM server. 25 | Go to the Config section and Configure your Certificate Authority. 26 | 27 | You should now be able to enroll devices. 28 | 29 | To enable Push-Notifications to work, you need to create your push 30 | certificate and call it "pushcert.pem" then place it in the mdm 31 | directory. 32 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cabal95/managedmacadmin/e0cd4afc717926c1c2d78e9cfe960840829e72a7/__init__.py -------------------------------------------------------------------------------- /config/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cabal95/managedmacadmin/e0cd4afc717926c1c2d78e9cfe960840829e72a7/config/__init__.py -------------------------------------------------------------------------------- /config/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from models import Certificate, CertificateAuthority 3 | 4 | admin.site.register(Certificate) 5 | admin.site.register(CertificateAuthority) 6 | -------------------------------------------------------------------------------- /config/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from south.utils import datetime_utils as datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | 8 | class Migration(SchemaMigration): 9 | 10 | def forwards(self, orm): 11 | # Adding model 'Certificate' 12 | db.create_table(u'config_certificate', ( 13 | (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), 14 | ('revoked', self.gf('django.db.models.fields.BooleanField')(default=False)), 15 | ('key', self.gf('django.db.models.fields.BinaryField')()), 16 | ('certificate', self.gf('django.db.models.fields.BinaryField')()), 17 | ('ca', self.gf('django.db.models.fields.related.ForeignKey')(related_name='certificates', to=orm['config.Certificate'])), 18 | )) 19 | db.send_create_signal(u'config', ['Certificate']) 20 | 21 | 22 | def backwards(self, orm): 23 | # Deleting model 'Certificate' 24 | db.delete_table(u'config_certificate') 25 | 26 | 27 | models = { 28 | u'config.certificate': { 29 | 'Meta': {'object_name': 'Certificate'}, 30 | 'ca': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'certificates'", 'to': u"orm['config.Certificate']"}), 31 | 'certificate': ('django.db.models.fields.BinaryField', [], {}), 32 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 33 | 'key': ('django.db.models.fields.BinaryField', [], {}), 34 | 'revoked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) 35 | } 36 | } 37 | 38 | complete_apps = ['config'] -------------------------------------------------------------------------------- /config/migrations/0002_auto__chg_field_certificate_ca.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from south.utils import datetime_utils as datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | 8 | class Migration(SchemaMigration): 9 | 10 | def forwards(self, orm): 11 | 12 | # Changing field 'Certificate.ca' 13 | db.alter_column(u'config_certificate', 'ca_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['config.Certificate'])) 14 | 15 | def backwards(self, orm): 16 | 17 | # User chose to not deal with backwards NULL issues for 'Certificate.ca' 18 | raise RuntimeError("Cannot reverse this migration. 'Certificate.ca' and its values cannot be restored.") 19 | 20 | # The following code is provided here to aid in writing a correct migration 21 | # Changing field 'Certificate.ca' 22 | db.alter_column(u'config_certificate', 'ca_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['config.Certificate'])) 23 | 24 | models = { 25 | u'config.certificate': { 26 | 'Meta': {'object_name': 'Certificate'}, 27 | 'ca': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'certificates'", 'null': 'True', 'to': u"orm['config.Certificate']"}), 28 | 'certificate': ('django.db.models.fields.BinaryField', [], {}), 29 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 30 | 'key': ('django.db.models.fields.BinaryField', [], {}), 31 | 'revoked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) 32 | } 33 | } 34 | 35 | complete_apps = ['config'] -------------------------------------------------------------------------------- /config/migrations/0003_auto__del_certificate__add_certficate__add_certificateauthority.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from south.utils import datetime_utils as datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | 8 | class Migration(SchemaMigration): 9 | 10 | def forwards(self, orm): 11 | # Deleting model 'Certificate' 12 | db.delete_table(u'config_certificate') 13 | 14 | # Adding model 'Certficate' 15 | db.create_table(u'config_certficate', ( 16 | (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), 17 | ('revoked', self.gf('django.db.models.fields.BooleanField')(default=False)), 18 | ('key', self.gf('django.db.models.fields.TextField')()), 19 | ('certificate', self.gf('django.db.models.fields.TextField')()), 20 | ('ca', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['config.CertificateAuthority'])), 21 | )) 22 | db.send_create_signal(u'config', ['Certficate']) 23 | 24 | # Adding model 'CertificateAuthority' 25 | db.create_table(u'config_certificateauthority', ( 26 | (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), 27 | ('revoked', self.gf('django.db.models.fields.BooleanField')(default=False)), 28 | ('key', self.gf('django.db.models.fields.TextField')()), 29 | ('certificate', self.gf('django.db.models.fields.TextField')()), 30 | ('next_serial', self.gf('django.db.models.fields.IntegerField')(default=1)), 31 | )) 32 | db.send_create_signal(u'config', ['CertificateAuthority']) 33 | 34 | 35 | def backwards(self, orm): 36 | # Adding model 'Certificate' 37 | db.create_table(u'config_certificate', ( 38 | ('revoked', self.gf('django.db.models.fields.BooleanField')(default=False)), 39 | ('certificate', self.gf('django.db.models.fields.BinaryField')()), 40 | ('ca', self.gf('django.db.models.fields.related.ForeignKey')(related_name='certificates', null=True, to=orm['config.Certificate'], blank=True)), 41 | ('key', self.gf('django.db.models.fields.BinaryField')()), 42 | (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), 43 | )) 44 | db.send_create_signal(u'config', ['Certificate']) 45 | 46 | # Deleting model 'Certficate' 47 | db.delete_table(u'config_certficate') 48 | 49 | # Deleting model 'CertificateAuthority' 50 | db.delete_table(u'config_certificateauthority') 51 | 52 | 53 | models = { 54 | u'config.certficate': { 55 | 'Meta': {'object_name': 'Certficate'}, 56 | 'ca': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['config.CertificateAuthority']"}), 57 | 'certificate': ('django.db.models.fields.TextField', [], {}), 58 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 59 | 'key': ('django.db.models.fields.TextField', [], {}), 60 | 'revoked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) 61 | }, 62 | u'config.certificateauthority': { 63 | 'Meta': {'object_name': 'CertificateAuthority'}, 64 | 'certificate': ('django.db.models.fields.TextField', [], {}), 65 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 66 | 'key': ('django.db.models.fields.TextField', [], {}), 67 | 'next_serial': ('django.db.models.fields.IntegerField', [], {'default': '1'}), 68 | 'revoked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) 69 | } 70 | } 71 | 72 | complete_apps = ['config'] -------------------------------------------------------------------------------- /config/migrations/0004_auto__del_certficate__add_certificate__del_field_certificateauthority_.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from south.utils import datetime_utils as datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | 8 | class Migration(SchemaMigration): 9 | 10 | def forwards(self, orm): 11 | # Deleting model 'Certficate' 12 | db.delete_table(u'config_certficate') 13 | 14 | # Adding model 'Certificate' 15 | db.create_table(u'config_certificate', ( 16 | (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), 17 | ('revoked', self.gf('django.db.models.fields.BooleanField')(default=False)), 18 | ('key', self.gf('django.db.models.fields.TextField')()), 19 | ('crt', self.gf('django.db.models.fields.TextField')()), 20 | ('ca', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['config.CertificateAuthority'])), 21 | )) 22 | db.send_create_signal(u'config', ['Certificate']) 23 | 24 | # Deleting field 'CertificateAuthority.certificate' 25 | db.delete_column(u'config_certificateauthority', 'certificate') 26 | 27 | # Adding field 'CertificateAuthority.crt' 28 | db.add_column(u'config_certificateauthority', 'crt', 29 | self.gf('django.db.models.fields.TextField')(default=''), 30 | keep_default=False) 31 | 32 | 33 | def backwards(self, orm): 34 | # Adding model 'Certficate' 35 | db.create_table(u'config_certficate', ( 36 | ('revoked', self.gf('django.db.models.fields.BooleanField')(default=False)), 37 | ('certificate', self.gf('django.db.models.fields.TextField')()), 38 | ('ca', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['config.CertificateAuthority'])), 39 | ('key', self.gf('django.db.models.fields.TextField')()), 40 | (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), 41 | )) 42 | db.send_create_signal(u'config', ['Certficate']) 43 | 44 | # Deleting model 'Certificate' 45 | db.delete_table(u'config_certificate') 46 | 47 | 48 | # User chose to not deal with backwards NULL issues for 'CertificateAuthority.certificate' 49 | raise RuntimeError("Cannot reverse this migration. 'CertificateAuthority.certificate' and its values cannot be restored.") 50 | 51 | # The following code is provided here to aid in writing a correct migration # Adding field 'CertificateAuthority.certificate' 52 | db.add_column(u'config_certificateauthority', 'certificate', 53 | self.gf('django.db.models.fields.TextField')(), 54 | keep_default=False) 55 | 56 | # Deleting field 'CertificateAuthority.crt' 57 | db.delete_column(u'config_certificateauthority', 'crt') 58 | 59 | 60 | models = { 61 | u'config.certificate': { 62 | 'Meta': {'object_name': 'Certificate'}, 63 | 'ca': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['config.CertificateAuthority']"}), 64 | 'crt': ('django.db.models.fields.TextField', [], {}), 65 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 66 | 'key': ('django.db.models.fields.TextField', [], {}), 67 | 'revoked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) 68 | }, 69 | u'config.certificateauthority': { 70 | 'Meta': {'object_name': 'CertificateAuthority'}, 71 | 'crt': ('django.db.models.fields.TextField', [], {}), 72 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 73 | 'key': ('django.db.models.fields.TextField', [], {}), 74 | 'next_serial': ('django.db.models.fields.IntegerField', [], {'default': '1'}), 75 | 'revoked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) 76 | } 77 | } 78 | 79 | complete_apps = ['config'] -------------------------------------------------------------------------------- /config/migrations/0005_auto__add_field_certificate_date_created__add_field_certificate_device.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from south.utils import datetime_utils as datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | 8 | class Migration(SchemaMigration): 9 | 10 | def forwards(self, orm): 11 | # Adding field 'Certificate.date_created' 12 | db.add_column(u'config_certificate', 'date_created', 13 | self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime(2014, 5, 27, 0, 0)), 14 | keep_default=False) 15 | 16 | # Adding field 'Certificate.device' 17 | db.add_column(u'config_certificate', 'device', 18 | self.gf('django.db.models.fields.related.ForeignKey')(to=orm['mdm.Device'], null=True, blank=True), 19 | keep_default=False) 20 | 21 | # Adding field 'CertificateAuthority.date_created' 22 | db.add_column(u'config_certificateauthority', 'date_created', 23 | self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime(2014, 5, 27, 0, 0)), 24 | keep_default=False) 25 | 26 | 27 | def backwards(self, orm): 28 | # Deleting field 'Certificate.date_created' 29 | db.delete_column(u'config_certificate', 'date_created') 30 | 31 | # Deleting field 'Certificate.device' 32 | db.delete_column(u'config_certificate', 'device_id') 33 | 34 | # Deleting field 'CertificateAuthority.date_created' 35 | db.delete_column(u'config_certificateauthority', 'date_created') 36 | 37 | 38 | models = { 39 | u'config.certificate': { 40 | 'Meta': {'object_name': 'Certificate'}, 41 | 'ca': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['config.CertificateAuthority']"}), 42 | 'crt': ('django.db.models.fields.TextField', [], {}), 43 | 'date_created': ('django.db.models.fields.DateTimeField', [], {}), 44 | 'device': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['mdm.Device']", 'null': 'True', 'blank': 'True'}), 45 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 46 | 'key': ('django.db.models.fields.TextField', [], {}), 47 | 'revoked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) 48 | }, 49 | u'config.certificateauthority': { 50 | 'Meta': {'object_name': 'CertificateAuthority'}, 51 | 'crt': ('django.db.models.fields.TextField', [], {}), 52 | 'date_created': ('django.db.models.fields.DateTimeField', [], {}), 53 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 54 | 'key': ('django.db.models.fields.TextField', [], {}), 55 | 'next_serial': ('django.db.models.fields.IntegerField', [], {'default': '1'}), 56 | 'revoked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) 57 | }, 58 | u'mdm.device': { 59 | 'Meta': {'object_name': 'Device'}, 60 | 'activation_lock': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), 61 | 'available_capacity': ('django.db.models.fields.FloatField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), 62 | 'battery_level': ('django.db.models.fields.FloatField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), 63 | 'bluetooth_mac': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '17', 'blank': 'True'}), 64 | 'build_version': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '16', 'blank': 'True'}), 65 | 'capacity': ('django.db.models.fields.FloatField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), 66 | 'cloud_backup': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), 67 | 'ethernet_mac': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '288', 'blank': 'True'}), 68 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 69 | 'last_checkin': ('django.db.models.fields.DateTimeField', [], {}), 70 | 'last_notification': ('django.db.models.fields.DateTimeField', [], {}), 71 | 'locator_service': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), 72 | 'model': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), 73 | 'model_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), 74 | 'name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '128', 'blank': 'True'}), 75 | 'os': ('django.db.models.fields.IntegerField', [], {'default': '0'}), 76 | 'os_version': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '16', 'blank': 'True'}), 77 | 'phone_number': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), 78 | 'product_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), 79 | 'push_magic': ('django.db.models.fields.CharField', [], {'max_length': '48'}), 80 | 'push_token': ('django.db.models.fields.CharField', [], {'max_length': '256'}), 81 | 'push_topic': ('django.db.models.fields.CharField', [], {'max_length': '96'}), 82 | 'serial_number': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}), 83 | 'supervised': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), 84 | 'type': ('django.db.models.fields.IntegerField', [], {'default': '0'}), 85 | 'udid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36', 'db_index': 'True'}), 86 | 'wifi_mac': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '17', 'blank': 'True'}) 87 | } 88 | } 89 | 90 | complete_apps = ['config'] -------------------------------------------------------------------------------- /config/migrations/0006_auto__add_field_certificate_md5.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from south.utils import datetime_utils as datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | 8 | class Migration(SchemaMigration): 9 | 10 | def forwards(self, orm): 11 | # Adding field 'Certificate.md5' 12 | db.add_column(u'config_certificate', 'md5', 13 | self.gf('django.db.models.fields.CharField')(default='', max_length=20), 14 | keep_default=False) 15 | 16 | 17 | def backwards(self, orm): 18 | # Deleting field 'Certificate.md5' 19 | db.delete_column(u'config_certificate', 'md5') 20 | 21 | 22 | models = { 23 | u'config.certificate': { 24 | 'Meta': {'object_name': 'Certificate'}, 25 | 'ca': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['config.CertificateAuthority']"}), 26 | 'crt': ('django.db.models.fields.TextField', [], {}), 27 | 'date_created': ('django.db.models.fields.DateTimeField', [], {}), 28 | 'device': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['mdm.Device']", 'null': 'True', 'blank': 'True'}), 29 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 30 | 'key': ('django.db.models.fields.TextField', [], {}), 31 | 'md5': ('django.db.models.fields.CharField', [], {'max_length': '20'}), 32 | 'revoked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) 33 | }, 34 | u'config.certificateauthority': { 35 | 'Meta': {'object_name': 'CertificateAuthority'}, 36 | 'crt': ('django.db.models.fields.TextField', [], {}), 37 | 'date_created': ('django.db.models.fields.DateTimeField', [], {}), 38 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 39 | 'key': ('django.db.models.fields.TextField', [], {}), 40 | 'next_serial': ('django.db.models.fields.IntegerField', [], {'default': '1'}), 41 | 'revoked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) 42 | }, 43 | u'mdm.device': { 44 | 'Meta': {'object_name': 'Device'}, 45 | 'activation_lock': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), 46 | 'available_capacity': ('django.db.models.fields.FloatField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), 47 | 'battery_level': ('django.db.models.fields.FloatField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), 48 | 'bluetooth_mac': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '17', 'blank': 'True'}), 49 | 'build_version': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '16', 'blank': 'True'}), 50 | 'capacity': ('django.db.models.fields.FloatField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), 51 | 'cloud_backup': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), 52 | 'ethernet_mac': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '288', 'blank': 'True'}), 53 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 54 | 'last_checkin': ('django.db.models.fields.DateTimeField', [], {}), 55 | 'last_notification': ('django.db.models.fields.DateTimeField', [], {}), 56 | 'locator_service': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), 57 | 'model': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), 58 | 'model_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), 59 | 'name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '128', 'blank': 'True'}), 60 | 'os': ('django.db.models.fields.IntegerField', [], {'default': '0'}), 61 | 'os_version': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '16', 'blank': 'True'}), 62 | 'phone_number': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), 63 | 'product_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), 64 | 'push_magic': ('django.db.models.fields.CharField', [], {'max_length': '48'}), 65 | 'push_token': ('django.db.models.fields.CharField', [], {'max_length': '256'}), 66 | 'push_topic': ('django.db.models.fields.CharField', [], {'max_length': '96'}), 67 | 'serial_number': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}), 68 | 'supervised': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), 69 | 'type': ('django.db.models.fields.IntegerField', [], {'default': '0'}), 70 | 'udid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36', 'db_index': 'True'}), 71 | 'wifi_mac': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '17', 'blank': 'True'}) 72 | } 73 | } 74 | 75 | complete_apps = ['config'] -------------------------------------------------------------------------------- /config/migrations/0007_auto__add_field_certificate_serial.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from south.utils import datetime_utils as datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | 8 | class Migration(SchemaMigration): 9 | 10 | def forwards(self, orm): 11 | # Adding field 'Certificate.serial' 12 | db.add_column(u'config_certificate', 'serial', 13 | self.gf('django.db.models.fields.IntegerField')(default=-1), 14 | keep_default=False) 15 | 16 | 17 | def backwards(self, orm): 18 | # Deleting field 'Certificate.serial' 19 | db.delete_column(u'config_certificate', 'serial') 20 | 21 | 22 | models = { 23 | u'config.certificate': { 24 | 'Meta': {'object_name': 'Certificate'}, 25 | 'ca': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['config.CertificateAuthority']"}), 26 | 'crt': ('django.db.models.fields.TextField', [], {}), 27 | 'date_created': ('django.db.models.fields.DateTimeField', [], {}), 28 | 'device': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['mdm.Device']", 'null': 'True', 'blank': 'True'}), 29 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 30 | 'key': ('django.db.models.fields.TextField', [], {}), 31 | 'md5': ('django.db.models.fields.CharField', [], {'max_length': '20'}), 32 | 'revoked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 33 | 'serial': ('django.db.models.fields.IntegerField', [], {}) 34 | }, 35 | u'config.certificateauthority': { 36 | 'Meta': {'object_name': 'CertificateAuthority'}, 37 | 'crt': ('django.db.models.fields.TextField', [], {}), 38 | 'date_created': ('django.db.models.fields.DateTimeField', [], {}), 39 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 40 | 'key': ('django.db.models.fields.TextField', [], {}), 41 | 'next_serial': ('django.db.models.fields.IntegerField', [], {'default': '1'}), 42 | 'revoked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) 43 | }, 44 | u'mdm.device': { 45 | 'Meta': {'object_name': 'Device'}, 46 | 'activation_lock': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), 47 | 'available_capacity': ('django.db.models.fields.FloatField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), 48 | 'battery_level': ('django.db.models.fields.FloatField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), 49 | 'bluetooth_mac': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '17', 'blank': 'True'}), 50 | 'build_version': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '16', 'blank': 'True'}), 51 | 'capacity': ('django.db.models.fields.FloatField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), 52 | 'cloud_backup': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), 53 | 'ethernet_mac': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '288', 'blank': 'True'}), 54 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 55 | 'last_checkin': ('django.db.models.fields.DateTimeField', [], {}), 56 | 'last_notification': ('django.db.models.fields.DateTimeField', [], {}), 57 | 'locator_service': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), 58 | 'model': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), 59 | 'model_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), 60 | 'name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '128', 'blank': 'True'}), 61 | 'os': ('django.db.models.fields.IntegerField', [], {'default': '0'}), 62 | 'os_version': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '16', 'blank': 'True'}), 63 | 'phone_number': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), 64 | 'product_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), 65 | 'push_magic': ('django.db.models.fields.CharField', [], {'max_length': '48'}), 66 | 'push_token': ('django.db.models.fields.CharField', [], {'max_length': '256'}), 67 | 'push_topic': ('django.db.models.fields.CharField', [], {'max_length': '96'}), 68 | 'serial_number': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}), 69 | 'supervised': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), 70 | 'type': ('django.db.models.fields.IntegerField', [], {'default': '0'}), 71 | 'udid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36', 'db_index': 'True'}), 72 | 'wifi_mac': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '17', 'blank': 'True'}) 73 | } 74 | } 75 | 76 | complete_apps = ['config'] -------------------------------------------------------------------------------- /config/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cabal95/managedmacadmin/e0cd4afc717926c1c2d78e9cfe960840829e72a7/config/migrations/__init__.py -------------------------------------------------------------------------------- /config/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | 4 | class CertificateAuthority(models.Model): 5 | revoked = models.BooleanField(default=False) 6 | key = models.TextField() 7 | crt = models.TextField() 8 | next_serial = models.IntegerField(default=1) 9 | date_created = models.DateTimeField() 10 | 11 | class Certificate(models.Model): 12 | revoked = models.BooleanField(default=False) 13 | key = models.TextField() 14 | crt = models.TextField() 15 | ca = models.ForeignKey(CertificateAuthority) 16 | date_created = models.DateTimeField() 17 | md5 = models.CharField(max_length=20) 18 | serial = models.IntegerField() 19 | device = models.ForeignKey("mdm.device", blank=True, null=True) 20 | 21 | -------------------------------------------------------------------------------- /config/templates/config/generateCA.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load static %} 3 | 4 | {% block extra_style %} 5 | 6 | {% endblock %} 7 | 8 | {% block java_script %} 9 | 10 | 38 | {% endblock %} 39 | 40 | {% block content %} 41 |
Organization | 46 |47 | |
---|---|
Organizational Unit | 50 |51 | |
Country | 54 |55 | |
State/Province | 58 |59 | |
City | 62 |63 | |
Server Name | 66 |67 | |