How to handle a custom provider where some input to the backend API can't be read back

Hello!

I am writing a provider for an API where I came across the following situation: One of my resources is a certificate. When I create a certificate I specify an ID (a string), the public key and the private key of the certificate. So when I want to create this certificate through my provider I get to specify the ID, the public key, and the private key of the certificate. So far, so good.
When I started implementing the read-part of the resource I realised that I am unable to read the private key back. I can only read the ID and the public key.
How do I handle this in my provider? I feel like this is a problem because I can’t verify that the state in the physical resource is the same as the Terraform state. I.e. the Terraform state will have three properties (id, public key, private key) but when I read the remote state I would only get two properties (id, public key).

I suppose someone has come across this situation before, how should I handle this?

1 Like

Hi @mattias-fjellstrom,

The typical compromise here is for the “read” operation to just preserve whatever was already recorded in the state, and thus remember the value as it was at the end of the last apply.

The planning step can then compare the current configuration to that previous value and still plan to make a change if needed, but of course there’s no way to detect if someone changed the value outside of Terraform and so the “Objects changed outside of Terraform” report won’t detect it and a planned update, if any, will report the value from the previous apply as the old value, rather than the current value stored in the remote system.

The schema.ResourceData object in the old SDK will preserve values by default in Read, and so you can usually get the effect I’ve described above by just not calling d.Set for the attribute in question, and thus allow the old value to propagate into the new state object.

2 Likes

One additional thing you could try for your particular case is to add some logic to Read to see if public_key has changed, and if so to force the private_key to some invalid placeholder value that can never be the real value. This is under the assumption that the public and private keys will always change together, and thus you can use the change of the public key as a proxy to detect the change to the private key even though you won’t know what the new private key value is.

The tradeoff here is that the private_key diff in the UI will appear as whatever placeholder value you select, which means you’d need to choose that value carefully to help a user understand what it represents.

1 Like

@apparentlymart Thanks for your suggestions! I will do as you suggested, to just use the value already in the state. I don’t know why that didn’t occur to me :slight_smile: