Re: Proposed patch for key management

2021-01-05 Thread Alastair Turner
On Mon, 4 Jan 2021 at 17:56, Bruce Momjian  wrote:
>
> On Sat, Jan  2, 2021 at 12:47:19PM +, Alastair Turner wrote:
> >
> > There is also a further validation task - probably beyond the scope of
> > the key management patch and into the encryption patch[es] territory -
> > checking that the keys supplied are the same keys in use for the data
> > currently on disk. It feels to me like this should be done at startup,
> > rather than as each file is accessed, which could make startup quite
> > slow if there are a lot of keys with narrow scope.
>
> We do that already on startup by using GCM to validate the  KEK when
> encrypting each DEK.
>
Which validates two things - that the KEK is the same one which was
used to encrypt the DEKs (instead of returning garbage plaintext when
given a garbage key), and that the DEKs have not been tampered with at
rest. What it does not check is that the DEKs are the keys used to
encrypt the data, that one has not been copied or restored independent
of the other.




Re: Proposed patch for key management

2021-01-05 Thread Alastair Turner
Hi Bruce

On Mon, 4 Jan 2021 at 18:23, Bruce Momjian  wrote:
>
> On Fri, Jan  1, 2021 at 06:26:36PM +, Alastair Turner wrote:
> > After the long intro, my question - If using a standard format,
> > managed by a library, for the internal keystore does not result in a
> > smaller or simpler patch, is there enough other value for this to be
> > worth considering? For security features, standards and building on
> > well exercised code bases do really have value, but is it enough...
>
> I know Stephen Frost looked at PKCS12 but didn't see much value in it
> since the features provided by PKCS12 didn't seem to add much for
> Postgres, and added complexity...

Yeah, OpenSSL 1.1's PKCS12 implementation doesn't offer much for
managing arbitrary secrets. Building a reasonable abstraction over the
primitives it does provide requires a non-trivial amount of code.

> ... Using GCM for key wrapping, heap/index
> files, and WAL seemed simple.

Having Postgres take on the task of wrapping the keys and deriving the
wrapping key requires less code than getting a library to do it, sure.
It also expands the functional scope of Postgres, what Postgres is
responsible for. This isn't what libraries should ideally do for
software development, but it's not uncommon and it's very fertile
ground for some of the discussion which has dogged this feature's
development.

There's a question of whether the new scope should be taken on at all.
Fabien expressed a strong opinion that it should not be earlier in the
thread. Even if you don't take an absolute view on the additional
scope, lines of code do not all create equal risk. Ensuring the
confidentiality of an encryption key is far higher stakes code than
serialising and deserialising the key which is being secured and
stored by a library or external provider. Which is why I like the idea
of having OpenSSL (and, at some point, nss) do the KDF, wrapping and
storage bit, and have been hacking on some code in that direction.

If all that Postgres is doing is the serde, that's also something
which can objectively be said to be right or wrong. Key derivation and
wrapping are only ever "strong enough for the moment" or "in line with
policy/best practice". Which brings us to flexibility.

> There is all sorts of flexibility being proposed:
>
> *  scope of keys
> *  encryption method
> *  encryption mode
> *  internal/external
>
> Some of this is related to wrapping the data keys, and some of it gets
> to the encryption of cluster files. I just don't see how anything with
> the level of flexibility being asked for could ever be reliable or
> simple to administer,...

Externalising the key wrap and its KDF (either downward to OpenSSL or
to a separate process) makes the related points of flexibility
something else's problem. OpenSSL and the like have put a lot of
effort into making these things configurable and building the APIs
(mainly PCKS11 and KMIP) for handing the functions off to dedicated
hardware. Many or most organisations requiring that sort of
integration will have those complexities budgeted in already.

>... and I don't see the security value of that
> flexibility.  I feel at a certain point, we just need to choose the best
> options and move forward.
>
> I thought this had all been debated, but people continue to show up and
> ask for it to be debated again.  At one level, these discussions are
> valuable, but at a certain point you end up re-litigate this that you
> get nothing else done.  I know some people who have given up working on
> this feature for this reason.

Apologies for covering the PCKS12 ground again, I really did look for
any on-list and wiki references to the topic.

> I am not asking we stop discussing it, but I do ask we address the
> negatives of suggestions, especially when the negatives have already
> been clearly stated.

The negatives are increasing the amount of code involved in delivering
TDE and, implicitly, pushing back the delivery of TDE. I'm not
claiming that they aren't valid. I was hoping that PCKS12 would
deliver some benefits on the code side, but a bit of investigation
showed that wasn't the case.

