what can go in root.crt ?

Started by Chapman Flackalmost 6 years ago33 messageshackers
Jump to latest
#1Chapman Flack
chap@anastigmatix.net

Certificates I get at $work come four layers deep:

Self-signed CA cert from "WE ISSUE TO EVERYBODY.COM"

Intermediate from "WE ISSUE TO LOTS OF FOLKS.COM"

Intermediate from "WE ISSUE TO ORGS LIKE YOURS.COM"

End-entity cert for my server.

Until today, we had the topmost, self-signed cert in root.crt
and stuff worked. But I needed to renew, and it seems that
recently WE ISSUE TO ORGS LIKE YOURS has chosen somebody else
to sign their certs, so I have new certs for the issuers above them,
so I have to go deal with root.crt.

And that got me thinking: do I really want WE ISSUE TO EVERYBODY
to be what I'm calling trusted in root.crt?

I considered just putting the end-entity cert for my server in there,
but it's only good for a couple years, and I'd rather not have to
fuss with editing and distributing root.crt that often.

As a compromise, I tried putting the WE ISSUE TO ORGS LIKE YOURS cert there.
I think I'm willing to accept that much risk. But psql says:

psql: SSL error: certificate verify failed

I would be happy if it gave a little more detail. Is it failing
verification because the cert I put in root.crt is *not* self-signed,
and I didn't include the two issuers above it?

Does that mean it also would fail if I directly put the server's
end-entity cert there?

Would I have to put all three of WE ISSUE TO ORGS LIKE YOURS,
WE ISSUE TO LOTS, and WE ISSUE TO EVERYBODY in the root.crt file
in order for verification to succeed?

If I did that, would the effect be any different from simply putting
WE ISSUE TO EVERYBODY there, as before? Would it then happily accept
a cert with a chain that ended at WE ISSUE TO EVERYBODY via some other
path? Is there a way I can accomplish trusting only certs issued by
WE ISSUE TO ORGS LIKE YOURS?

I never noticed how thin the docs or verify-failure messages were
on this topic until just now. Are there any options, openssl
environment variables, or the like, to get it to be a little more
forthcoming about what it expects?

Regards,
-Chap

