[Freeipa-devel] [Design Review Request] V4/Automatic_Certificate_Request_Generation

Ben Lipton blipton at redhat.com
Mon Aug 8 20:23:28 UTC 2016


On 07/25/2016 07:45 AM, Jan Cholasta wrote:
> On 25.7.2016 13:11, Alexander Bokovoy wrote:
>> On Mon, 25 Jul 2016, Jan Cholasta wrote:
>>> On 20.7.2016 16:05, Ben Lipton wrote:
>>>> Hi,
>>>>
>>>> Thanks very much for the feedback! Some responses below; I hope you'll
>>>> let me know what you think of my reasoning.
>>>>
>>>>
>>>> On 07/20/2016 04:20 AM, Jan Cholasta wrote:
>>>>> Hi,
>>>>>
>>>>> On 17.6.2016 00:06, Ben Lipton wrote:
>>>>>> On 06/14/2016 08:27 AM, Ben Lipton wrote:
>>>>>>> Hello all,
>>>>>>>
>>>>>>> I have written up a design proposal for making certificate requests
>>>>>>> easier to generate when using alternate certificate profiles:
>>>>>>> http://www.freeipa.org/page/V4/Automatic_Certificate_Request_Generation. 
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> The use case for this is described in
>>>>>>> https://fedorahosted.org/freeipa/ticket/4899. I will be working on
>>>>>>> implementing this design over the next couple of months. If you 
>>>>>>> have
>>>>>>> the time and interest, please take a look and share any comments or
>>>>>>> concerns that you have.
>>>>>>>
>>>>>>> Thanks!
>>>>>>>
>>>>>>> Ben
>>>>>>>
>>>>>> Just a quick update to say that I've created a new document that
>>>>>> covers
>>>>>> the proposed schema additions in a more descriptive way (with
>>>>>> diagrams!)
>>>>>> I'm very new to developing with LDAP, so some more experienced 
>>>>>> eyes on
>>>>>> the proposal would be very helpful, even if you don't have time to
>>>>>> absorb the full design. Please take a look at
>>>>>> http://www.freeipa.org/page/V4/Automatic_Certificate_Request_Generation/Schema 
>>>>>>
>>>>>>
>>>>>>
>>>>>> if you have a chance.
>>>>>
>>>>> I finally had a chance to take a look at this, here are some 
>>>>> comments:
>>>>>
>>>>> 1) I don't like how transformation rules are tied to a particular
>>>>> helper and have to be duplicated for each of them. They should be
>>>>> generic and work with any helper, as helpers are just an
>>>>> implementation detail and their resulting data is the same.
>>>>>
>>>>> In fact, I think I would prefer if the CSR was generated using
>>>>> python-cryptography's CertificateSigningRequestBuilder [1] rather 
>>>>> than
>>>>> openssl or certutil or any other command line tool.
>>>>>
>>>> There are lots of tools that users might want to use to manage their
>>>> private keys, so I don't know if we can assume that whatever 
>>>> library we
>>>> prefer will actually be able to access the private key to sign a CSR,
>>>> which is why I thought it would be useful to support more than one.
>>>
>>> python-cryptography has the notion of backends, which allow it to
>>> support multiple crypto implementations. Upstream it currently
>>> supports only OpenSSL [2], but some work has been done on PKCS#11
>>> backend [3], which provides support for HSMs and soft-tokens (like NSS
>>> databases).
>>>
>>> Alternatively, for NSS databases (and other "simple" cases), you can
>>> generate the private key with python-cryptography using the default
>>> backend, export it to a file and import the file to the target
>>> database, so you don't actually need the PKCS#11 backend for them.
>>>
>>> So, the only thing that's currently lacking is HSM support, but given
>>> that we don't support HSMs in IPA nor in certmonger, I don't think
>>> it's an issue for now.
>>>
>>>> The
>>>> purpose of the mapping rule is to tie together the transformation 
>>>> rules
>>>> that produce the same data into an object that's
>>>> implementation-agnostic, so that profiles referencing those rules are
>>>> automatically compatible with all the helper options.
>>>
>>> They are implementation-agnostic, as long as you consider `openssl`
>>> and `certutil` the only implementations :-) But I don't think this
>>> solution scales well to other possible implementations.
>>>
>>> Anyway, my main grudge is that the transformation rules shouldn't
>>> really be stored on and processed by the server. The server should
>>> know the *what* (mapping rules), but not the *how* (transformation
>>> rules). The *how* is an implementation detail and does not change in
>>> time, so there's no benefit in handling it on the server. It should be
>>> handled exclusively on the client, which I believe would also make the
>>> whole thing more robust (it would not be possible for a bug on the
>>> server to break all the clients).
>> This is a good point. However, for the scope of Ben's project can we
>> limit it by openssl and certutil support? Otherwise Ben wouldn't be able
>> to complete the project in time.
>
> I'm fine with that, but I don't think it's up to me :-)
>
>>
>>>> This is turning out to be a common (and, I think, reasonable) reaction
>>>> to the proposal. It is rather complex, and I worry that it will be
>>>> difficult to configure. On the other hand, there is some hidden
>>>> complexity to enabling a simpler config format, as well. One of the
>>>> goals of the project as it was presented to me was to allow the 
>>>> creation
>>>> of profiles that add certificate extensions *that FreeIPA doesn't yet
>>>> know about*. With the current proposal, one only has to add a rule
>>>> generating text that the helper will understand.
>>>
>>> ... which will be possible only as long as the helper understands the
>>> extension. Which it might not, thus the current proposal works only
>>> for *some* extensions that FreeIPA doesn't yet support.
>> We can go ad infinitum here but with any helper implementation, be it
>> python-cryptography or anything else, you will need to have a support
>> there as well.
>
> My point was that the current proposal is not any better than my 
> proposal in this regard, as neither of them allows one to use an 
> arbitrary extension.
>
>> The idea with unknown extensions was to allow mapping
>> their acceptance to a specific relationship between IPA objects
>> (optionally) and an input from the CSR. A simplest example would be an
>> identity rule that would copy an ASN.1 encoded content from the CSR to
>> the certificate.
>>
>> That's on the mapping side, not on the CSR generation side, but it would
>> go similarly for the CSR if you would be able to enter unknown but
>> otherwise correct ASN.1 stream. There is no difference at which helper
>> type we are talking about because all of them support inserting ASN.1
>> content.
>>
>>>> With your suggestion,
>>>> if there's a mapping between "san_directoryname" and the corresponding
>>>> API calls or configuration lines, we need some way for users to 
>>>> augment
>>>> that mapping without changing the code. If there's no mapping, and 
>>>> it's
>>>> just done with text processing, we need enough in the config format to
>>>> be able to generate fairly complex structures:
>>>>
>>>> builder = builder.subject_name(x509.Name(u'CN=user,O=EXAMPLE.COM'))
>>>> builder =
>>>> builder.add_extension(x509.SubjectAlternativeName([x509.RFC822Name(u'user at example.com'), 
>>>>
>>>>
>>>> x509.DirectoryName(x509.Name(u'CN=user,O=EXAMPLE.COM'))]), False)
>>>>
>>>> and we need to do it without it being equivalent to calling eval() on
>>>> the config attributes. I'm not sure how to achieve this (is it safe to
>>>> call getattr(x509, extensiontype)(value) where extensiontype and value
>>>> are user-specified?) and it definitely would have to be tied to a
>>>> particular library/tool.
>>>
>>> As I pointed out above, this needs to be figured out for the generic
>>> case for both the current proposal and my suggestion.
I have a proof of concept[1] for using openssl-based rules to add a 
subject alt name extension without using openssl's knowledge of that 
extension. It's not extremely pretty, and it took some trial and error, 
but no code changes. So, I think this actually is a difference between 
the two proposals.