To offset these, I believe that taking a slightly longer route now
(and I am keen to do some of that slog) has significant benefits in
getting Postgres (or at least the core server processes) out of the
business of key derivation and wrapping. Not just the implementation
detail, but also decisions about what is "good enough" - the KDF
worries me particularly in this regard. With my presales techie hat
on, I'm very aware that everyone's good enough is slightly different,
and not just on one axis. Using library functions (let's say OpenSSL)
will provide a range of flexibility to fit these varied boundaries, at
no incremental cost beyond the library integration, and avoid any
implementation decisions becoming a lightning rod for objections to
Postgres.

Regards
Alastair




Re: Proposed patch for key management

2021-01-02 Thread Alastair Turner
Hi Fabien

On Sat, 2 Jan 2021 at 09:50, Fabien COELHO  wrote:
>
...
> ISTM that pg at the core level should (only) directly provide:
>
> (1) a per-file encryption scheme, with loadable (hook-replaceable
> functions??) to manage pages, maybe:
>
>encrypt(page_id, *key, *clear_page, *encrypted_page);
>decrypt(page_id, *key, *encrypted_page, *clear_page);
>
> What encrypt/decrypt does is beyond pg core stuff. Ok, a reasonable
> implementation should be provided, obviously, possibly in core. There may
> be some block-size issues if not full pages are encrypted, so maybe the
> interface needs to be a little more subtle.
>

There are a lot of specifics of the encryption implementation which
need to be addressed in future patches. This patch focuses on making
keys available to the encryption processes at run-time, so ...

>
> (2) offer a key management scheme interface, to manage *per-file* keys,
> possibly loadable (hook replaceable?). If all files have the same key,
> which is stored in a directory and encoded with a KEK, this is just one
> (debatable) implementation choice. For that, ISTM that what is needed at
> this level is:
>
>get_key(file_id (relative name? oid? 8 or 16 bytes something?));
>

Per-cluster keys for permanent data and WAL allow a useful level of
protection, even if it could be improved upon. It's also going to be
quicker/simpler to implement, so any API should allow for it. If
there's an arbitrary number of DEK's, using a scope label for
accessing them sounds right, so "WAL", "local_data",
"local_data/tablespaceiod" or "local_data/dboid/tableoid".

>
...
> (3) ISTM that the key management interface should be external, or at least
> it should be possible to make it external easily. I do not think that
> there is a significant performance issue because keys are needed once, and
> once loaded they are there. A simple way to do that is a separate process
> with a basic protocol on stdin/stdout to implement "get_key", which is
> basically already half implemented in the patch for retrieving the KEK.
>

If keys can have arbitrary scope, then the pg backend won't know what
to ask for. So the API becomes even simpler with no specific request
on stdin and all the relevant keys on stdout. I generally like this
approach as well, and it will be the only option for some
integrations. On the other hand, there is an advantage to having the
key retrieval piece of key management in-process - the keys are not
being passed around in plain.

There is also a further validation task - probably beyond the scope of
the key management patch and into the encryption patch[es] territory -
checking that the keys supplied are the same keys in use for the data
currently on disk. It feels to me like this should be done at startup,
rather than as each file is accessed, which could make startup quite
slow if there are a lot of keys with narrow scope.

Regards
Alastair




Re: Proposed patch for key management

2021-01-01 Thread Alastair Turner
Hi Stephen, Bruce, Fabien

On Thu, 31 Dec 2020 at 17:05, Stephen Frost  wrote:
>
> Greetings,
>
> * Bruce Momjian (br...@momjian.us) wrote:
> > On Thu, Dec 31, 2020 at 11:11:11AM +0100, Fabien COELHO wrote:
> > > > I am not sure what else I can add to this discussion.  Having something
> > > > that is completely external might be a nice option, but I don't think it
> > > > is the common use-case, and will make the most common use cases more
> > > > complex.
> > >
> > > I'm unsure about what is the "common use case". ISTM that having the
> > > postgres process holding the master key looks like a "no" for me in any 
> > > use
> > > case with actual security concern: as the database must be remotely
> > > accessible, a reasonable security assumption is that a pg account could be
> > > compromised, and the "master key" (if any, that is just one particular
> > > cryptographic design) should not be accessible in that case. The first
> > > barrier would be pg admin account.
> >
> > Let's unpack this logic, since I know others, like Alastair Turner (CC
> > added), had similar concerns.  Frankly, I feel this feature has limited
> > security usefulness, so if we don't feel it has sufficient value, let's
> > mark it as not wanted and move on.
>
> Considering the amount of requests for this, I don't feel it's at all
> reasonable to suggest that it's 'not wanted'.
>

FWIW, I think that cluster file encryption has great value, even if we
only consider its incremental value on top of disk or volume
encryption. Particularly in big IT estates where monitoring tools,
backup managers, etc have read access to a lot of mounted volumes.
Limiting the impact of these systems (or their credentials) being
compromised is definitely useful.

>
> > I think there are two basic key configurations:
> >
> > 1.  pass data encryption keys in from an external source
> > 2.  store the data encryption keys wrapped by a key encryption key (KEK)
> > passed in from an external source
>
> I agree those are two basic configurations (though they aren't the only
> possible ones).
>

If we rephrase these two in terms of what the server process does to
get a key, we could say

 1. Get the keys from another process at startup (and maybe reload) time
 2. Get the wrapped keys from a local file...
 2.a. directly and unwrap them using the server's own logic and user prompt
 2.b. via a library which manages wrapping and user prompting

With the general feeling in the mailing list discussions favouring an
approach in the #2 family, I have been looking at options around 2b. I
was hoping to provide some flexibility for users without adding
complexity to the pg code base and use some long standing,
standardised, features rather than reinventing or recoding the wheel.
It has not been a complete success, or failure.

The nearest thing to a standard for wrapped secret store files is
PKCS#12. I searched and cannot find it discussed on-list in this
context before. It is the format used for Java local keystores in
recent versions. The format is supported, up to a point, by OpenSSL,
nss and gnuTLS. OpenSSL also has command line support for many
operations on the files, including updating the wrapping password.

Content in the PKCS12 files is stored in typed "bags". The challenge
is that the OpenSSL command line tools currently support only the
content types related to TLS operations - certificates, public or
private keys, CRLs, ... and not the untyped secret bag which is
appropriate for storing AES keys. The c APIs will work with this
content but there are not as many helper functions as for other
content types.

For future information - the nss command line tools understand the
secret bags, but don't offer nearly so many options for configuration.

For building something now - the OpenSSL pkcs12 functions provide
features like tags and friendly names for keys, and configurable key
derivation from passwords, but the code to interact with the
secretBags is accumulating quickly in my prototype.

After the long intro, my question - If using a standard format,
managed by a library, for the internal keystore does not result in a
smaller or simpler patch, is there enough other value for this to be
worth considering? For security features, standards and building on
well exercised code bases do really have value, but is it enough...

Regards
Alastair




Re: Proposed patch for key managment

