Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auth (DNSSEC): a "hybrid" signing mode for serving RRSIG #14372

Open
d-wibowo opened this issue Jun 24, 2024 · 9 comments
Open

Auth (DNSSEC): a "hybrid" signing mode for serving RRSIG #14372

d-wibowo opened this issue Jun 24, 2024 · 9 comments

Comments

@d-wibowo
Copy link
Contributor

  • Program: Authoritative
  • Issue type: Feature request

Short description

A hybrid signing mode for a particular zone, where certain record types can be pre-signed while other types can be signed directly by PDNS.

Usecase

A mode where signatures of DNSKEY record types are provided by the backend pre-signed, while other record types are still signed directly by PDNS Auth by providing it the ZSK's private key.

Description

When using PDNS Auth's online signing mode, we can provide PDNS Auth with the private keys of ZSK and/or KSK. If we provide both KSK and ZSK, PDNS Auth will sign DNSKEY record with KSK while the other record types with ZSK; however, without providing the KSK (only the ZSK), PDNS Auth will also sign the DNSKEY record type with the ZSK.

We are currently in a situation where our KSK's private key must be held by a certain KMS Service outside of our control. In this arrangement, we only have access to the KSK's public key and also a Sign method provided by the KMS; so we can still pre-sign the DNSKEY records before storing it in our backend. With this scenario in mind, the only option that we have is to use the pre-signed mode since we cannot provide the private key of our KSK to PDNS Auth.

We do manage the ZSK ourselves though, so we do have access to its private key. Technically with this, we can use the online signing mode, however, this will mean that we are not going to be utilising our KSK for the signing of the DNSKEY records, and we are not going to be using the pre-signed DNSKEY signatures generated from the KMS.

What we are proposing is some sort of hybrid mode between online signing and pre-signed.

The way we envisioned it is having DNSKEY signatures as pre-signed records provided by the backend, while for signatures of record types other than DNSKEY will be signed online by PDNS. This way, us that do not have access to the KSK's private key but still retain control over the ZSK, would still be able to take advantage of PDNS Auth's online signing mode, while allowing ourselves the option of having the DNSKEY signatures pre-signed by an external KMS.

@Habbie
Copy link
Member

Habbie commented Jun 27, 2024

@d-wibowo
Copy link
Contributor Author

d-wibowo commented Jul 1, 2024

Hi @Habbie, thanks for the reply 😺

I've checked out the direct-dnskey config and unfortunately, I don't think it would be able to help with our situation.

Do correct my understanding on direct-dnskey if I am mistaken; when disabled, PDNS Auth would effectively generate DNSKEY records by deriving it from the private keys (of ZSKs / KSKs) gathered by calling the backend (in my case I was using remote-backend and they called the GetDomainKeys function). However, when the config is enabled, PDNS Auth would not try to generate / construct the DNSKEY records by itself, rather it will query the backend for any available DNSKEY records and return it as such.

While it is definitely closer to something that we were hoping to be achieved, I do not think it is sufficient for our case.

Just to give an overview of what we had tried.

Setup:

  1. PDNS Auth with remote backend and online-signing enabled
  2. The GetDomainKeys function returns the private key for a ZSK
  3. The Lookup function for DNSKEY record types return the DNSKEY records of both ZSK and KSK

When direct-dnskey Disabled:

  1. Resolving for type DNSKEY only returns 1 DNSKEY record representing the ZSK
  2. PDNS Auth signs the DNSKEY RRSET with the ZSK

When direct-dnskey Enabled:

  1. Resolving for type DNSKEY returns 2 DNSKEY records representing the ZSK and KSK
  2. PDNS Auth signs the DNSKEY RRSET with ZSK

The problem that we have with either approach is that both ultimately uses the ZSK's private key to sign the DNSKEY RRSET, which we want to avoid.

What we had in mind goes on something like the following (using remote backend again just as an example)

Suppose we have a setup:

  1. PDNS Auth with remote backend
  2. We have the zone example.com on the backend, with records of type A , DNSKEY and RRSIG
  3. The DNSKEY RRSET has ZSK and KSK records
  4. The RRSIG record is the signature of the DNSKEY RRSET (presigned)
  5. The GetDomainKeys function return the private key of the ZSK

