diff options
author | Rob Austein <sra@hactrn.net> | 2011-12-20 19:00:07 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2011-12-20 19:00:07 +0000 |
commit | b87cc14f975ed5cf1e0b34d3a8e30d49ca1a4632 (patch) | |
tree | 5b5da1a955f697b51aa653a34d6f7c9002fa820c | |
parent | 022a93196b06dbfebb7757ce5b97a814075a57c5 (diff) |
Checkpoint. More schema tweaks (HostedCA model).
svn path=/branches/tk100/; revision=4129
-rw-r--r-- | rpkid/rpki/irdb/models.py | 65 | ||||
-rw-r--r-- | rpkid/rpki/rpkic.py | 63 | ||||
-rw-r--r-- | scripts/convert-from-entitydb-to-sql.py | 13 |
3 files changed, 65 insertions, 76 deletions
diff --git a/rpkid/rpki/irdb/models.py b/rpkid/rpki/irdb/models.py index 2cc46737..20f38d6c 100644 --- a/rpkid/rpki/irdb/models.py +++ b/rpkid/rpki/irdb/models.py @@ -25,6 +25,7 @@ PERFORMANCE OF THIS SOFTWARE. import django.db.models import rpki.x509 import rpki.sundial +import socket ### @@ -148,15 +149,18 @@ class CertificateManager(django.db.models.Manager): Runs certification method for new or updated objects. Returns a tuple consisting of the object and a boolean indicating whether anything has changed. - - This is a somewhat weird use of ._meta.unique_together, but fits - with the way this application use unique indices and foreign keys. """ changed = False try: - obj = self.get(**dict((k, kwargs[k]) for k in self.model._meta.unique_together[0])) + # Icky, but does what we need. + try: + keys = self.model._meta.unique_together + except AttributeError: + keys = ("handle",) + print "++ Keys:", repr(keys) + obj = self.get(**dict((k, kwargs[k]) for k in keys)) except self.model.DoesNotExist: obj = self.model(**kwargs) @@ -176,15 +180,8 @@ class CertificateManager(django.db.models.Manager): ### -class Identity(django.db.models.Model): - handle = HandleField(unique = True) - - def __unicode__(self): - return self.handle - class CA(django.db.models.Model): - identity = django.db.models.ForeignKey(Identity) - purpose = EnumField(choices = ("resources", "servers")) + handle = HandleField(unique = True) certificate = CertificateField() private_key = RSAKeyField() latest_crl = CRLField() @@ -200,18 +197,20 @@ class CA(django.db.models.Model): objects = CertificateManager() - class Meta: - unique_together = ("identity", "purpose") - # These should come from somewhere, but I don't yet know where ca_certificate_lifetime = rpki.sundial.timedelta(days = 3652) crl_interval = rpki.sundial.timedelta(days = 1) + def __unicode__(self): + return self.handle + def avow(self): if self.private_key is None: self.private_key = rpki.x509.RSA.generate() - subject_name = rpki.x509.X501DN("%s BPKI %s CA" % ( - self.identity.handle, self.get_purpose_display())) + if self.handle: + subject_name = rpki.x509.X501DN("%s BPKI resource CA" % self.handle) + else: + subject_name = rpki.x509.X501DN("%s BPKI server CA" % socket.gethostname()) now = rpki.sundial.now() notAfter = now + self.ca_certificate_lifetime self.certificate = rpki.x509.X509.bpki_self_certify( @@ -265,6 +264,7 @@ class CA(django.db.models.Model): self.next_crl_number += 1 class Certificate(django.db.models.Model): + certificate = CertificateField() objects = CertificateManager() @@ -272,10 +272,10 @@ class Certificate(django.db.models.Model): class Meta: abstract = True + unique_together = ("issuer", "handle") def revoke(self): - self.ca.revoke(self) - + self.issuer.revoke(self) class CrossCertification(Certificate): handle = HandleField() @@ -283,7 +283,6 @@ class CrossCertification(Certificate): class Meta: abstract = True - unique_together = ("issuer", "handle") def avow(self): self.certificate = self.issuer.certify( @@ -296,6 +295,20 @@ class CrossCertification(Certificate): def __unicode__(self): return self.handle +class HostedCA(Certificate): + hosted_ca = OneToOneField(CA, related_name = "hosting_ca") + + def avow(self): + self.certificate = self.issuer.certify( + subject_name = self.hosted_ca.getSubject(), + subject_key = self.hosted_ca.getPublicKey(), + interval = self.default_interval, + is_ca = True, + pathLenConstraint = 1) + + def __unicode__(self): + return self.hosted_ca.handle + class Revocation(django.db.models.Model): issuer = django.db.models.ForeignKey(CA, related_name = "revocations") serial = django.db.models.BigIntegerField() @@ -317,7 +330,8 @@ class EECertificate(Certificate): if self.private_key is None: self.private_key = rpki.x509.RSA.generate() subject_name = rpki.x509.X501DN("%s BPKI %s EE" % ( - self.issuer.identity.handle, self.get_purpose_display())) + self.issuer.handle if self.issuer.handle else socket.gethostname(), + self.get_purpose_display())) self.certificate = self.issuer.certify( subject_name = subject_name, subject_key = self.private_key.get_RSApublic(), @@ -329,9 +343,6 @@ class BSC(Certificate): handle = HandleField() pkcs10 = PKCS10Field() - class Meta: - unique_together = ("issuer", "handle") - def avow(self): self.certificate = self.issuer.certify( subject_name = self.pkcs10.getSubject(), @@ -374,7 +385,7 @@ class Parent(CrossCertification): referral_authorization = SignedReferralField(null = True, blank = True) class ROARequest(django.db.models.Model): - identity = django.db.models.ForeignKey(Identity, related_name = "roa_requests") + issuer = django.db.models.ForeignKey(CA, related_name = "roa_requests") asn = django.db.models.BigIntegerField() class ROARequestPrefix(django.db.models.Model): @@ -388,8 +399,8 @@ class ROARequestPrefix(django.db.models.Model): unique_together = ("roa_request", "version", "prefix", "prefixlen", "max_prefixlen") class GhostbusterRequest(django.db.models.Model): - identity = django.db.models.ForeignKey(Identity, related_name = "ghostbuster_requests") - parent = django.db.models.ForeignKey(Parent, related_name = "ghostbuster_requests", null = True) + issuer = django.db.models.ForeignKey(CA, related_name = "ghostbuster_requests") + parent = django.db.models.ForeignKey(Parent, related_name = "ghostbuster_requests", null = True) vcard = django.db.models.TextField() class Repository(CrossCertification): diff --git a/rpkid/rpki/rpkic.py b/rpkid/rpki/rpkic.py index 8ff18fd5..f77eefbb 100644 --- a/rpkid/rpki/rpkic.py +++ b/rpkid/rpki/rpkic.py @@ -216,20 +216,13 @@ class main(rpki.cli.Cmd): def reset_identity(self): try: - self.identity = rpki.irdb.Identity.objects.get(handle = self.handle) - except rpki.irdb.Identity.DoesNotExist: - self.identity = None + self.resource_ca = rpki.irdb.CA.objects.get(handle = self.handle) + except rpki.irdb.CA.DoesNotExist: self.resource_ca = None + try: + self.server_ca = rpki.irdb.CA.objects.get(handle = "") + except rpki.irdb.CA.DoesNotExist: self.server_ca = None - else: - try: - self.resource_ca = self.identity.ca_set.get(purpose = "resources") - except rpki.irdb.CA.DoesNotExist: - self.resource_ca = None - try: - self.server_ca = self.identity.ca_set.get(purpose = "servers") - except rpki.irdb.CA.DoesNotExist: - self.server_ca = None def help_overview(self): """ @@ -243,7 +236,7 @@ class main(rpki.cli.Cmd): self.stdout.write("\n") def irdb_handle_complete(self, klass, text, line, begidx, endidx): - return [obj.handle for obj in klass.objects.all() if obj.handle.startswith(text)] + return [obj.handle for obj in klass.objects.all() if obj.handle and obj.handle.startswith(text)] def do_select_identity(self, arg): """ @@ -257,7 +250,7 @@ class main(rpki.cli.Cmd): self.reset_identity() def complete_select_identity(self, *args): - return self.irdb_handle_complete(rpki.irdb.Identity, *args) + return self.irdb_handle_complete(rpki.irdb.CA, *args) def do_initialize(self, arg): @@ -271,23 +264,14 @@ class main(rpki.cli.Cmd): if arg: raise BadCommandSyntax, "This command takes no arguments" - self.identity, created = rpki.irdb.Identity.objects.get_or_create(handle = self.handle) + self.resource_ca, created = rpki.irdb.CA.objects.get_or_certify(handle = self.handle) if created: - print 'Created new identity for "%s"' % self.handle + print "Created new BPKI resource CA for identity %s" % self.handle - self.resource_ca, created = rpki.irdb.CA.objects.get_or_certify( - identity = self.identity, purpose = "resources") - if created: - print "Created new BPKI resource CA" - - if not self.run_rpkid and not self.run_pubd and not self.run_rootd: - self.server_ca = None - else: - self.server_ca, created = rpki.irdb.CA.objects.get_or_certify( - identity = self.identity, purpose = "servers") + if self.run_rpkid or self.run_pubd or self.run_rootd: + self.server_ca, created = rpki.irdb.CA.objects.get_or_certify(handle = "") if created: print "Created new BPKI server CA" - if self.run_rpkid: rpki.irdb.EECertificate.objects.get_or_certify(issuer = self.server_ca, purpose = "rpkid") rpki.irdb.EECertificate.objects.get_or_certify(issuer = self.server_ca, purpose = "irdbd") @@ -295,6 +279,8 @@ class main(rpki.cli.Cmd): rpki.irdb.EECertificate.objects.get_or_certify(issuer = self.server_ca, purpose = "pubd") if self.run_rpkid or self.run_pubd: rpki.irdb.EECertificate.objects.get_or_certify(issuer = self.server_ca, purpose = "irbe") + if self.run_rootd: + rpki.irdb.EECertificate.objects.get_or_certify(issuer = self.server_ca, purpose = "rootd") ## @todo # Why do we issue root's EE certificate under our server CA? @@ -306,9 +292,6 @@ class main(rpki.cli.Cmd): # -didn't- have to cross-certify. Leave alone for now, but # think about this later. - if self.run_rootd: - rpki.irdb.EECertificate.objects.get_or_certify(issuer = self.server_ca, purpose = "rootd") - # Build the identity.xml file. Need to check for existing file so we don't # overwrite? Worry about that later. @@ -372,7 +355,7 @@ class main(rpki.cli.Cmd): obj.avow() for ca in rpki.irdb.CA.all(): - print "Regenerating CRL for", ca.identity.handle, ca.purpose + print "Regenerating CRL for", ca.handle if ca.handle else "[servers]" ca.generate_crl() def do_configure_child(self, arg): @@ -885,16 +868,16 @@ class main(rpki.cli.Cmd): action = "set", bpki_crl = self.server_ca.latest_crl)) + for ca in rpki.irdb.CA.objects.exclude(handle = ""): - for xmlfile in xmlfiles: - - - # Check for certificates before attempting anything else - - hosted_cacert = findbase64(tree, "bpki_ca_certificate") - if not hosted_cacert: - print "Nothing else I can do without a trust anchor for the entity I'm hosting." - continue + # rpkid_xcert is the server CA cross-certifying this resource CA + # so that stuff trusted by this resource CA will validate for + # rpkid. The resource cross-certifies parents and children with + # PathLen 0 so that parent and child EE certs can be rolled; + # this cross-certification therefore needs to be PathLen 1. + # + # HostedCA class in models is an attempt to represent this. + # Not yet hacked into other code. rpkid_xcert = rpki.x509.X509(PEM_file = self.bpki_servers.fxcert( b64 = hosted_cacert.get_Base64(), diff --git a/scripts/convert-from-entitydb-to-sql.py b/scripts/convert-from-entitydb-to-sql.py index 1fae02c4..aa15b461 100644 --- a/scripts/convert-from-entitydb-to-sql.py +++ b/scripts/convert-from-entitydb-to-sql.py @@ -101,10 +101,6 @@ assert e.tag == tag_identity self_handle = e.get("handle") assert self_handle == cfg.get("handle", section = "myrpki") -# Create identity if we haven't already - -identity = rpki.irdb.Identity.objects.get_or_create(handle = self_handle)[0] - # Some BPKI utillity routines def read_openssl_serial(filename): @@ -121,8 +117,7 @@ def get_or_create_CA(purpose): crl_number = read_openssl_serial(os.path.join(bpki, purpose, "crl_number")) return rpki.irdb.CA.objects.get_or_create( - identity = identity, - purpose = purpose, + handle = self_handle if purpose == "resources" else "", certificate = cer, private_key = key, latest_crl = crl, @@ -319,7 +314,7 @@ for filename in glob.iglob(os.path.join(entitydb, "parents", "*.xml")): """, (self_handle, parent_handle)) for row in cur.fetchall(): rpki.irdb.GhostbusterRequest.objects.get_or_create( - identity = identity, + issuer = resource_ca, parent = parent, vcard = row[0]) @@ -383,7 +378,7 @@ if copy_csv_data: WHERE roa_request_handle = %s """, (self_handle,)) for roa_request_id, asn in cur.fetchall(): - roa_request = rpki.irdb.ROARequest.objects.get_or_create(identity = identity, asn = asn)[0] + roa_request = rpki.irdb.ROARequest.objects.get_or_create(issuer = resource_ca, asn = asn)[0] cur.execute(""" SELECT prefix, prefixlen, max_prefixlen, version FROM roa_request_prefix WHERE roa_request_id = %s @@ -404,7 +399,7 @@ if copy_csv_data: """, (self_handle,)) for row in cur.fetchall(): rpki.irdb.GhostbusterRequest.objects.get_or_create( - identity = identity, + issuer = resource_ca, parent = None, vcard = row[0]) |