2020-12-22 Thread Alastair Turner
Hi Bruce

In ckey_passphrase.sh.sample

+
+echo "$PASS" | sha256sum | cut -d' ' -f1
+

Under the threat model discussed, a copy of the keyfile could be
attacked offline. So getting from passphrase to DEKs should be as
resource intensive as possible to slow down brute-force attempts.
Instead of just a SHA hash, this should be at least a PBKDF2 (PKCS#5)
operation or preferably scrypt (which is memory intensive as well as
computationally intensive). While OpenSSL provides these key
derivation options for it's encoding operations, it does not offer a
command line option for key derivation using them. What's your view on
including third party utilities like nettlepbkdf in the sample or
providing this utility as a compiled program?

In the same theme - in ossl_cipher_ctx_create and the functions using
that context should rather be using the key-wrapping variants of the
cipher. As well as lower throughput, with the resulting effects on
brute force attempts, the key wrap variants provide more robust
ciphertext output
"
KW, KWP, and TKW are each robust in the sense that each bit of output
can be expected to depend in a nontrivial fashion on each bit of
input, even when the length of the input data is greater than one
block. This property is achieved at the cost of a considerably lower
throughput rate, compared to other authenticated-encryption modes, but
the tradeoff may be appropriate for some key management applications.
For example, a robust method may be desired when the length of the
keys to be protected is greater than the block size of the underlying
block cipher, or when the value of the protected data is very high.
" - NIST SP 800-38F

and aim to manage the risk of short or predictable IVs ([1] final para
of page 1)

On Tue, 22 Dec 2020 at 15:40, Bruce Momjian  wrote:
>
> Here is an updated patch.  Are people happy with the Makefile, its
> location in the source tree, and the install directory name?  I used the
> directory name 'auth_commands' because I thought 'auth' was too easily
> misinterpreted. I put the scripts in /src/backend/utils/auth_commands.
>

What's implemented in these patches is an internal keystore, wrapped
with a key derived from a passphrase. I'd think that the scripts
directory should reflect what they interact with, so
'keystore_commands' or 'local_keystore_command' sounds more specific
and therefore better than 'auth_commands'.

Regards
Alastair

[1] https://web.cs.ucdavis.edu/~rogaway/papers/keywrap.pdf




Re: Proposed patch for key managment

2020-12-20 Thread Alastair Turner
Thanks Stephen,

On Mon, 21 Dec 2020 at 00:33, Stephen Frost  wrote:
>
> Greetings,
>
> * Alastair Turner (min...@decodable.me) wrote:
...
> >
> > What I'd like specifically is to have the option of an external
> > keyring as a first class key store, where the keys stored in the
> > external keyring are used directly to encrypt the database contents.
>
> Right- understood, but that's not what the patch does today and there
> isn't anyone who has proposed such a patch, nor explained why we
> couldn't add that capability later.
>

I'm keen to propose a patch along those lines, even if just as a
sample. Minimising the amount of code which would have to be unpicked
in that effort would be great. Particularly avoiding any changes to
data structures, since that may effectively block adding new
capabilities.

>
> >...Your description above of changes to pass keys out
> > of the command sound like they may have addressed this.
>
> The updates are intended to make it so that the KEK which wraps the
> internal keyring will be obtained directly from the cluster key command,
> pushing the transformation of a passphrase (should one be provided) into
> a proper key to the script, but otherwise allowing the result of things
> like 'openssl rand -hex 32' to be used directly as the KEK.
>

Sounds good.

>
> > Regarding the on-disk format, separate storage of the key HMACs and
> > the wrapped keys sounds like a requirement for implementing a fully
> > external keyring or doing key wrapping externally via an OpenSSL or
> > nss tls pluggable engine. I'm still looking through the code.
>
> This seems a bit confusing as the question at hand is the on-disk format
> of the internal keyring, not anything to do with an external keyring
> (which we wouldn't have any storage of and so I don't understand how it
> makes sense to even discuss the idea of storage for the external
> keyring..?).
>

A requirement for validating the keys, no matter which keyring they
came from, was mentioned along the way. Since there would be no point
in validating keys from the internal ring twice, storing the
validation data (HMACs in the current design) separately from the
internal keyring's keys seems like it would avoid changing the data
structures for the internal keyring when adding an external option.

>
> Again, we will need the ability to perform the encryption using a simple
> passphrase provided by the user, while using multiple randomly generated
> data encryption keys, and that's what the latest set of patches are
> geared towards.  I'm generally in support of adding additional
> capabilities in this area in the future, but I don't think we need to
> bog down the current effort by demanding that be implemented today.
>

I'm really not looking to bog down the current effort.

I'll have a go at adding another keyring and/or abstracting the key
wrap and see how well a true peer to the passphrase approach fits in.

Regards
Alastair




Re: Proposed patch for key managment

2020-12-20 Thread Alastair Turner
Thanks, Bruce

On Sat, 19 Dec 2020 at 16:58, Bruce Momjian  wrote:
>
...
>
> To enable the direct injection of keys into the server, we would need a
> new command for this, since trying to make the passphrase command do
> this will lead to unnecessary complexity.  The passphrase command should
> do one thing, and you can't have it changing its behavior based on
> parameters, since the parameters are for the script to process, not to
> change behavior of the server.
>
> If we wanted to do this, we would need a new command, and one of the
> parameters would be %k or something that would identify the key number
> we want to retrieve from the KMS.  Stephen pointed out that we could
> still validate that key;  the key would not be stored wrapped in the
> file system, but we could store an HMAC in the file system, and use that
> for validation.
>

I think that this is where we have ended up talking at cross-purposes.
My idea (after some refining based on Stephen's feedback) is that
there should be only this new command (the cluster key command) and
that the program for unwrapping stored keys should be called this way.
As could a program to contact an HSM, etc. This moves the generating
and wrapping functionality out of the core Postgres processes, making
it far easier to add alternatives. I see this approach was discussed
on the email thread you linked to, but I can't see where or how a
conclusion was reached about it...

>
> On other interesting approach would be to allow the server to call out
> for a KMS when it needs to generate the initial data keys that are
> wrapped by the passphrase;  this is in contrast to calling the KMS
> everytime it needs the data keys.
>
...
> ...The data keys are generated using this random value
> code:
>
> 
> https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/port/pg_strong_random.c;hb=HEAD
>
> so someone would have to explain why generating this remotely in a KMS
> is superior, not just based on company policy.
>

The pg_strong_random() function uses OpesnSSL's RAND_bytes() where
available. With appropriate configuration of an OpenSSL engine
supplying an alternative RAND, this could be handed off to a TRNG.

This is an example of the other option for providing flexibility to
support specific key generation, wrapping, ... requirements - handing
the operations off to a library like OpenSSL or nss tls which, in
turn, can use pluggable providers for these functions. FWIW, the
proprietary DBMSs use a pluggable engine approach to meet requirements
in this category.

>
> We should create code for the general use-case, which is currently
> passphrase-wrapped system-generated data keys, and then get feedback on
> what else we need.  However, I should point out that the community is
> somewhat immune to the "my company needs this" kind of argument without
> logic to back it up, though sometimes I think this entire feature is in
> that category. ...

Yeah. Security in general, and crypto in particular, are often
"because someone told me to" requirements.

>
> My final point is that we can find ways to do what you are suggesting as
> an addition to what we are adding now.  What we need is clear
> justification of why these additional features are needed.  Requiring
> the use of a true random number generator is a valid argument, but we
> need to figure out, once this is implemented, who really wants that, and
> how to implement it cleanly.
>

Clean interfaces would be either "above" the database calling out to
commands in user-land or "below" the database in the abstractions
which OpenSSL, nss tls and friends provide. Since the conclusion seems
already to have been reached that the keyring should be inside the
core process and only the passphrase should pop out above, I'll review
the patch in this vein and see if I can suggest any routes to carving
out more manageable subsets of the patch.

"...once this is implemented..." changes become a lot more difficult.
Particularly when the changes would affect what are regarded as the
database's on-disk files. Which I suspect is a contributing factor to
the level of engagement surrounding this feature.

Regards
Alastair




Re: Proposed patch for key managment

2020-12-19 Thread Alastair Turner
Hi Bruce

On Sat, 19 Dec 2020 at 02:38, Bruce Momjian  wrote:
>
> I am not going be as kind.  Our workflow is:
>
> Desirability -> Design -> Implement -> Test -> Review -> Commit
> https://wiki.postgresql.org/wiki/Todo#Development_Process
>
> I have already asked about the first item, and received a reply talking
> about the design --- that is not helpful.  I only have so much patience
> for the "I want my secret decoder ring to glow in the dark" type of
> feature additions to this already complex feature.  Unless we stay on
> Desirability, I will not be replying.  If you can't answer the
> Desirability question, well, talking about items farther right on the
> list is not very helpful.
>
> Now, I will say that your question about how a KMS will use this got me
> thinking about how to test this, and that got me to implement the AWS
> Secret Manager script, so that we definitely helpful.  My point is that
> I don't think it is helpful to get into long discussions unless the
> Desirability is clearly answered.  This is not just related to this
> thread --- this kind of jump-over-Desirability has happened a lot in
> relation to this feature, so I thought it would be good to clearly state
> it now.
>

Sorry, I have waved Desirability through under the headings of ease of
adoption or not raising barriers to adoption, without detailing what
barriers I see or how to avoid them. I also realise that "don't scare
the users" is so open-ended so as to be actively unhelpful and very
quickly starts to sound like "I want my secret decoder ring to glow
pink, or blue, or green when anyone asks". Given the complexity of the
feature and pixels spilled in discussing it, I understand that it gets
frustrating. That said, I believe there is an important case to be
made here.

In summary, I believe that forcing an approach for key generation and
wrapping onto users of Cluster File Encryption limits the Desirability
of the feature.

Cluster File Encryption for Postgres would be Desirable to many users
I meet if, and only if, the generation and handling of keys fits with
their corporate policies. Therefore, giving a user the option to pass
an encryption key to Postgres for CFE is Desirable. I realise that the
option for feeding the keys in directly is an additional feature, and
that it has a user experience impact if a passphrase is used. It is,
however, a feature which opens up near-infinite flexibility. To
stretch the analogy, it is the clip for attaching coloured or opaque
coverings to the glowy bit on the secret decoder ring.

The generation of keys and the wrapping of keys are contentious issues
and are frequently addressed/specified in corporate security policies,
standards and technical papers (NIST 800-38F is often mentioned in
product docs). There are, for instance, policies in the wild which
require that keys for long term use are generated from the output of a
True Random Number Generator - the practical implication being that
the key used to encrypt data at rest should be created by an HSM. When
and why to use symmetric or asymmetric cyphers for key wrapping is
another item which different organisations have different policies on
- the hardware and cloud service vendors all offer both options, even
if they recommend one and make it easier to use.

Thanks

Alastair




Re: Proposed patch for key managment

2020-12-19 Thread Alastair Turner
Hi Stephen

On Fri, 18 Dec 2020 at 21:36, Stephen Frost  wrote:
>
> Greetings Alastair,
>
> * Alastair Turner (min...@decodable.me) wrote:
> > On Wed, 16 Dec 2020 at 22:43, Stephen Frost  wrote:
...
> > passphrase key wrapper, the secret store and the cloud/HW KMS.
> >
> > Since the examples expand the purpose of cluster_passphrase_command,
> > let's call it cluster_key_challenge_command in the examples.
>
> These ideas don't seem too bad but I'd think we'd pass which key we want
> on the command-line using a %i or something like that, rather than using
> stdin, unless there's some reason that would be an issue..?  Certainly
> the CLI utilities I've seen tend to expect the name of the secret that
> you're asking for to be passed on the command line.

Agreed. I was working on the assumption that the calling process
(initdb or pg_ctl) would have access to the challenge material and be
passing it to the utility, so putting it in a command line would allow
it to leak. If the utility is accessing the challenge material
directly, then just an indicator of which key to work with would be a
lot simpler, true.

>
> > Starting with the passphrase key wrapper, since it's what's in place now.
> >
> >  - cluster_key_challenge_command = 'password_key_wrapper %q'
>
> I do tend to like this idea of having what
> cluster_key_challenge_command, or whatever we call it, expects is an
> actual key and have the command that is run be a separate command that
> takes the passphrase and runs the KDF (key derivation function) on it,
> when a passphrase is what the user wishes to use.
>
> That generally makes more sense to me than having the key derivation
> effort built into the backend which I have a hard time seeing any
> particular reason for, as long we're already calling out to some
> external utility of some kind to get the key.
>
...
>
> With the thought of trying to keep it a reasonably simple interface, I
> had a thought along these lines:
>
> - Separate command that runs the KDF, this is simple enough as it's
>   really just a hash, and it returns the key on stdout.
> - initdb time option that says if we're going to have PG manage the
>   sub-keys, or not.
> - cluster_key_command defined as "a command that is passed the ID of
>   the key, or keys, required for the cluster to start"
>
> initdb --pg-subkeys
>   - Calls cluster_key_command once with "$PG_SYSTEM_ID-main" or similar
> and expects the main key to be provided on stdout.  Everything else
> is then more-or-less as is today: PG generates DEK sub-keys for data
> and WAL and then encrypts them with the main key and stores them.
>
> As long as the enveloped keys file exists on the filesystem, when PG
> starts, it'll call the cluster_key_command and will expect the 'main'
> key to be provided and it'll then decrypt and verify the DEK sub-keys,
> very similar to today.
>
> In this scenario, cluster_key_command might be set to call a command
> which accepts a passphrase and runs a KDF on it, or it might be set to
> call out to an external vaulting system or to a Yubikey, etc.
>
> initdb --no-pg-subkeys
>   - Calls cluster_key_command for each of the sub-keys that "pg-subkeys"
> would normally generate itself, passing "$PG_SYSTEM_ID-keyid" for
> each (eg: $PG_SYSTEM_ID-data, $PG_SYSTEM_ID-wal), and getting back
> the keys on stdout to use.
>
> When PG starts, it sees that the enveloped keys file doesn't exist and
> does the same as initdb did- calls cluster_key_command multiple times to
> get the keys which are needed.  We'd want to make sure to have a way
> early on that checks that the data DEK provided actually decrypts the
> cluster, and bail out otherwise, before actually writing any data with
> that key.  I'll note though that this approach would actually allow you
> to change the WAL key, if you wanted to, though, which could certainly
> be nice (naturally there would be various caveats about doing so and
> that replicas would have to also be switched to the new key, etc, but
> that all seems reasonably solvable). Having a stand-alone utility that
> could do that for the --pg-subkeys case would be useful too (and just
> generally decrypt it for viewing/backup/replacement/etc).
>
> Down the line this might even allow us to do an online re-keying, at
> least once the challenges around enabling online data checksums are
> sorted out, but I don't think that's something to worry about today.
> Still, it seems like this potentially provides a pretty clean interface
> for that to happen eventually.
>

Changing the WAL key independently of the local storage key is the big
operational advantage I see of managing the two keys separately. It
lay

Re: Proposed patch for key managment

2020-12-16 Thread Alastair Turner
On Wed, 16 Dec 2020 at 22:43, Stephen Frost  wrote:
>
> Greetings,
...
>
> If I'm following, you're suggesting something like:
>
> cluster_passphrase_command = 'aws get %q'
>
> and then '%q' gets replaced with "Please provide the WAL DEK: ", or
> something like that?  Prompting the user for each key?  Not sure how
> well that's work if want to automate everything though.
>
> If you have specific ideas, it'd really be helpful to give examples of
> what you're thinking.

I can think of three specific ideas off the top of my head: the
passphrase key wrapper, the secret store and the cloud/HW KMS.

Since the examples expand the purpose of cluster_passphrase_command,
let's call it cluster_key_challenge_command in the examples.

Starting with the passphrase key wrapper, since it's what's in place now.

 - cluster_key_challenge_command = 'password_key_wrapper %q'
 - Supplied on stdin to the process is the wrapped DEK (either a
combined key for db files and WAL or one for each, on separate calls)
 - %q is "Please provide WAL key wrapper password" or just "...provide
key wrapper password"
 - Returned on stdout is the unwrapped DEK

For a secret store

 - cluster_key_challenge_command = 'vault_key_fetch'
 - Supplied on stdin to the process is the secret's identifier (pg_dek_xxUUIDxx)
 - Returned on stdout is the DEK, which may never have been wrapped,
depending on implementation
 - Access control to the secret store is managed through the challenge
command's own config, certs, HBA, ...

For an HSM or cloud KMS

 - cluster_key_challenge_command = 'gcp_kms_key_fetch'
 - Supplied on stdin to the process is the the wrapped DEK (individual
or combined)
 - Returned on stdout is the DEK (individual or combined)
 - Access control to the kms is managed through the challenge
command's own config, certs, HBA, ...

The secret store and HSM/KMS options may be promptless, and therefore
amenable to automation, depending on the setup of those clients.

>
...
>
> > > ...That
> > > avoids the complication of having to have an API that somehow provides
> > > more than one key, while also using the primary DEK key as-is from the
> > > key management service and the KEK never being seen on the system where
> > > PG is running.
> >
> > Other than calling out (and therefore potentially prompting) twice,
> > what do you see as the complications of having more than one key?
>
> Mainly just a concern about the API and about what happens if, say, we
> decide that we want to have another sub-key, for example.  If we're
> handling them then there's really no issue- we just add another key in,
> but if that's not happening then it's going to mean changes for
> administrators.  If there's a good justification for it, then perhaps
> that's alright, but hand waving at what the issue is doesn't really
> help.
>

Sorry, I wasn't trying to hand wave it away. For automated
interactions, like big iron HSMs or cloud KSMs, the difference between
2 operations and 10 operations to start a DB server won't matter. For
an admin/operator having to type 10 passwords or get 10 clean
thumbprint scans, it would be horrible. My underlying question was, is
that toil the only problem to be solved, or is there another reason to
get into key combination, key splitting and the related issues which
are less documented and less well understood than key wrapping.

>
...
> >
> > I'd describe what the current patch does as using YubiKey to encrypt
> > and then decrypt an intermediate secret, which is then used to
> > generate/derive a KEK, which is then used to unwrap the stored,
> > wrapped DEK.
>
> This seems like a crux of at least one concern- that the current patch
> is deriving the actual KEK from the passphrase and not just taking the
> provided value (at least, that's what it looks like from a *very* quick
> look into it), and that's the part that I was suggesting that we might
> add an option for- to indicate if the cluster passphrase command is
> actually returning a passphrase which should be used to derive a key, or
> if it's returning a key directly to be used.  That does seem to be a
> material difference to me and one which we should care about.
>

Yes. Caring about that is the reason I've been making a nuisance of myself.

> > > There's an entirely independent discussion to be had about figuring out
> > > a way to actually off-load *entirely* the encryption/decryption of data
> > > to the linux crypto system or hardware devices, but unless someone can
> > > step up and write code for those today, I'd suggest that we table that
> > > effort until after we get this initial capability of having TDE with PG
> > > doing all of the encryption/decryption.
> >
> > I'm hopeful that the work on abstracting OpenSSL, nsstls, etc is going
> > to help in this direct.
>
> Yes, I agree with that general idea but it's a 'next step' kind of
> thing, not something we need to try and bake in today.
>

Agreed.

Thanks
Alastair




Re: Proposed patch for key managment

2020-12-16 Thread Alastair Turner
On Wed, 16 Dec 2020 at 21:32, Stephen Frost  wrote:
>
> Greetings,
>
> * Alastair Turner (min...@decodable.me) wrote:
> > On Wed, 16 Dec 2020 at 00:12, Bruce Momjian  wrote:
> > > The second approach is to make a new API for what you want
> >
> > I am trying to motivate for an alternate API. Specifically, an API
> > which allows any potential adopter of Postgres and Cluster File
> > Encryption to adopt them without having to accept any particular
> > approach to key management, key derivation, wrapping, validation, etc.
> > A passphrase key-wrapper with validation will probably be very useful
> > to a lot of people, but making it mandatory and requiring twists and
> > turns to integrate with already-established security infrastructure
> > sounds like a barrier to adoption.
>
> Yeah, I mentioned this in one of the other threads where we were
> discussing KEKs and DEKs and such.  Forcing one solution for working
> with the KEK/DEK isn't really ideal.
>
> That said, maybe there's an option to have the user indicate to PG if
> they're passing in a passphrase or a DEK, ...

Some options very much like the current cluster_passphrase_command,
but that takes an input sounds to me like it would meet that
requirement. The challenge sent to the command could be just a text
prompt, or it could be the wrapped DEK. The selection of the command
would indicate what the user was expected to pass. The return would be
a DEK.

> ...but we otherwise more-or-less
> keep things as they are where the DEK that the user provides actually
> goes to encrypting the sub-keys that we use for tables vs. WAL..?  ...

The idea of subkeys sounds great, if it can merge the two potential
interactions into one and not complicate rotating the two parts
separately. But having Postgres encrypting them, leaves us open to
many of the same issues. That still feels like managing the keys, so a
corporate who have strong opinions on how that should be done will
still ask all sorts of pointy questions, complicating adoption.

> ...That
> avoids the complication of having to have an API that somehow provides
> more than one key, while also using the primary DEK key as-is from the
> key management service and the KEK never being seen on the system where
> PG is running.
>

Other than calling out (and therefore potentially prompting) twice,
what do you see as the complications of having more than one key?

> > > ...It would be
> > > similar to the cluster_passphrase_command, but it would be simple in
> > > some ways, but complex in others since we need at least two DEKs, and
> > > key rotation might be very risky since there isn't validation in the
> > > server.
> >
...
>
> I'm not quite following this- I agree that we don't want PG, or anything
> really, to see the private key that's on the Yubikey, as that wouldn't
> be good- instead, we should be able to ask for the Yubikey to decrypt
> the DEK for us and then use that, which I had thought was happening but
> it's not entirely clear from the above discussion (and, admittedly, I've
> not tried using the patch with my yubikey yet, but I do plan to...).
>
> Are we sure we're talking about the same thing here..?  That's really
> the question I'm asking myself.
>

I'd describe what the current patch does as using YubiKey to encrypt
and then decrypt an intermediate secret, which is then used to
generate/derive a KEK, which is then used to unwrap the stored,
wrapped DEK.

> There's an entirely independent discussion to be had about figuring out
> a way to actually off-load *entirely* the encryption/decryption of data
> to the linux crypto system or hardware devices, but unless someone can
> step up and write code for those today, I'd suggest that we table that
> effort until after we get this initial capability of having TDE with PG
> doing all of the encryption/decryption.

I'm hopeful that the work on abstracting OpenSSL, nsstls, etc is going
to help in this direct.

Regards

Alastair




Re: Proposed patch for key managment

2020-12-16 Thread Alastair Turner
Hi Bruce

On Wed, 16 Dec 2020 at 00:12, Bruce Momjian  wrote:
>
...
>
> The second approach is to make a new API for what you want

I am trying to motivate for an alternate API. Specifically, an API
which allows any potential adopter of Postgres and Cluster File
Encryption to adopt them without having to accept any particular
approach to key management, key derivation, wrapping, validation, etc.
A passphrase key-wrapper with validation will probably be very useful
to a lot of people, but making it mandatory and requiring twists and
turns to integrate with already-established security infrastructure
sounds like a barrier to adoption.

> ...It would be
> similar to the cluster_passphrase_command, but it would be simple in
> some ways, but complex in others since we need at least two DEKs, and
> key rotation might be very risky since there isn't validation in the
> server.
>

I guess that the risk you're talking about here is encryption with a
bogus key and bricking the data? In a world where the wrapped keys are
opaque to the application, a key would be validated through a
roundtrip: request the unwrapping of the key, encrypt a known string,
request the unwrapping again, decrypt the known string, compare. If
any of those steps fail, don't use the wrapped key provided.
Validating that the stored keys have not been fiddled/damaged is the
KMS/HSM's responsibility.

>
>... I don't think this can be accomplished by a contrib module, but
> would actually be easy to implement, but perhaps hard to document
> because the user API might be tricky.
>

If integration through a pipeline isn't good enough (it would be a
pain for the passphrase, with multiple prompts), what else do you see
an API having to provide?