When resolving for example.com DNSKEY:

  1. PDNS Auth would do a lookup to the backend for the DNSKEY records and return the RRSET containing both ZSK and KSK (this is something that is achievable using the direct-dnskey config before)
  2. PDNS Auth would do a lookup to the backend for the presigned RRSIG of the DNSKEY RRSET
  3. It would effectively be processing DNSKEY record types in presigned mode

When resolving example.com A:

  1. Auth would do a lookup to the backend for the A record and return its corresponding value
  2. Auth would get the private key of the ZSK from the backend (via GetDomainKeys) and signs the response RRSET
  3. Here, Auth would effectively be running in online signing mode

In short, for a single zone, its DNSKEY record is treated as in presigned mode while its other types are treated as in online signing mode.

Let me know if you have any other questions. I am not sure if PDNS supports this currently since I haven't found any mention on the docs regarding this kind of setup.

cheers..

@Habbie
Copy link
Member

Habbie commented Jul 1, 2024

However, when the config is enabled, PDNS Auth would not try to generate / construct the DNSKEY records by itself, rather it will query the backend for any available DNSKEY records and return it as such.

It should be doing both when enabled.

@Habbie
Copy link
Member

Habbie commented Jul 1, 2024

PDNS Auth would do a lookup to the backend for the presigned RRSIG of the DNSKEY RRSET

right. I wonder if we could/should expand direct-dnskey to do this.

@d-wibowo
Copy link
Contributor Author

d-wibowo commented Jul 2, 2024

Interesting. Now that you mentioned it, it does sound similar to the way direct-dnskey works; maybe direct-dnskey could be expanded to cover the case when a DNSKEY signature was presigned.

Or, it might also be possible to have some sort of new configuration, something like direct-rrsig, where similar to direct-dnskey, if auth wasn't able to get the desired presigned RRSIG records from the backend, it will try to generate RRSIG by itself through online signing mode. This way, it wouldn't only be limited to DNSKEY records only. Though i'm not that familiar with the pdns code, so i'm not sure how great of an effort would be required to implement something like this.

@d-wibowo
Copy link
Contributor Author

@Habbie I'd like to come back to this issue if you don't mind. Have you guys started working on it? If not, I was wondering if I can open a PR on it, but I'd still need a second opinion if the approach is correct and/or if there are any concerns.

Since you mentioned about the possibility of expanding direct-dnskey to accomodate this, I was thinking that direct-dnskey could be updated to accept one more option. Currently in my testing, I named the config rrsig (I'm open to other name suggestions). So, with the rrsig option for direct-dnskey, aside from Auth doing direct query for DNSKEY records to the backend (similar to the yes option), it will also try to do a direct query for the RRSIG of said DNSKEY records. It thought this feature should be separated from the normal yes option as to accommodate users who want a direct query for DNSKEY record, but still want them to be signed live within PDNS Auth.

The main change to the logic of the code should happen within the addSignature(...) function specifically here. We can change the checking to if(dk.isPresigned(signer) || (::arg()["direct-dnskey"] == "rrsig" && signQType == QType::DNSKEY)). This way, when the direct-dnskey mode is set to rrsig, and the RRS type we're trying to sign is DNSKEY, we can do direct query to the backend for the RRSIG record (which should be handled in the same way as a presigned record).

Personally, I have tested this and it seems to work. What do you think about this approach?

@d-wibowo
Copy link
Contributor Author

@Habbie I'd like to ask your thoughts on another alternative approach and whether this is preferable to the earlier approach.

Rather than expanding direct-dnskey setting to have a new option as mentioned previously, what if we instead add an entirely new setting separate from direct-dnskey? After talking a bit with some of my senior colleagues, one of their concerns (and confusion) is that direct-dnskey has more to do with the addition of DNSKEY records itself, rather than the addition of its signatures; it might be better to separate this new feature as a new setting from direct-dnskey, to make the distinction clear.

In terms of actual changes to the code, the main logical change will remain the same as what I mentioned earlier, that is modifying the checking within the addSignature(...) method; its just that we will not be using the direct-dnskey=rrsig as a condition, and instead replacing direct-dnskey with a new setting. At the moment, I was thinking of something along the lines of direct-dnskey-signature with the default option no and the other option yes.

@Habbie
Copy link
Member

Habbie commented Aug 22, 2024

I'm not picky about flag naming or the number of flags, for now; I find those things are easier to reason about once there is running code. As for that code, what you say makes sense I think. Would love to see a PR so we can test.

@d-wibowo
Copy link
Contributor Author

Cool, I've opened the PR #14581 already. Looking forward for the review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants