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

Jan Cholasta jcholast at redhat.com
Tue Nov 8 06:54:15 UTC 2016


On 3.11.2016 00:18, Ben Lipton wrote:
> On 10/20/2016 03:52 PM, Ben Lipton wrote:
>> On 10/17/2016 02:16 AM, Jan Cholasta wrote:
>>> On 13.10.2016 17:23, Ben Lipton wrote:
>>>> Thank you, this was a really helpful clarification of your point.
>>>> Comments below. Once again, I'm sorry I missed the email for so long.
>>>>
>>>> Ben
>>>>
>>>> On 09/05/2016 06:52 AM, Jan Cholasta wrote:
>>>>> On 27.8.2016 22:40, Ben Lipton wrote:
>>>>>> On 08/25/2016 04:11 PM, Rob Crittenden wrote:
>>>>>>> Ben Lipton wrote:
>>>>>>>> On 08/23/2016 03:54 AM, Jan Cholasta wrote:
>>>>>>>>> On 8.8.2016 22:23, Ben Lipton wrote:
>>>>>>>>>> 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.
>>>>>>>>>
>>>>>>>>> With the obvious catch being that it works only with OpenSSL,
>>>>>>>>> which
>>>>>>>>> might not work for everyone, e.g. when using HSMs or
>>>>>>>>> SmartCards, due
>>>>>>>>> to a limited PKCS#11 support in OpenSSL.
>>>>>>>>
>>>>>>>> Very true. Even certutil's equivalent feature (--extGeneric)
>>>>>>>> doesn't
>>>>>>>> seem like it would work very well in this context, as you are
>>>>>>>> supposed
>>>>>>>> to pass in an already-encoded extension, so text-based templating
>>>>>>>> wouldn't be able to do much.
>>>>>>>
>>>>>>> Yeah, I struggled with this myself. I ended up writing a pyasn1
>>>>>>> script
>>>>>>> to generate the extension I needed, wrote that to a file, and passed
>>>>>>> it to certutil using:
>>>>>>>
>>>>>>> --extGeneric 2.5.29.17:not-critical:/path/to/msupn.der
>>>>>>>
>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> 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.
>>>>>>>>>
>>>>>>>>> There is *no* advantage in forcing the user to choose between
>>>>>>>>> helpers
>>>>>>>>> which differ only in the set of limitations on the CSR they are
>>>>>>>>> able
>>>>>>>>> to produce. The user should specify a) where the private key is
>>>>>>>>> located and b) what profile to use, and that's it, it should just
>>>>>>>>> work.
>>>>>>>> Ok, this is a good point about usability. The user creating the CSR
>>>>>>>> shouldn't have to care about helpers, and I agree that the
>>>>>>>> current way
>>>>>>>> they are exposed is clunky. I do think that an administrator
>>>>>>>> creating
>>>>>>>> custom rules might want to take advantage of a helper, so they
>>>>>>>> wouldn't
>>>>>>>> need to understand the ASN.1 representation of their chosen
>>>>>>>> certificate
>>>>>>>> extension. Of course, the desired extension might not be
>>>>>>>> supported by
>>>>>>>> the helper either. Since I don't know what specific extensions
>>>>>>>> people
>>>>>>>> will want to use this for, I don't know how to balance the better
>>>>>>>> administrator experience of adding extensions via a helper with the
>>>>>>>> limited extension support.
>>>>>>>>
>>>>>>>> The original reason we arrived at the concept of "helpers" was to
>>>>>>>> support different ways of getting at private keys, but perhaps this
>>>>>>>> should not be the concern of the CSR data generator. In your
>>>>>>>> opinion,
>>>>>>>> would it be sufficient to support just one key format (PKCS#12?
>>>>>>>> PEM?)
>>>>>>>> and let the user deal with putting those keys into whatever
>>>>>>>> formats/databases they need? If that's ok, maybe we can stop having
>>>>>>>> *multiple* helpers, but if we want to replace helpers entirely I'm
>>>>>>>> still
>>>>>>>> not certain what to replace them with.
>>>>>>>
>>>>>>> I'd just add an option to specify the output format, e.g PEM, NSS,
>>>>>>> Java keystore, PKCS#12, whatever. You can probably get away with the
>>>>>>> first two for starters. Different output format is going to mean
>>>>>>> different options but that is probably not a big deal.
>>>>>>
>>>>>> My point was that if we want to get rid of all the helpers but
>>>>>> one, or
>>>>>> replace helpers with something else entirely like somehow templating
>>>>>> ASN1 structures directly, it will get harder to support all those
>>>>>> formats (or even both of the first two). For example, if we drop
>>>>>> certutil as a helper, how will we sign CSRs with keys stored in NSS
>>>>>> databases?
>>>>>
>>>>> 1. get the public part of the key from the NSS database
>>>>> 2. construct a CertificationRequestInfo [1] from the template and the
>>>>> public key
>>>>> 3. sign the CertificationRequestInfo with NSS using the private key to
>>>>> get a CSR
>>>>>
>>>>> This is purely client side, will work with any crypto library (just
>>>>> substitute NSS for something else) and, if done right, using very
>>>>> little code.
>>>>
>>>> Ok, I like this. If an encoded CertificationRequestInfo is something we
>>>> can expect to be compatible with any reasonable library (it sounds like
>>>> it should be) then the library can be used client-side to do the
>>>> key-storage-specific parts. I'm going to try writing this data ->
>>>> encoded CertificationRequestInfo -> CSR flow to make sure it works as
>>>> well as it sounds. If it does, it will also be useful for the code I'm
>>>> working on right now to connect certmonger with the current version of
>>>> the CSR autogeneration tool.
>>>
>>> Note that this will most probably require calling C functions. You
>>> might want to look into python-cffi.
>
> For now I just went ahead and implemented it in C, for simplicity. So
> far it only does the data + SubjectPublicKeyInfo ->
> CertificationRequestInfo conversion (data in the openssl config file
> format), but I'm convinced that both openssl and NSS should be able to
> sign this to turn it into a CSR. I'm also pretty sure you were right
> that calling C functions is required - none of the python libraries seem
> to have bindings for the functions that manipulate these objects. You
> can see the prototype here:
> https://github.com/LiptonB/freeipa-prototypes/blob/master/build_requestinfo.c

Nice, glad to hear it works :-)

>
>>>
>>>>>
>>>>>>>
>>>>>>> Remember that the private key will be at rest for some period of
>>>>>>> time
>>>>>>> while the CSR is being approved. The key needs to be protected at
>>>>>>> that
>>>>>>> time.
>>>>>>>
>>>>>>> rob
>>>>>>>
>>>>>>>>>
>>>>>>>>>> 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 :)
>>>>>>>>>
>>>>>>>>> Right. Like I said, using GSER was just a quick idea off the top
>>>>>>>>> of my
>>>>>>>>> head. I would actually rather use some sort of data structure
>>>>>>>>> templating rather than textual templating on top of any kind of
>>>>>>>>> textual representation of said data structures. I don't know if
>>>>>>>>> there
>>>>>>>>> is such a thing, though.
>>>>>>>>
>>>>>>>> This sounds interesting, can you give an example of what this might
>>>>>>>> look
>>>>>>>> like?
>>>>>
>>>>> It would be something like XSLT, but for ASN.1 rather than XML.
>>>>>
>>>>>>>>
>>>>>>>> I learned that there's also an XML encoding for ASN.1, XER, but
>>>>>>>> that's
>>>>>>>> still a textual representation and we'd have to insert the data
>>>>>>>> textually.
>>>>>
>>>>> Well, yes and no. While it's true that it's still a textual
>>>>> representation, what really makes a difference is that for XML, there
>>>>> is a templating mechanism which understands the structure of the data
>>>>> (XLST, as mentioned above).
>>>>>
>>>>> Unforutantely, XER has the same shortcoming as GSER: to be able to
>>>>> convert it to DER, you need to know the ASN.1 definition of the data
>>>>> structure. If we used XER+XSLT, we would also have to provide means of
>>>>> adding custom ASN.1 definitions and run them through ASN.1 compiler to
>>>>> convert between XER and DER.
>>>>
>>>> This is a little disappointing, but it makes sense. I don't think I
>>>> realized that we'll need to compile the ASN.1 data definitions for any
>>>> extensions we want to use in a cert. That limitation didn't come up
>>>> when
>>>> we were only talking about extensions that were supported by the helper
>>>> utility. But providing the ASN.1 spec for unusual extensions an admin
>>>> wants to use in their certs is probably a reasonable expectation.
>>>
>>> Yes, that's what I think as well. It could be a simple IPA object
>>> with name, description, extension OID and the ASN.1 definition.
>>>
>>>>>
>>>>>>>> It doesn't seem to be supported by any python libraries,
>>>>>>>> either, but it does look like it's supported by the asn1 compiler
>>>>>>>> in the
>>>>>>>> IPA source distribution.I could imagine an implementation that
>>>>>>>> builds
>>>>>>>> an XML representation of the CSR via python templating, then
>>>>>>>> makes a
>>>>>>>> signed CSR out of it in C. I'm a little concerned about it
>>>>>>>> because it
>>>>>>>> would have to implement the whole CSR structure from scratch,
>>>>>>>> but is
>>>>>>>> this a prototype that you'd be interested in seeing?
>>>>>
>>>>> I can imagine something like this might work:
>>>>>
>>>>> 1. (client) generate a key pair
>>>>> 2. (client) get SubjectPublicKeyInfo [2] for the public key
>>>>> 3. (client) encode the SubjectPublicKeyInfo as XER using asn1c and
>>>>> python-cffi in API mode [3]
>>>>> 4. (client) call server to construct CertificationRequestInfo for
>>>>> specified subject from a specified template and the
>>>>> SubjectPublicKeyInfo
>>>>> 5. (server) get the subject's LDAP entry
>>>>> 6. (server) create a XML document which contains the subject's LDAP
>>>>> attributes and the SubjectPublicKeyInfo
>>>>> 7. (server) use XSLT to transform the XML document to
>>>>> CertificationRequestInfo using the specified template
>>>>> 8. (server) return the CertificationRequestInfo to the client
>>>>> 9. (client) convert the CertificationRequestInfo from XER to DER using
>>>>> asn1c and python-cffi in API mode
>>>>> 10. (client) sign the CertificationRequestInfo using the private key
>>>>> to get a CSR
>>>>>
>>>>> It would be better if the XER-DER conversion was done on the server,
>>>>> but I don't think that compiling and running code on the fly on the
>>>>> server is a particularly good idea. Apparently there is a ASN.1
>>>>> compiler available for PyASN1 [4], maybe that could be used instead,
>>>>> but we would have to write a XER codec for PyASN1 ourselves (which
>>>>> shouldn't be too hard IMO).
>>>>
>>>> Yeah, running programs compiled from arbitrary ASN.1 seems like a risk.
>>>> Maybe a little better because the ASN.1 is provided by an
>>>> administrator,
>>>> but we'd still be depending a lot on the security of the generated
>>>> code.
>>>> On the other hand, if we compile on the client, the CSR generation
>>>> feature is limited to platforms where asn1c can be installed. I wish I
>>>> could think of a way to do the compilation once when the profile is
>>>> created, but run it on the client. That seems like asking for
>>>> compatibility problems, though...
>>>
>>> It seems you missed the most important thing in the above paragraph
>>> :-) - that is asn1ate, the PyASN1-based compiler. The nice thing
>>> about it is that it compiles the ASN.1 definition into a PyASN1 type
>>> object, which means you can compile the definition and use it to
>>> (un)parse data in the same Python program. If we used it, we could
>>> JIT-compile the ASN.1 definitions on the server, without the security
>>> risk of executing native code and without the compatibility issues of
>>> compilation on the client.
>>
>> What do you see as the risks of compiling native code with asn1c and
>> executing it that are not present when generating python code with
>> asn1ate and loading it? I would think that, native or not, we're
>> depending on the ASN.1 compiler to generate secure code from any ASN.1
>> definition the admin might give it. Even a parser like libtasn1 that
>> interprets the structure on the fly rather than generating executable
>> code could do something dangerous when given poorly-constructed input.
>> I don't mean to create a false equivalence, but are the interpreted
>> options really safer than the native code?

