stnoonan / spnego-http-auth-nginx-module

SPNEGO HTTP Authentication Module for nginx
Other
276 stars 112 forks source link

KVNO validation #123

Open arturslogins opened 2 years ago

arturslogins commented 2 years ago

Hello!

Can someone explain me with example, how can I disable kvno validation from keytab file? My keytab file consist of one record where KVNO = 13 but in error log I'm getting error - gss_accept_sec_context() failed: Cannot find key for HTTP/example@example.com kvno 9 in keytab

Should I need to generate and update these kvno numbers manually in keytab file? Better if there is an option to disable this validation

jheiss commented 2 years ago

You can't disable it. Key version 13 (KVNO==13) and key version 9 are different keys. The client has presented a ticket using KVNO 9, and your keytab only has KVNO 13, so the server can't validate the client's ticket. If you have a reasonable number of clients just have them kinit again (which will clear their credential cache of the service ticket for KVNO 9) and then they'll get a new service ticket for the latest KVNO (presumably 13) from your KDC.

arturslogins commented 2 years ago

You can't disable it. Key version 13 (KVNO==13) and key version 9 are different keys. The client has presented a ticket using KVNO 9, and your keytab only has KVNO 13, so the server can't validate the client's ticket. If you have a reasonable number of clients just have them kinit again (which will clear their credential cache of the service ticket for KVNO 9) and then they'll get a new service ticket for the latest KVNO (presumably 13) from your KDC.

But, which side walidate this kvno numbers? AD or module?

Like I see, this KVNO number comes from domain computer.
So I need to generate multiple KVNO numbers? For example from 1 to 1k ?

jheiss commented 2 years ago

Key versions aren't just a number. Each key version (KVNO) is a different key. The key with KVNO 1 can't be used to decrypt something encrypted with KVNO 2. The KVNO is incremented every time you perform an operation that causes the KDC to generate a new key for a given name. What those operations are varies depending on your KDC implementation, but is often tied to generating a new keytab.

Regarding your question about "which side validates the KVNO": the service (e.g. this nginx module) uses the KVNO in the client's ticket to figure out which key to use to validate the ticket. If the client's ticket refers to a key/KVNO that the service doesn't have it its keytab it will just give up and say "I don't have a key that goes with this ticket, so I can't validate it." It's not that the KVNO itself is the problem, it is an indication that the service doesn't have the cryptographic key it needs to actually do the crypto.

arturslogins commented 2 years ago

Key versions aren't just a number. Each key version (KVNO) is a different key. The key with KVNO 1 can't be used to decrypt something encrypted with KVNO 2. The KVNO is incremented every time you perform an operation that causes the KDC to generate a new key for a given name. What those operations are varies depending on your KDC implementation, but is often tied to generating a new keytab.

Regarding your question about "which side validates the KVNO": the service (e.g. this nginx module) uses the KVNO in the client's ticket to figure out which key to use to validate the ticket. If the client's ticket refers to a key/KVNO that the service doesn't have it its keytab it will just give up and say "I don't have a key that goes with this ticket, so I can't validate it." It's not that the KVNO itself is the problem, it is an indication that the service doesn't have the cryptographic key it needs to actually do the crypto.

And what you think about my workaround? If I generate kvno numbers in keytab file? Is it ok? Because I see the risk that I will have to recover the keytab file every week :|

jheiss commented 2 years ago

Typically the KDC issue service tickets to clients for the last KVNO on file. So generating a bunch of keys (KVNOs) doesn't do anything useful except slow down your service. (We've found that keytabs with hundreds of keys in them meaningfully slow down authentication time.) Let's say you somehow get your service to have a keytab with KVNOs for 1-999. The client wants to talk to "HTTP/example.com". It requests a service ticket for "HTTP/example.com" from your KDC. In general the KDC is going to look in its database, see that KVNO 999 is the largest/most recent, and send the client back a service ticket for HTTP/example.com using KVNO 999. The client then sends that ticket to nginx. The Kerberos library gets called by this module, which opens up your keytab and scans through it linearly until it finds KVNO 999 (likely at the very end of the file if you added the keys sequentially) and uses that key to validate the client's ticket. Having 998 other keys in the KDC database and in your keytab did nothing except slow down the process.

I think in your case it sounds like you're not sure why your KVNO jumped from 9 to 13. So you'll probably need to read some docs for your KDC (sounds like it is Active Directory?) or conduct some experiments to see what operation(s) cause a new key to get generated. My guess would be that you ran the command to generate a new keytab a few times.

arturslogins commented 2 years ago

Typically the KDC issue service tickets to clients for the last KVNO on file. So generating a bunch of keys (KVNOs) doesn't do anything useful except slow down your service. (We've found that keytabs with hundreds of keys in them meaningfully slow down authentication time.) Let's say you somehow get your service to have a keytab with KVNOs for 1-999. The client wants to talk to "HTTP/example.com". It requests a service ticket for "HTTP/example.com" from your KDC. In general the KDC is going to look in its database, see that KVNO 999 is the largest/most recent, and send the client back a service ticket for HTTP/example.com using KVNO 999. The client then sends that ticket to nginx. The Kerberos library gets called by this module, which opens up your keytab and scans through it linearly until it finds KVNO 999 (likely at the very end of the file if you added the keys sequentially) and uses that key to validate the client's ticket. Having 998 other keys in the KDC database and in your keytab did nothing except slow down the process.

I think in your case it sounds like you're not sure why your KVNO jumped from 9 to 13. So you'll probably need to read some docs for your KDC (sounds like it is Active Directory?) or conduct some experiments to see what operation(s) cause a new key to get generated. My guess would be that you ran the command to generate a new keytab a few times.

Yes you are right, I regenerate keytab file multiple times in AD (Windows server) side, when experimenting with configuration issue. So as You said, requesting new KVNO number it should not be bigger then KVNO in keytab - will research this. One think what I know - On client server there is multiple KDC for other systems, but these systems use apache kerberos module configuration.

Is there a difference between Nginx module and Apache krb module? Because in other systems where is used a Apache - there are no such problems with KVNO

jheiss commented 2 years ago

Both this module and the Apache krb module are not doing the Kerberos operations themselves. They're linking in an open source Kerberos library (the MIT library in most cases) to do the actual Kerberos bits. These modules are just bridging the HTTP server's interface with the Kerberos library. So the actual Kerberos operations should be the same in both cases.

arturslogins commented 2 years ago

Both this module and the Apache krb module are not doing the Kerberos operations themselves. They're linking in an open source Kerberos library (the MIT library in most cases) to do the actual Kerberos bits. These modules are just bridging the HTTP server's interface with the Kerberos library. So the actual Kerberos operations should be the same in both cases.

Thanks for information :)

arturslogins commented 2 years ago

Just for your information @jheiss - I changed nginx to apache and there is no issue with KVNO validation.

hawicz commented 2 years ago
 I regenerate keytab file multiple times in AD (Windows server) side,

If you do that, then you need to make sure to keep all the old keys available so existing clients that have already fetched a ticket with the old key (kvno 9 in your example) will keep working. This has nothing to do with nginx vs apache, and is required until those client's service tickets expire.

Alternately, you could force the client to fetch new service tickets by clearing its cred cache (kinit -R on unix, klist purge on windows)