One other thing to consider. Endi suggested that it might be nice to have the UUID generated by the database. One way to do this would be make use of the 389's DNA plugin. As we do not expect too many of these subCAs to be created, this might work well. Using DNA would ensure that all replicas would generate different IDs, and would prevent us having to make a database query to confirm that an ID has no longer been used. On the other hand, this might be harder to set up than simply using java.util.UUID, and may require configuration changes on the DS. For the first iteration, to unblock me so that I can start writing clients and testing, we can use something simple. In a following iteration, we can look into DNA. In fact, you can hide these details in a UUID Generator interface which we can switch out later. Ade On Thu, 2015-08-27 at 10:22 -0400, Ade Lee wrote:
On Thu, 2015-08-27 at 17:22 +1000, Fraser Tweedale wrote:
On Wed, Aug 26, 2015 at 11:09:24AM -0400, Ade Lee wrote:
Some more comments to clarify my concerns on the use of hierarchical urls as the identifier for subcas.
This is the "usual" way (ie. for example OpenStack) REST interfaces are defined:
POST /subcas -- creates a subca and returns the reference /subcas/{uuid}
POST /subcas/ -- POST includes "parent_ref"=http://../subcas/{uuid}" ; returns a subca that has the relevant parent
Full URL reference mandatory here? Preferable? Much-of-a -muchness? Would a plain UUID suffice?
If URL is the way to go here, is it necessary to ensure that the host:port refers to "this" server, or can we just ignore the front matter and go straight to looking up the UUID?
I used full URL reference here because of my experience with OpenStack, where systems can be federated across multiple domains. Using URLs for all references is de rigueur there. I do not expect us to be federated in the same way, and we tend to use plain ids everywhere in the API now. Lets use a plain ID.
GET /subcas -- list all subcas
GET /subcas/{uuid} - get details on subca.
GET /subcas/{uuid}/subcas -- list subcas for subca {uuid}
An alternate formulation could also be:
POST /subcas/{uuid}/subcas -- creates subca with subca {uuid} as parent.
I don't like this as much because its a little less standard. The resulting resource would be /subcas/{uuid2} rather than /subcas/{uuid}/subcas/{uuid2}
Lets not use the above alternative formulation. It is as suggested non -standard and therefore less intuitive.
Now, I hate uuids. I mean whats not to love about "2a549393-0710 -444b -8aa5-84cf0f85ea79" ? It just rolls off the tongue.
Everyone hates uuids but thats actually an advantage, rather than a weakness in that no one possibly would want to change the URL.
Great wisdom!
Handles on the other hand - are subject to all kinds of bike shedding. Do I use something like "ca1", "ca2"? Thats no better than a UUID in terms of semantic content. How about org references? "foo_it_dept", "bar_domain"? Uh oh, what if I decide later I didn't like my handle? What if there is an org rename? Or a reorg? Remember, certs can potentially live a long time.
And what if I'm really perverse and use the handle "subcas" -- aargh! now I've broken one of the possible paths above. Or I might end up breaking a path we'll add in future.
No - the only way to keep this straight is to have the resource identifier be something unique that no one will want to change -- like /subcas/{uuid} - and have some kind of alias system for that subca that can be changed at will.
That mapping could be kept in IPA or Barbican database for instance, rather that in dogtag itself.
Yep. Unless you need it for feel strongly otherwise, we can avoid implementing the alias indirection in initial feature. Certainly it is not needed for IPA use case.
Agreed. Aliases can come later (if ever).
We can also do what we did for secrets and allow the user to define a "client nickname" as part of the subca record. This is a field that can later be searched for or changed.
As for hierachical-ness, flatter is easier to understand and maintain.
Fair enough. I will implement the scheme proposed above. Thank you for your input! Hope to have a new patchset tomorrow or early next week.
Excellent. Also, while we want to keep the hierarchy flat, we do want to keep track of which CA/subCA is the parent CA in the CA record. This should probably be the plain ID of the parent CA. On the other hand, we want to return this to the client as a fully formed URL. Its the HATEOAS thing to do.
Looking forward to the patches.
Ade
Ade
On Wed, 2015-08-26 at 02:09 -0400, Ade Lee wrote:
Some more thoughts.
First off, there are things that should be included with the CAData for each subsystem.
1. CA signing cert (or more likely a reference to the ca cert) 2. pkcs7 chain (again this is something that could/should likely be a reference) 3. status - ie. enabled/disabled. 4. Description -- user defined description.
For the motivation for (30 status, we do need to consider what we want do when someone wants to delete or decommission a subCA. If we want to keep the subCA record -- and we almost certainly need to -- we should probably add some kind of field to enable/disable.
Second, we definitely need code to be able to issue a cert using the subcas from the REST interface. This will allow us to actually test that the subCA is working.
Third, if we do stick with the current REST API, I think we should consider using something like:
POST /subcas/ca1/ca2 {"id": "ca3"} to generate a subca /ca1/ca2/ca3
Fourth, though, we need to consider carefully whether or not it makes sense to identify a subca through 1) an identifier that contains slashes 2) an identifier that is defined by the user instead of the server. We have currently no controls as to what names are chosen, and no clear rationale for what should be chosen.
Much as I dislike uuids, there is a good reasons openstack uses them everywhere.
We can discuss over IRC, but I can see many issues here.
Ade
On Tue, 2015-08-25 at 14:40 -0400, Ade Lee wrote:
Some initial comments and questions. Will have more after playing with it and testing. Looks pretty good so far.
1. what is org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true and why is it needed?
2. In CAService.java: issueX509Cert() - if ca is null, this throws an ECAException - which, if I understand the code correctly, ends up being some kind of BaseException. So, if someone requests a cert and provides a bogus caref, it will be reported as a server error instead of a installation error?
3. CertificateAuthority.java -- subCAHier --> rename to subCAHierarchy.
-- In the constructor, it would be useful to have example inputs in the method documentation so that we can see what data is expected to be in each of the fields. Its hard to review/understand/maintain otherwise.
-- you have extracted initCetDatabase() and initCRLDB(), also extract the replica repo initialization code into initReplicaRepo() or similar.
-- loadSubCAs - could use some description in method comments about the structure we expect to construct here. An example config would help understanding.
-- createSubCA -- returns ECAException() in many different cases ie. if the CA exists, if the parent does not exist, if there is an error in CA creation. This makes it difficult to separate out the things that are likely client request issues vs. server issues. More likely, we want different exceptions that can be caught by the caller and handled appropriately. -- what about uniqueness checks for the issuer DN?
4. SubCAResource.java -- path should be subcas ? not subca .. -- acls needed of course
5. CAEnrollProfile.java --> could not reach CA -- that ends up being a ProfileException