I suppose asn1ate is not really safer than asn1c, as either of them may 
allow you to inject and execute arbitrary code (doesn't matter if it's C 
or Python), but I think it would be much harder with libtasn1, as it 
would require overcoming buffer overflow and/or SELinux execmem protection.

>>>
>>> I did a little research since my last email, andt doesn't seem to
>>> have there is also another library which allows you to compile and
>>> use ASN.1 definitions on the fly - libtasn1 [5]. Compared to asn1ate,
>>> it seems to be pretty stable (asn1ate is currently in alpha) and is
>>> written in C, so it makes it possible to use the
>>> administrator-defined extensions outside of IPA (specifically, it
>>> could be useful for certificate matching and mapping [6] in SSSD).
>>
>> Good find. That seems quite useful for being able to interact with
>> ASN.1 defined on the fly. I wonder how hard it would be to connect it
>> to pyasn1 to get more flexible ASN.1 decoding within python. Still
>> doesn't help with XER encoding/decoding, but I suppose that's a SMOP :)
>>>
>>>>
>>>>>
>>>>>>>>
>>>>>> On further investigation, it turns out the version of
>>>>>> python-cryptography in F24 includes a feature allowing arbitrary
>>>>>> extensions to be added by adding an UnrecognizedExtension to the
>>>>>> CertificateSigningRequestBuilder. This makes me feel somewhat better
>>>>>> both about python-cryptography as a tool for this task and about the
>>>>>> solution I just proposed. But I still don't have a clear idea that
>>>>>> answers 1) how to make templates that we can turn into encoded
>>>>>> extensions, and 2) how to deal with all the desired key formats.
>>>>>
>>>>> I hope the above clarifies these a little bit.
>>>>>
>>>>> [1] <https://tools.ietf.org/html/rfc2986#section-4.1>
>>>>> [2] <https://tools.ietf.org/html/rfc5280#section-4.1.2.7>
>>>>> [3]
>>>>> <https://cffi.readthedocs.io/en/latest/overview.html#abi-versus-api>
>>>>> [4] <https://github.com/kimgr/asn1ate>
>>>
>>> [5] <https://www.gnu.org/software/libtasn1/>
>>> [6]
>>> <https://www.redhat.com/archives/freeipa-devel/2016-October/msg00090.html>
>>>
>>>
>>
>


-- 
Jan Cholasta




More information about the Freeipa-devel mailing list