Next we have the easy case, extensions that we as FreeIPA developers 
know are important and build support for. For these, the two proposals 
work equivalently well, but yours is simpler to configure because the 
knowledge of how to make a san_rfc822name is built into the library 
instead of being stored on the server as a set of rules.

Finally, we have the case of extensions that are known to the helper, 
but not to FreeIPA. In the existing proposal, new rules can be written 
to support these extensions under a particular helper. Further, those 
rules can be used by reference in many profiles, reducing duplication of 
effort/data/errors.

As I understand it, the main objections in this thread are that 
transformation rules are implementation (i.e. helper) specific data 
stored in the IPA server, and that the system has several levels of 
schema when it could just embed rules in the profile. But without 
helper-specific rules, administrators could not take advantage of the 
additional extensions supported by the helper they are using. And 
without the separation of profiles from mapping rules in the schema, 
rules would need to be copy+pasted among profiles, and grouping rules 
with the same effect under different helpers would be much uglier. We 
can and should discuss whether these are the right tradeoffs, but this 
is where those decisions came from.

>>>
>>> OTOH, I think we could use GSER encoding of the extension value:
>>>
>>>    { rfc822Name:"user at example.com",
>>> directoryName:rdnSequence:"CN=user,O=EXAMPLE.COM" }
>> GSER is not really used widely and does not have standardized encoding
>> rules beyond its own definition. If you want to allow transformation
>> rules in GSER that mention existing content in IPA objects, you would
>> need to deal with templating anyway. At this point it becomes irrelevant
>> what you are templating, though.
>
> True, but the goal here is not to avoid templating, but rather to 
> avoid implementation-specific bits on the server, and GSER is the only 
> thing that is textual, implementation-neutral and, as a bonus, 
> standardized.
>
As I said elsewhere, we could use GSER as a textual output format 
instead of openssl or certutil, but it still needs its own "helper" to 
build the CSR, and unlike the other options, it seems like we might need 
to implement that helper. I'm not sure it's fair to call it 
implementation-neutral if no implementation exists yet :) But, with 
sufficient time to do so, I would agree that building GSER support into 
python-cryptography or some other library could be an elegant way to 
abstract away the helper utilities. I think even in this environment the 
schema/syntax simplification you proposed would be problematic, as some 
of the reasons discussed above would still hold.

[1]
[root at vm-058-019 freeipa]# ipa certtransformationrule-show GenericSAN 
GenericSANOpenssl
   Certificate Transformation Rule ID: GenericSANOpenssl
   String defining the transformation: {% set extension = true 
%}2.5.29.17=ASN1:SEQUENCE:{% call openssl.section() %}{{ 
datarules|join(n) }}{% endcall %}
   Name of CSR generation helper: openssl
[root at vm-058-019 freeipa]# ipa certtransformationrule-show GenericDNS 
GenericDNSOpenssl
   Certificate Transformation Rule ID: GenericDNSOpenssl
   String defining the transformation: dns=IMPLICIT:2,IA5STRING:{{ 
ipa.datafield(subject.krbprincipalname.0|safe_attr("hostname")) }}
   Name of CSR generation helper: openssl




More information about the Freeipa-devel mailing list