#2Chapman Flack
chap@anastigmatix.net
In reply to: Chapman Flack (#1)
Re: what can go in root.crt ?

On 05/25/20 15:15, Chapman Flack wrote:

Does that mean it also would fail if I directly put the server's
end-entity cert there?

Would I have to put all three of WE ISSUE TO ORGS LIKE YOURS,
WE ISSUE TO LOTS, and WE ISSUE TO EVERYBODY in the root.crt file
in order for verification to succeed?

If I did that, would the effect be any different from simply putting
WE ISSUE TO EVERYBODY there, as before? Would it then happily accept
a cert with a chain that ended at WE ISSUE TO EVERYBODY via some other
path? Is there a way I can accomplish trusting only certs issued by
WE ISSUE TO ORGS LIKE YOURS?

The client library is the PG 10 one that comes with Ubuntu 18.04
in case it matters.

I think I have just verified that I can't make it work by putting
the end entity cert there either. It is back working again with only
the WE ISSUE TO EVERYBODY cert there, but if there is a workable way
to narrow that grant of trust a teensy little bit, I would be happy
to do that.

Regards,
-Chap

#3Bruce Momjian
bruce@momjian.us
In reply to: Chapman Flack (#2)
Re: what can go in root.crt ?

On Mon, May 25, 2020 at 03:32:52PM -0400, Chapman Flack wrote:

On 05/25/20 15:15, Chapman Flack wrote:

Does that mean it also would fail if I directly put the server's
end-entity cert there?

Would I have to put all three of WE ISSUE TO ORGS LIKE YOURS,
WE ISSUE TO LOTS, and WE ISSUE TO EVERYBODY in the root.crt file
in order for verification to succeed?

If I did that, would the effect be any different from simply putting
WE ISSUE TO EVERYBODY there, as before? Would it then happily accept
a cert with a chain that ended at WE ISSUE TO EVERYBODY via some other
path? Is there a way I can accomplish trusting only certs issued by
WE ISSUE TO ORGS LIKE YOURS?

The client library is the PG 10 one that comes with Ubuntu 18.04
in case it matters.

I think I have just verified that I can't make it work by putting
the end entity cert there either. It is back working again with only
the WE ISSUE TO EVERYBODY cert there, but if there is a workable way
to narrow that grant of trust a teensy little bit, I would be happy
to do that.

Did you review the PG documentation about intermediate certificates?

https://www.postgresql.org/docs/13/ssl-tcp.html#SSL-CERTIFICATE-CREATION

Is there a specific question you have? I don't know how to improve the
error reporting.

--
Bruce Momjian <bruce@momjian.us> https://momjian.us
EnterpriseDB https://enterprisedb.com

+ As you are, so once was I.  As I am, so you will be. +
+                      Ancient Roman grave inscription +
#4Chapman Flack
chap@anastigmatix.net
In reply to: Bruce Momjian (#3)
Re: what can go in root.crt ?

On 05/25/20 22:03, Bruce Momjian wrote:

Did you review the PG documentation about intermediate certificates?

https://www.postgresql.org/docs/13/ssl-tcp.html#SSL-CERTIFICATE-CREATION

AFAICT, there isn't much in that section to apply to my question.

Is there a specific question you have?

I'm pretty sure there is. :) Let me try to clarify it.

The doc section you linked has an example showing how to be my own CA,
and generate a chain of certs including a self-signed one to serve as
the root. It suggests putting that self-signed one in root.crt on the
client.

That means the client will happily connect to any server wearing a
certificate signed by that root (or by intermediates that can be followed
up to that root). For the example that's fine, because that root signer
is me, and there aren't a lot of other certs around that chain back to it.

At $work we have Ways Of Doing Things. Generating our own self-signed certs
generally isn't among those. If I want a certificate so I can stand up
a server, I generate a key and a CSR, I send the CSR to our Bureau of
Making Certificates Happen, and they send me back a signed cert with
a chain of external authorities, ending in the self-signed certificate
of a prominent commercial root CA.

Sure, I can put that self-signed root cert into root.crt on the client,
and my client will happily connect to my server.

But in this case the world is teeming with other certificates and even
other whole sub-CAs that chain back to that prominent root issuer.
Granted, you might have to be a bit enterprising to find a sub-CA out
there that will sign a cert for you with the name of my server in it,
but if you can, my client will follow the chain back to that same root,
and therefore trust it.

So I would like to be able to do one of two things:

1. I would like to put my server's end-entity (leaf) certificate
in the root.crt file, and have my client only accept a server
with that exact cert.

Or,

2. I would like to put one of the lower intermediates from the chain
into the root.crt file, to at least limit my client to trusting
only certs signed by that particular sub-CA.

What seems to be happening (for the libpq and libssl versions in 18.04
anyway) is that the certificate that I put in root.crt is found, but
because it isn't a literal "root", as in signer-of-itself, the library
declares a verification failure because it hasn't been able to continue
climbing the chain to find a "root" cert.

Whereas I would like it to say "but I don't have to do that, because
I have already verified as far as this certificate that the administrator
deliberately placed in this file here to tell me to trust it."

In Java, for example, the analogous file is called trustStore, which
may be a better name. You populate the trustStore with certificates you
consider trusted. They can be root certs, intermediate certs, or flat-out
leaf certs of individual servers. Whenever Java is verifying a connection,
as soon as its chain-following brings it to a cert that you placed in
the trustStore, it stops and says "yes, I trust this, because you have
told me to."

I have also encountered web browsers that work in both of these ways.
The last time I was standing up a temporary web service to test something,
I did make a self-signed cert and then use it to sign a leaf cert for
the service. I was testing with Chrome and Firefox and they both have
spiffy UIs for managing a list of trusted certs, but one of them (I have
forgotten which) allowed me to simply load the leaf cert that I wanted
to trust, while the other insisted I give it the self-signed root that
I had signed the leaf cert with.

I think the former behavior, which is like Java's, is strictly more useful.

What puzzled me today, and why I began this thread, is that I hadn't
(and still haven't) found a clear discussion in the doc of these two
approaches and which one libpq is intended to supply. I know that my
attempts to use root.crt like a trustStore have so far been met with
failure, but between the terse error message and the sparse doc, it is
hard to know whether that's a "you can't do that, dummy!" or a "you
just haven't guessed the right way yet."

If there is a way to get a trustStore-like behavior and have the client
trust an intermediate or leaf cert that I explicitly tell it to, but I
just haven't pronounced the magic words right, this email may be read
as "oh good, how do I do it?"

If the current implementation really is stuck accepting only self-signed
certs in that file and therefore can't offer trustStore-like behavior,
this email may be read as "it could be made more useful by changing that."

And in either case, there seems to be room in the docs for some
discussion of the difference between those two models and which one
libpq is meant to offer.

I would not be unwilling to try my hand at such a doc patch one day,
but for now I'm still hoping to learn the answers myself.

Regards,
-Chap

#5Laurenz Albe
laurenz.albe@cybertec.at
In reply to: Chapman Flack (#1)
Re: what can go in root.crt ?

On Mon, 2020-05-25 at 15:15 -0400, Chapman Flack wrote:

Certificates I get at $work come four layers deep:

Self-signed CA cert from "WE ISSUE TO EVERYBODY.COM"

Intermediate from "WE ISSUE TO LOTS OF FOLKS.COM"

Intermediate from "WE ISSUE TO ORGS LIKE YOURS.COM"

End-entity cert for my server.

And that got me thinking: do I really want WE ISSUE TO EVERYBODY
to be what I'm calling trusted in root.crt?

I don't know if there is a way to get this to work, but the
fundamental problem seems that you have got the system wrong.

If you don't trust WE ISSUE TO EVERYBODY, then you shouldn't use
it as a certification authority.

Yours,
Laurenz Albe

#6Bruce Momjian
bruce@momjian.us
In reply to: Laurenz Albe (#5)
Re: what can go in root.crt ?

On Tue, May 26, 2020 at 05:22:13AM +0200, Laurenz Albe wrote:

On Mon, 2020-05-25 at 15:15 -0400, Chapman Flack wrote:

Certificates I get at $work come four layers deep:

Self-signed CA cert from "WE ISSUE TO EVERYBODY.COM"

Intermediate from "WE ISSUE TO LOTS OF FOLKS.COM"

Intermediate from "WE ISSUE TO ORGS LIKE YOURS.COM"

End-entity cert for my server.

And that got me thinking: do I really want WE ISSUE TO EVERYBODY
to be what I'm calling trusted in root.crt?

I don't know if there is a way to get this to work, but the
fundamental problem seems that you have got the system wrong.

If you don't trust WE ISSUE TO EVERYBODY, then you shouldn't use
it as a certification authority.

It is true that WE ISSUE TO EVERYBODY can create a new intermediate with
the same intemediate name anytime they want.

--
Bruce Momjian <bruce@momjian.us> https://momjian.us
EnterpriseDB https://enterprisedb.com

+ As you are, so once was I.  As I am, so you will be. +
+                      Ancient Roman grave inscription +
#7Chapman Flack
chap@anastigmatix.net
In reply to: Laurenz Albe (#5)
Re: what can go in root.crt ?

On 05/25/20 23:22, Laurenz Albe wrote:

I don't know if there is a way to get this to work, but the
fundamental problem seems that you have got the system wrong.

If you don't trust WE ISSUE TO EVERYBODY, then you shouldn't use
it as a certification authority.

That's a reasonable viewpoint.

I've worked in organizations from smallish to largish, and in the
largish ones, sometimes there are Ways Of Doing Things, that were
laid down by Other People.

There the challenge becomes how to piece together practices that
maximize my comfort level, within the ways of doing things that
come down from others.

If the libpq root.crt file can be made to work similarly to a
Java trustStore, that expands the possible solution space.

Regards,
-Chap

#8Isaac Morland
isaac.morland@gmail.com
In reply to: Chapman Flack (#7)
Re: what can go in root.crt ?

What about the SSH model? In the Postgres context, this would basically be
a table containing authorized certificates for each user. Upon receiving a
connection attempt, look up the user and the presented certificate and see
if it is one of the authorized ones. If so, do the usual verification that
the client really does have the corresponding private key and if so,
authenticate the connection.

This is way simpler than messing around with certificate authorities.
Please, if anybody can give a coherent explanation why this isn't the first
certificate authentication model supported, I would love to understand.

On Mon, 25 May 2020 at 23:43, Chapman Flack <chap@anastigmatix.net> wrote:

Show quoted text

On 05/25/20 23:22, Laurenz Albe wrote:

I don't know if there is a way to get this to work, but the
fundamental problem seems that you have got the system wrong.

If you don't trust WE ISSUE TO EVERYBODY, then you shouldn't use
it as a certification authority.

That's a reasonable viewpoint.

I've worked in organizations from smallish to largish, and in the
largish ones, sometimes there are Ways Of Doing Things, that were
laid down by Other People.

There the challenge becomes how to piece together practices that
maximize my comfort level, within the ways of doing things that
come down from others.

If the libpq root.crt file can be made to work similarly to a
Java trustStore, that expands the possible solution space.

Regards,
-Chap

#9Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Chapman Flack (#7)
Re: what can go in root.crt ?

On 2020-May-25, Chapman Flack wrote:

If the libpq root.crt file can be made to work similarly to a
Java trustStore, that expands the possible solution space.

If I understand you correctly, you want a file in which you drop any of
these intermediate CA's cert in, causing the server to trust a cert
emitted by that CA -- regardless of that CA being actually root.

--
�lvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

#10Isaac Morland
isaac.morland@gmail.com
In reply to: Alvaro Herrera (#9)
Re: what can go in root.crt ?

On Tue, 26 May 2020 at 00:08, Alvaro Herrera <alvherre@2ndquadrant.com>
wrote:

On 2020-May-25, Chapman Flack wrote:

If the libpq root.crt file can be made to work similarly to a
Java trustStore, that expands the possible solution space.

If I understand you correctly, you want a file in which you drop any of
these intermediate CA's cert in, causing the server to trust a cert
emitted by that CA -- regardless of that CA being actually root.

I think he wants only certificates signed by the specific intermediate
certificate to be trusted.

I just had an idea: would it work to create a self-signed root certificate,
put it in root.crt, and then use it to sign the intermediate certificate?

You can't use other people's certificates to sign your certificates, and
it's not usual to sign other people's intermediate certificates, but as far
as I can tell there is no reason you can't.

#11Chapman Flack
chap@anastigmatix.net
In reply to: Alvaro Herrera (#9)
Re: what can go in root.crt ?

On 05/26/20 00:07, Alvaro Herrera wrote:

If the libpq root.crt file can be made to work similarly to a
Java trustStore, that expands the possible solution space.

If I understand you correctly, you want a file in which you drop any of
these intermediate CA's cert in, causing the server to trust a cert
emitted by that CA -- regardless of that CA being actually root.

Right: an intermediate cert, or a self-signed root cert, or even the
end-entity (leaf) cert for a specific machine. You name it, if I put
in in the trust store, and a connection verification starts with or leads
to a cert that I put there, success.

Regards,
-Chap

#12Chapman Flack
chap@anastigmatix.net
In reply to: Isaac Morland (#8)
Re: what can go in root.crt ?

On 05/26/20 00:07, Isaac Morland wrote:

What about the SSH model? In the Postgres context, this would basically be
a table containing authorized certificates for each user. Upon receiving a
connection attempt, look up the user and the presented certificate and see
if it is one of the authorized ones. If so, do the usual verification that
the client really does have the corresponding private key and if so,
authenticate the connection.

I like the SSH model, but just in case it wasn't clear, I wasn't thinking
about client-cert authentication here, just about conventional verification
by the client of a certificate for the server.

By the same token, there's no reason not to ask the same questions about
the other direction.

Regards,
-Chap

#13Craig Ringer
craig@2ndquadrant.com
In reply to: Chapman Flack (#7)
Re: what can go in root.crt ?

On Tue, 26 May 2020 at 11:43, Chapman Flack <chap@anastigmatix.net> wrote:

On 05/25/20 23:22, Laurenz Albe wrote:

I don't know if there is a way to get this to work, but the
fundamental problem seems that you have got the system wrong.

If you don't trust WE ISSUE TO EVERYBODY, then you shouldn't use
it as a certification authority.

Right. In fact you must not, because WE ISSUE TO EVERYBODY can issue a new
certificate in the name of WE ISSUE TO ORGS LIKE YOURS.COM - right down to
matching backdated signing date and fingerprint.

Then give it to WE ARE THE BAD GUYS.COM.

If you don't trust the root, you don't trust any of the intermediate
branches.

The main reason to put intermediate certificates in the root.crt is that it
allows PostgreSQL to supply the whole certificate chain to a client during
the TLS handshake. That frees the clients from needing to have local copies
of the intermediate certificates; they only have to know about WE ISSUE TO
EVERYBODY.

If you wanted to require that your certs are signed by WE ISSUE TO ORGS
LIKE YOURS.COM, you must configure your CLIENTS with a restricted root of
trust that accepts only the intermediate certificate of WE ISSUE TO ORGS
LIKE YOURS.COM . Assuming the client will accept it; not all clients allow
you to configure "certificates I trust to sign peers" separately to
"certificates that sign my trusted roots". Because really, in security
terms that's nonsensical.

--
Craig Ringer http://www.2ndQuadrant.com/
2ndQuadrant - PostgreSQL Solutions for the Enterprise

#14Chapman Flack
chap@anastigmatix.net
In reply to: Craig Ringer (#13)
Re: what can go in root.crt ?

On 05/26/20 02:05, Craig Ringer wrote:

The main reason to put intermediate certificates in the root.crt is that it
allows PostgreSQL to supply the whole certificate chain to a client during

Hold on a sec; you're not talking about what I'm talking about, yet.

Yes, you have make the chain available to the server to serve out with
its own cert so clients can verify. root.crt isn't where you put that,
though. You put that in server.crt (or wherever the ssl_cert_file GUC
points).

That frees the clients from needing to have local copies
of the intermediate certificates; they only have to know about WE ISSUE TO
EVERYBODY.

Bingo. Put WE ISSUE TO EVERYBODY in the root.crt (client-side, libpq) file,
and the clients happily connect to the server. It is easy and convenient.

But if WE STEAL YOUR STUFF gets their certs signed by WE SIGN ANYTHING
FOR A PRICE and their CA is WE'RE SOMETIMES LESS ATTENTIVE THAN YOU HOPE
and /their/ CA is WE ISSUE TO EVERYBODY, then the clients would just as
happily connect to a server of the same name run by WE STEAL YOUR STUFF.

Which brings us around to what I was talking about.

If you wanted to require that your certs are signed by WE ISSUE TO ORGS
LIKE YOURS.COM, you must configure your CLIENTS with a restricted root of
trust that accepts only the intermediate certificate of WE ISSUE TO ORGS
LIKE YOURS.COM .

Precisely. And the place to configure that restricted root of trust would
have to be ~/.postgresql/root.crt on the client, and the question is,
does that work?

Assuming the client will accept it; not all clients allow
you to configure "certificates I trust to sign peers" separately to
"certificates that sign my trusted roots". Because really, in security
terms that's nonsensical.

And that's the key question: there are clients that grok that and clients
that don't; so now, libpq is which kind of client?

Could you expand on your "sign _peers_" notion, and on what exactly
you are calling nonsensical?

Each of those intermediate CAs really is a CA; the WE ISSUE TO ORGS
LIKE yours cert does contain these extensions:

X509v3 extensions:
...
X509v3 Key Usage: critical
Digital Signature, Certificate Sign, CRL Sign
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:0
...

My server's end-entity certificate does not have the Certificate Sign,
CRL Sign or CA:TRUE bits, or a URL to a revocation-checking service.
An end entity and a CA are not 'peers' in those respects.

Regards,
-Chap

#15Andrew Dunstan
andrew@dunslane.net
In reply to: Chapman Flack (#2)
Re: what can go in root.crt ?

On 5/25/20 3:32 PM, Chapman Flack wrote:

On 05/25/20 15:15, Chapman Flack wrote:

Does that mean it also would fail if I directly put the server's
end-entity cert there?

Would I have to put all three of WE ISSUE TO ORGS LIKE YOURS,
WE ISSUE TO LOTS, and WE ISSUE TO EVERYBODY in the root.crt file
in order for verification to succeed?

If I did that, would the effect be any different from simply putting
WE ISSUE TO EVERYBODY there, as before? Would it then happily accept
a cert with a chain that ended at WE ISSUE TO EVERYBODY via some other
path? Is there a way I can accomplish trusting only certs issued by
WE ISSUE TO ORGS LIKE YOURS?

The client library is the PG 10 one that comes with Ubuntu 18.04
in case it matters.

I think I have just verified that I can't make it work by putting
the end entity cert there either. It is back working again with only
the WE ISSUE TO EVERYBODY cert there, but if there is a workable way
to narrow that grant of trust a teensy little bit, I would be happy
to do that.

The trouble is I think you have it the wrong way round. It makes sense
to give less trust to a non-root CA than to one of its up-chain
authorities, e.g. only trust it for certain domains, or for a lesser
period of time. But it doesn't seem to make much sense to trust the
up-chain CA less, since it is what you should base your trust of the
lower CA on.

cheers

andrew

--
Andrew Dunstan https://www.2ndQuadrant.com
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

#16Chapman Flack
chap@anastigmatix.net
In reply to: Andrew Dunstan (#15)
Re: what can go in root.crt ?

On 05/26/20 09:35, Andrew Dunstan wrote:

The trouble is I think you have it the wrong way round. It makes sense
to give less trust to a non-root CA than to one of its up-chain
authorities, e.g. only trust it for certain domains, or for a lesser
period of time. But it doesn't seem to make much sense to trust the
up-chain CA less, since it is what you should base your trust of the
lower CA on.

I wonder if there might be different meanings of 'trust' in play here
complicating the conversation.

At $work, when I make a certificate request and send it off to our
own in-house bureau of making certificates happen, what you might
expect is that they would be running the first level of CA right
in house (and IIRC that was the case in my early years here).
So I would get back some chain like this:

WE ARE A PROMINENT GLOBAL ISSUER FOUND IN WEB BROWSER TRUST STORES
WE ISSUE TO LOTS OF FOLKS
WE ISSUE TO ORGS LIKE YOURS
WE ARE YOUR ORG
my server cert

In that picture, the question of whether I give more or less trust to
PROMINENT GLOBAL ISSUER because they have larger market cap and their
name in the news, or to WE ARE YOUR ORG because they are my org, seems
to turn on different understandings of trust. There might be a lot of
reasons in general to trust PROMINENT GLOBAL in the sense of putting
their cert in widely distributed web browser trust stores. But there
are excellent reasons to trust WE ARE YOUR ORG as authoritative on
what's a server for my org.

Now in these later days when there is no longer an in-house CA at the
bottom of this chain, the situation's not as clear-cut. WE ISSUE TO ORGS
LIKE YOURS isn't quite authoritative on what's a server for my org.
But there are inked signatures on paper between their honcho and my org's
honcho that don't exist between my org and PROMINENT GLOBAL. And you would
have to work harder to get a spoof cert for one of my servers signed by
them. You would have to talk /them/ into it.

If I have PROMINENT GLOBAL in there, you just have to make offers to
their umpty sub-CAs and their umpty-squared sub-sub-CAs and find just
one that will make a deal.

to give less trust to a non-root CA than to one of its up-chain
authorities, e.g. only trust it for certain domains, or for a lesser

That's certainly appropriate, and I'd be delighted if the root.crt file
supported syntax like this:

*.myorg.org: WE ARE YOUR ORG.crt
*: PROMINENT GLOBAL ISSUER.crt { show exfiltration/HIPAA/FERPA banner }

Doing the same thing (or some of it) in certificate style, you would
want WE ARE YOUR ORG.crt to be signed with a Name Constraints extension
limiting it to be a signer for .myorg.org certificates. That is indeed
a thing. The history in [1]https://security.stackexchange.com/questions/31376/can-i-restrict-a-certification-authority-to-signing-certain-domains-only shows it was at first of limited value
because client libraries didn't all grok it, or would accept certificates
without Subject Alt Name extensions and verify by CN instead, without the
constraint. But I have noticed more recently that mainstream web browsers,
anyway, are no longer tolerant of certs without SAN, and that seems to be
part of a road map to giving the Name Constraints more teeth.

Regards,
-Chap

[1]: https://security.stackexchange.com/questions/31376/can-i-restrict-a-certification-authority-to-signing-certain-domains-only
https://security.stackexchange.com/questions/31376/can-i-restrict-a-certification-authority-to-signing-certain-domains-only

#17Bruce Momjian
bruce@momjian.us
In reply to: Chapman Flack (#16)
Re: what can go in root.crt ?

On Tue, May 26, 2020 at 10:13:56AM -0400, Chapman Flack wrote:

At $work, when I make a certificate request and send it off to our
own in-house bureau of making certificates happen, what you might
expect is that they would be running the first level of CA right
in house (and IIRC that was the case in my early years here).
So I would get back some chain like this:

WE ARE A PROMINENT GLOBAL ISSUER FOUND IN WEB BROWSER TRUST STORES
WE ISSUE TO LOTS OF FOLKS
WE ISSUE TO ORGS LIKE YOURS
WE ARE YOUR ORG
my server cert

In that picture, the question of whether I give more or less trust to
PROMINENT GLOBAL ISSUER because they have larger market cap and their
name in the news, or to WE ARE YOUR ORG because they are my org, seems
to turn on different understandings of trust. There might be a lot of
reasons in general to trust PROMINENT GLOBAL in the sense of putting
their cert in widely distributed web browser trust stores. But there
are excellent reasons to trust WE ARE YOUR ORG as authoritative on
what's a server for my org.

I think it gets down to an issue I blogged about in 2017:

https://momjian.us/main/blogs/pgblog/2017.html#January_9_2017

The use of public certificate authorities doesn't make sense for most
databases because it allows third parties to create trusted
certificates. Their only reasonable use is if you wish to allow public
certificate authorities to independently issue certificates that you
wish to trust. This is necessary for browsers because they often connect
to unaffiliated websites where trust must be established by a third
party. (Browsers include a list of public certificate authorities who
can issue website certificates it trusts.)

The server certificate should be issued by a certificate authority root
outside of your organization only if you want people outside of your
organization to trust your server certificate, but you are then asking
for the client to only trust an intermediate inside your organization.
The big question is why bother having the server certificate chain to a
root certificat you don't trust when you have no intention of having
clients outside of your organization trust the server certificate.
Postgres could be made to handle such cases, but is is really a valid
configuration we should support?

--
Bruce Momjian <bruce@momjian.us> https://momjian.us
EnterpriseDB https://enterprisedb.com

The usefulness of a cup is in its emptiness, Bruce Lee

#18Ants Aasma
ants.aasma@cybertec.at
In reply to: Bruce Momjian (#17)
Re: what can go in root.crt ?

On Tue, 2 Jun 2020 at 20:14, Bruce Momjian <bruce@momjian.us> wrote:

The server certificate should be issued by a certificate authority root
outside of your organization only if you want people outside of your
organization to trust your server certificate, but you are then asking
for the client to only trust an intermediate inside your organization.
The big question is why bother having the server certificate chain to a
root certificat you don't trust when you have no intention of having
clients outside of your organization trust the server certificate.
Postgres could be made to handle such cases, but is is really a valid
configuration we should support?

I think the "why" the org cert is not root was already made clear, that is
the copmany policy. I don't think postgres should take a stance whether the
certificate designated as the root of trust is self-signed or claims to get
its power from somewhere else.

It's pretty easy to conceive of certificate management procedures that make
use of this chain to implement certificate replacement securely. For
example one might trust the global issuer to verify that a CSR is coming
from the O= value that it's claiming to come from to automate replacement
of intermediate certificates, but not trust that every other sub-CA signed
by root and their sub-sub-CA-s are completely honest and secure.

Regards,
Ants Aasma

#19Bruce Momjian
bruce@momjian.us
In reply to: Ants Aasma (#18)
Re: what can go in root.crt ?

On Wed, Jun 3, 2020 at 03:07:30PM +0300, Ants Aasma wrote:

On Tue, 2 Jun 2020 at 20:14, Bruce Momjian <bruce@momjian.us> wrote:

The server certificate should be issued by a certificate authority root
outside of your organization only if you want people outside of your
organization to trust your server certificate, but you are then asking
for the client to only trust an intermediate inside your organization.
The big question is why bother having the server certificate chain to a
root certificat you don't trust when you have no intention of having
clients outside of your organization trust the server certificate.
Postgres could be made to handle such cases, but is is really a valid
configuration we should support?

I think the "why" the org cert is not root was already made clear, that is the
copmany policy. I don't think postgres should take a stance whether the
certificate designated as the root of trust is self-signed or claims to get its
power from�somewhere else.

Uh, we sure can. We disallow many configurations that we consider
unsafe. openssl allowed a lot of things, and their flexibility make
them less secure.

--
Bruce Momjian <bruce@momjian.us> https://momjian.us
EnterpriseDB https://enterprisedb.com

The usefulness of a cup is in its emptiness, Bruce Lee

#20Chapman Flack
chap@anastigmatix.net
In reply to: Ants Aasma (#18)
Re: what can go in root.crt ?

On 06/03/20 08:07, Ants Aasma wrote:

I think the "why" the org cert is not root was already made clear, that is
the copmany policy.

Thank you, yes, that was what I had intended to convey, and you have saved
me finishing a weedsier follow-up message hoping to convey it better.

I don't think postgres should take a stance ...

whether the
certificate designated as the root of trust is self-signed or claims to get
its power from somewhere else.

On 06/03/20 16:34, Bruce Momjian wrote:

Uh, we sure can. We disallow many configurations that we consider
unsafe.

Ok, so a person in the situation described here, who is not in a position
to demand changes in an organizational policy (whether or not it seems
ill-conceived to you or even to him/her), is facing this question:

What are the "safest" things I /can/ do, under the existing constraints,
and /which of those will work in PostgreSQL/?

For example, we might agree that it is safe to trust nothing but the
end-entity cert of my server itself. I made a server, here is its cert,
here is a root.crt file for libpq containing only this exact cert, I
want libpq to connect only ever to this server with this cert and nothing
else. It's a pain because I have to roll out new root.crt files to everybody
whenever the cert changes, but it would be hard to call it unsafe.

Great! Can I do that? I think the answer is no. I haven't found it
documented, but I think libpq will fail such a connection, because
the cert it has found in root.crt is not self-signed.

Or, vary the scenario just enough that my organization, or even my
department in my organization, now has its own CA, as the first
intermediate, the issuer of the end-entity cert.

It might be entirely reasonable to put that CA cert into root.crt,
so libpq would only connect to things whose certs were issued in
my department, or at least my org. I trust the person who would be
issuing my department's certs (in all likelihood, me). I would
more-or-less trust my org to issue certs for my org.

Great! Can I do that? I think that answer is also no, for the same
reason.

My department's or org's CA cert isn't going to be self-signed, it's
going to be vouched for by a chain of more certs leading to a globally
recognized one. Why? Short answer, our org also has web sites. We like
for people's browsers to be able to see those. We have one group that
makes server certs and they follow one procedure, and the certs they make
come out the same way. That shouldn't be a problem for PostgreSQL, so it's
hard to argue they should have to use a different procedure just for my
cert.

I don't think postgres should take a stance whether the
certificate designated as the root of trust is self-signed or claims
to get its power from somewhere else.

I'm inclined to agree but I would change the wording a bit for clarity.
*Any* certificate we are going to trust gets its power from somewhere
else. Being self-signed is not an exception to that rule (if it were,
every Snake Oil, Ltd. self-signed cert generated by every student in
every network security class ever would be a root of trust).

For us to trust a cert, it must be vouched for in some way. The most
important vouching that happens, as far as libpq is concerned, is
vouching by the administrator who controls the file system where root.crt
is found and the contents of that file.

If libpq is looking at a cert and finds it in that file, I have vouched
for it. That's why it's there.

If it is self-signed, then I'm the only person vouching for it, and that's
ok.

If it is not self-signed, that just means somebody else also has vouched
for it. Maybe for the same use, maybe for some other use. In any event,
the fact that somebody else has also vouched for it does not in any way
negate that I vouched for it, by putting it there in that file I control.

It's pretty easy to conceive of certificate management procedures that make
use of this chain to implement certificate replacement securely. For
example one might trust the global issuer to verify that a CSR is coming
from the O= value that it's claiming to come from to automate replacement
of intermediate certificates, but not trust that every other sub-CA signed
by root and their sub-sub-CA-s are completely honest and secure.

That's an example of the kind of policy design I think ought to be possible,
but a first step to getting there would be to just better document what
does and doesn't work in libpq now. There seem to be some possible
configurations that aren't available, not because of principled arguments
for disallowing them, but because they fail unstated assumptions.

In an ideal world, I think libpq would be using this algorithm:

I'm looking at the server's certificate, s.
Is s unexpired and in the trust file? If so, SUCCEED.

otherwise, loop:
get issuer certificate i from s (if s is self-signed, FAIL).
does i have CA:TRUE and Certificate Sign bits? If not, FAIL.
does i's Domain Constraint allow it to sign s? If not, FAIL.
is i unexpired, or has s a Signed Certificate Timestamp made
while i was unexpired? If not, FAIL.
is i in the trust file? If so, SUCCEED.
s := i, continue.

(I left out steps like verify signature, check revocation, etc.)

What it seems to be doing, though, is just:

I'm looking at s
Follow chain all the way to a self-signed cert
is that in the file?

which seems too simplistic.

Regards,
-Chap

#21Laurenz Albe
laurenz.albe@cybertec.at
In reply to: Chapman Flack (#20)
#22Chapman Flack
chap@anastigmatix.net
In reply to: Laurenz Albe (#21)
#23Laurenz Albe
laurenz.albe@cybertec.at
In reply to: Chapman Flack (#22)
#24Chapman Flack
chap@anastigmatix.net
In reply to: Laurenz Albe (#23)
#25Andrew Dunstan
andrew@dunslane.net
In reply to: Chapman Flack (#20)
#26Chapman Flack
chap@anastigmatix.net
In reply to: Andrew Dunstan (#25)
#27Tom Lane
tgl@sss.pgh.pa.us
In reply to: Chapman Flack (#26)
#28Chapman Flack
chap@anastigmatix.net
In reply to: Tom Lane (#27)
#29Tom Lane
tgl@sss.pgh.pa.us
In reply to: Chapman Flack (#28)
#30Bruce Momjian
bruce@momjian.us
In reply to: Chapman Flack (#20)
#31Chapman Flack
chap@anastigmatix.net
In reply to: Bruce Momjian (#30)
#32Chapman Flack
chap@anastigmatix.net
In reply to: Chapman Flack (#31)
#33Bruce Momjian
bruce@momjian.us
In reply to: Chapman Flack (#31)