>
> I think my big question is about your sentence, "A key feature of these
> key management approaches is that the application handling the
> encrypted data doesn't get the KEK, the HSM/KSM passes the DEK back
> after unwrapping it."  It is less secure for the HSM to return a KEK
> rather than a DEK?  I can't see why it would be.  The application never
> sees the KEK used to wrap the DEK it has stored in the file system,
> though that DEK is actually used as a passphrase by Postgres.  This is
> the same with the Yubikey --- Postgres never sees the private key used
> to unlock what it locked with the Yubikey public key.
>

The protocols and practices are designed for a lot of DEKs and small
number of KEK's. So the compromise of a KEK would, potentially, lead
to compromise of thousands of DEKs. In this particular case with 2
DEKs wrapped by one KEK, it doesn't sound like much of a difference, I
agree. From an acceptance and adoption point of view, I'm just
inclined to use the security ecosystem in an established and
understood way.

Regards
Alastair




Re: Proposed patch for key managment

2020-12-15 Thread Alastair Turner
Hi Bruce et al

Firstly, thanks for shaping the patch, getting it down to a manageable
scope of cluster file encryption. I think this is a great feature and it
matters to a lot of the customers I talk to at VMware about
adopting Postgres.

Since it's exciting stuff, I've been trying to lash together a PoC
integration with the crypto infrastructure we see at these customers.
Unfortunately, in short, the API doesn't seem to suit integration with HSM
big iron, like Thales, Utimaco, (other options are available), or their
cloudy lookalikes.

I understand the model of wrapping the Data Encryption Key and storing the
wrapped key with the encrypted data. The thing I can't find support for in
your patch is passing a wrapped DEK to an external system for decryption. A
key feature of these key management approaches is that the
application handling the encrypted data doesn't get the KEK, the HSM/KSM
passes the DEK back after unwrapping it. Google have a neat illustration of
their approach, which is very similar to others, at
https://cloud.google.com/kms/docs/envelope-encryption#how_to_decrypt_data_using_envelope_encryption

So instead of calling out to a passphrase command which returns input for a
PBKDF, Postgres (in the form of initdb or postmaster) should be passing the
wrapped DEK and getting back the DEK in plain. The value passed from
Postgres to the external process doesn't even have to be a wrapped DEK, it
could be a key in the key->value sense, for use in a lookup against Vault,
CredHub or the Kubernetes secret store. Making the stored keys opaque to
the Postgres processes and pushing the task of turning them into
cryptographic material to an external hepler process probably wouldn't
shrink the patch overall, but it would move a lot of code from core
processes into the helper. Maybe that helper should live in contrib, as
discussed below, where it would hopefully be joined by a bridge for KMIP
and others.

On Tue, 15 Dec 2020 at 19:09, Stephen Frost  wrote:

> Greetings,
>
> * Bruce Momjian (br...@momjian.us) wrote:
> > On Tue, Dec 15, 2020 at 10:05:49AM +0900, Michael Paquier wrote:
> > > On Mon, Dec 14, 2020 at 06:06:15PM -0500, Bruce Momjian wrote:

 

> > > >   There are a few shell script I should include to show how to create
> > > >   commands.  Where should they be stored?  /contrib module?
> > >
> > > Why are these needed.  Is it a matter of documentation?
> >
> > I have posted some of the scripts.  They involved complex shell
> > scripting that I doubt the average user can do.  The scripts are for
> > prompting for a passphrase from the user's terminal, or using the
> > Yubikey, with our without typing a pin.  I can put them in the docs and
> > then users can copy them into a file.  Is that the preferred method?
>
> If we are going to include these in core anywhere, I would think a new
> directory under contrib would make the most sense.  I'd hope that we
> could find a way to automate the testing of them though, so that we have
> some idea when they break because otherwise I'd be concerned that
> they'll break somewhere down the line and we won't notice for quite a
> while.
>
> Regards

Alastair


Re: Parallel copy

2020-02-26 Thread Alastair Turner
On Wed, 26 Feb 2020 at 10:54, Amit Kapila  wrote:
>
> On Tue, Feb 25, 2020 at 9:30 PM Tomas Vondra
>  wrote:
> >
...
> >
> > Perhaps. I guess it'll depend on the CSV file (number of fields, ...),
> > so I still think we need to do some measurements first.
> >
>
> Agreed.
>
> > I'm willing to
> > do that, but (a) I doubt I'll have time for that until after 2020-03,
> > and (b) it'd be good to agree on some set of typical CSV files.
> >
>
> Right, I don't know what is the best way to define that.  I can think
> of the below tests.
>
> 1. A table with 10 columns (with datatypes as integers, date, text).
> It has one index (unique/primary). Load with 1 million rows (basically
> the data should be probably 5-10 GB).
> 2. A table with 10 columns (with datatypes as integers, date, text).
> It has three indexes, one index can be (unique/primary). Load with 1
> million rows (basically the data should be probably 5-10 GB).
> 3. A table with 10 columns (with datatypes as integers, date, text).
> It has three indexes, one index can be (unique/primary). It has before
> and after trigeers. Load with 1 million rows (basically the data
> should be probably 5-10 GB).
> 4. A table with 10 columns (with datatypes as integers, date, text).
> It has five or six indexes, one index can be (unique/primary). Load
> with 1 million rows (basically the data should be probably 5-10 GB).
>
> Among all these tests, we can check how much time did we spend in
> reading, parsing the csv files vs. rest of execution?

That's a good set of tests of what happens after the parse. Two
simpler test runs may provide useful baselines - no
constraints/indexes with all columns varchar and no
constraints/indexes with columns correctly typed.

For testing the impact of various parts of the parse process, my idea would be:
 - A base dataset with 10 columns including int, date and text. One
text field quoted and containing both delimiters and line terminators
 - A derivative to measure just line parsing - strip the quotes around
the text field and quote the whole row as one text field
 - A derivative to measure the impact of quoted fields - clean up the
text field so it doesn't require quoting
 - A derivative to measure the impact of row length - run ten rows
together to make 100 column rows, but only a tenth as many rows

If that sounds reasonable, I'll try to knock up a generator.

--
Alastair




Re: Parallel copy

2020-02-15 Thread Alastair Turner
On Sat, 15 Feb 2020 at 04:55, Amit Kapila  wrote:
>
> On Fri, Feb 14, 2020 at 7:16 PM Alastair Turner  wrote:
> >
...
> >
> > Parsing rows from the raw input (the work done by CopyReadLine()) in a 
> > single process would accommodate line returns in quoted fields. I don't 
> > think there's a way of getting parallel workers to manage the 
> > in-quote/out-of-quote state required.
> >
>
> AFAIU, the whole of this in-quote/out-of-quote state is manged inside
> CopyReadLineText which will be done by each of the parallel workers,
> something on the lines of what Thomas did in his patch [1].
> Basically, we need to invent a mechanism to allocate chunks to
> individual workers and then the whole processing will be done as we
> are doing now except for special handling for partial tuples which I
> have explained in my previous email.  Am, I missing something here?
>
The problem case that I see is the chunk boundary falling in the
middle of a quoted field where
 - The quote opens in chunk 1
 - The quote closes in chunk 2
 - There is an EoL character between the start of chunk 2 and the closing quote

When the worker processing chunk 2 starts, it believes itself to be in
out-of-quote state, so only data between the start of the chunk and
the EoL is regarded as belonging to the partial line. From that point
on the parsing of the rest of the chunk goes off track.

Some of the resulting errors can be avoided by, for instance,
requiring a quote to be preceded by a delimiter or EoL. That answer
fails when fields end with EoL characters, which happens often enough
in the wild.

Recovering from an incorrect in-quote/out-of-quote state assumption at
the start of parsing a chunk just seems like a hole with no bottom. So
it looks to me like it's best done in a single process which can keep
track of that state reliably.

--
Aastair




Re: Parallel copy

2020-02-14 Thread Alastair Turner
On Fri, 14 Feb 2020 at 11:57, Amit Kapila  wrote:

> On Fri, Feb 14, 2020 at 3:36 PM Thomas Munro 
> wrote:
> >
> > On Fri, Feb 14, 2020 at 9:12 PM Amit Kapila 
> wrote:

 ...

> > > Another approach that came up during an offlist discussion with Robert
> > > is that we have one dedicated worker for reading the chunks from file
> > > and it copies the complete tuples of one chunk in the shared memory
> > > and once that is done, a handover that chunks to another worker which
> > > can process tuples in that area.  We can imagine that the reader
> > > worker is responsible to form some sort of work queue that can be
> > > processed by the other workers.  In this idea, we won't be able to get
> > > the benefit of initial tokenization (forming tuple boundaries) via
> > > parallel workers and might need some additional memory processing as
> > > after reader worker has handed the initial shared memory segment, we
> > > need to somehow identify tuple boundaries and then process them.
>

Parsing rows from the raw input (the work done by CopyReadLine()) in a
single process would accommodate line returns in quoted fields. I don't
think there's a way of getting parallel workers to manage the
in-quote/out-of-quote state required. A single worker could also process a
stream without having to reread/rewind so it would be able to process input
from STDIN or PROGRAM sources, making the improvements applicable to load
operations done by third party tools and scripted \copy in psql.


> >

...

>
> > > Another thing we need to figure out is the how many workers to use for
> > > the copy command.  I think we can use it based on the file size which
> > > needs some experiments or may be based on user input.
> >
> > It seems like we don't even really have a general model for that sort
> > of thing in the rest of the system yet, and I guess some kind of
> > fairly dumb explicit system would make sense in the early days...
> >
>
> makes sense.
>
The ratio between chunking or line parsing processes and the parallel
worker pool would vary with the width of the table, complexity of the data
or file (dates, encoding conversions), complexity of constraints and
acceptable impact of the load. Being able to control it through user input
would be great.

--
Alastair