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

FIDO2 endpoint Ingress missing from Helm charts #7889

Closed
tailnet-h-usky-io opened this issue Feb 28, 2024 · 1 comment · Fixed by #7931 or #7935
Closed

FIDO2 endpoint Ingress missing from Helm charts #7889

tailnet-h-usky-io opened this issue Feb 28, 2024 · 1 comment · Fixed by #7931 or #7935
Assignees

Comments

@tailnet-h-usky-io
Copy link

Describe the bug
I am unable to register FIDO2 keys.

Specifically, Clicking the Ready button in Casa's Security Keys and built-in Platform Authenticators page
results in an error. (screenshot below)

The same problem occurs in Chrome, Firefox, and Safari.
This is a fresh installation of Janssen using the v1.0.22 Helm charts (only test users).

To Reproduce
Steps to reproduce the behavior:

  1. Install Janssen from Helm chars with Casa and FIDO2 enabled
  2. Enable the fido2 authentication script in TUI config
  3. Enable FIDO 2 as an auth option in the Casa Admin page
  4. Restart auth service, fido2 service, and casa service
  5. Attempt to register a FIDO device

Expected behavior
The browser-native FIDO2 device registration flow

Screenshots
image

Desktop (please complete the following information):

  • OS: MacOS
  • Browser: Chrome, Firefox, and Safari
  • Version: latest

Additional context

The browser debug console shows a successful response to a POST to

https://[my jans host]/jans-casa/zkau

.. but the Response payload was:

{
    "rs": [
        [
            "invoke",
            [
                null,
                "showAlert",
                "An error occurred",
                "error",
                5000
            ]
        ],
        [
            "setAttr",
            [
                {$u:'jZ7Kk1'
                },
                "visible",
                true
            ]
        ]
    ],
    "rid": 2
}

The error surfaces itself in the Casa server log, which reports 2 potentially-related issues:

  1. an ERROR from the jans.casa.core.PersistenceService, which chokes on what might be an incorrect LDAP query; and
  2. a 404 from io.jans.casa.plugins.authnmethod.service.Fido2Service$Proxy

Casa service log

casa - 28-02 18:42:35.950 INFO  plugins.authnmethod.service.Fido2Service Fido2Service.java:57- Retrieving contents of URL https://sso.h.usky.io/.well-known/fido2-configuration
casa - 28-02 18:42:35.971 INFO  plugins.authnmethod.service.Fido2Service Fido2Service.java:60- Base path is https://sso.h.usky.io/jans-fido2/restv1/attestation
casa - 28-02 18:42:36.058 ERROR jans.casa.core.PersistenceService PersistenceService.java:107- Failed to find entries with baseDN: ou=fido2_register,inum=20601eb7-f87f-4530-8000-76ec378b96d8,ou=people,o=jans, filter: (&(&(objectClass=jansFido2RegistrationEntry))(&(jansStatus=registered)(personInum=20601eb7-f87f-4530-8000-76ec378b96d8)(jansApp=sso.h.usky.io)))
casa - 28-02 18:42:36.058 INFO  ui.vm.user.UserPreferenceViewModel UserPreferenceViewModel.java:85- Number of credentials for user admin: 0
casa - 28-02 18:42:36.065 ERROR jans.casa.core.PersistenceService PersistenceService.java:107- Failed to find entries with baseDN: ou=fido2_register,inum=20601eb7-f87f-4530-8000-76ec378b96d8,ou=people,o=jans, filter: (&(&(objectClass=jansFido2RegistrationEntry))(&(jansStatus=registered)(personInum=20601eb7-f87f-4530-8000-76ec378b96d8)(jansApp=sso.h.usky.io)))
casa - 28-02 18:42:36.077 ERROR jans.casa.core.PersistenceService PersistenceService.java:107- Failed to find entries with baseDN: ou=fido2_register,inum=20601eb7-f87f-4530-8000-76ec378b96d8,ou=people,o=jans, filter: (&(&(objectClass=jansFido2RegistrationEntry))(&(jansStatus=registered)(personInum=20601eb7-f87f-4530-8000-76ec378b96d8)(jansApp=sso.h.usky.io)))
casa - 28-02 18:42:49.732 ERROR jans.casa.core.PersistenceService PersistenceService.java:107- Failed to find entries with baseDN: ou=fido2_register,inum=20601eb7-f87f-4530-8000-76ec378b96d8,ou=people,o=jans, filter: (&(&(objectClass=jansFido2RegistrationEntry))(&(jansStatus=registered)(personInum=20601eb7-f87f-4530-8000-76ec378b96d8)(jansApp=sso.h.usky.io)))
casa - 28-02 18:43:05.683 ERROR plugins.authnmethod.service.Fido2Service Fido2Service.java:197- Registration failed (code: 404); response was: <html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>

casa - 28-02 18:43:05.683 ERROR ui.vm.user.SecurityKey2ViewModel SecurityKey2ViewModel.java:179- Registration failed (code: 404)
java.lang.Exception: Registration failed (code: 404)
	at io.jans.casa.plugins.authnmethod.service.Fido2Service.doRegister(Fido2Service.java:198) ~[classes/:?]
	at io.jans.casa.plugins.authnmethod.service.Fido2Service$Proxy$_$$_WeldClientProxy.doRegister(Unknown Source) ~[classes/:?]
	at io.jans.casa.ui.vm.user.SecurityKey2ViewModel.triggerAttestationRequest(SecurityKey2ViewModel.java:170) ~[classes/:?]
	at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
	at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:?]
	at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:?]
	at java.lang.reflect.Method.invoke(Unknown Source) ~[?:?]
	at org.zkoss.bind.impl.ParamCall.call(ParamCall.java:174) ~[zkbind-9.6.0.2-jakarta.jar:9.6.0.2-migrated-1.0.0]
	at org.zkoss.bind.impl.BinderImpl.handleNotifyChange(BinderImpl.java:1952) ~[zkbind-9.6.0.2-jakarta.jar:9.6.0.2-migrated-1.0.0]
	...
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1194) ~[?:?]
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1149) ~[?:?]
	at java.lang.Thread.run(Unknown Source) ~[?:?]

Analysis

I have three initial ideas about what might be causing this problem.

Idea 1 - Potentially bad app logic?

Interestingly, the non-error (INFO) log message:

casa - 28-02 18:42:36.058 INFO  ui.vm.user.UserPreferenceViewModel UserPreferenceViewModel.java:85- Number of credentials for user admin: 0

is mixed in with the ERROR messages:

casa - 28-02 18:42:36.065 ERROR jans.casa.core.PersistenceService PersistenceService.java:107- Failed to find entries with baseDN: ou=fido2_register,inum=20601eb7-f87f-4530-8000-76ec378b96d8,ou=people,o=jans, filter: (&(&(objectClass=jansFido2RegistrationEntry))(&(jansStatus=registered)(personInum=20601eb7-f87f-4530-8000-76ec378b96d8)(jansApp=sso.h.usky.io)))

So, on the one hand, Casa understands that there are no FIDO creds registered for this user, but on the other hand, when it queries the persistence service for any jansFido2RegistrationEntry objects (I'm using LDAP), it panics when none are found.

This feels at first like a bug in the core Casa application logic for this page - except that surely would have been caught before.
The fact that it fails to find FIDO entries for a given user should not cause an error, right?

Idea 2 - Potentially bad connectivity between the casa and fido2 services?

Aside from the LDAP-related errors, why the 404 from io.jans.casa.plugins.authnmethod.service.Fido2Service$Proxy ?
Is the Casa service trying to reach the fido2 service, and some ingress or proxy route is misconfigured?
Note that the /.well-known/fido2-configuration is reachable as configured.

  fido2:
    enabled: true
    ingress:
      # -- Enable endpoint /.well-known/fido2-configuration
      fido2ConfigEnabled: true

Idea 3 - Malformed LDAP (and/or SQL?) query?

One more thing strikes me as odd: the baseDN of that LDAP query

ou=fido2_register,inum=20601eb7-f87f-4530-8000-76ec378b96d8,ou=people,o=jans

Because LDAP is dumb, this string actually represents the following hierarchy (the components are reversed!):

o=jans---
        |
        ou=people----
                    |
                    inum=206...--                  <---- LDAP entry for admin user (JansCustomPerson)
                                |
                                ou=fido2_register  <----- does *not* exist right here, 
                                                        ...but *does* exist under o=jans,ou=fido2 !

It's been a long time since I got my hands dirty with LDAP, but I can't remember ever seeing an ou (in this case, fido_register)
embedded below a person entry. I don't think it violates any LDAP schema rules, but it does seem like a strange place to put it.
Why would each user have their own fido2_register ou entry rather than just a multi-valued attribute?

Even more compellingly, the ou entries fido2_register and fido2_auth do actually exist already, but in a different place:
image

^^ on the left, you can see the fido2_register and fido2_auth entries under o=jans,ou=fido2.

Any help debuigging this problem will be greatly appreciated.

Thanks in advance!
-b

@tailnet-h-usky-io
Copy link
Author

OK, I dug into the code and fixed it.

TL;DR; The proper title of this Issue should be:
FIDO2 endpoint Ingress missing from Helm charts
(This Issue probably only affects Helm-based deployments.)

Here are the clarifications / resolutions to the three ideas previously posed.

Idea 1 - Potentially bad app logic?

Nope.

The ERROR message is indeed spurious, but the app code is fine – in fact, Casa is covering up a bug in the Gluu ORM layer.
A pedant could argue that the ERROR level message should be a WARNING, but the point is that this is not ultimately the source of the problem.

Idea 2 - Potentially bad connectivity between the casa and fido2 services?

Bingo.

As noted above, in my deployment, the FIDO well-known configuration endpoint is exposed – but the fido2 service endpoints are not! The 404 is coming from the K8s NGinx Ingress - you can see <center>nginx</center> in the Casa log output!

So, I exported the Casa Ingress Resource into a YAML file...

kubectl get ingresses.networking.k8s.io janssen-nginx-ingress-casa -o yaml >janssen-nginx-ingress-fido2.yaml

...then just search-replaced casa with fido2, resulting in:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    # meta.helm.sh/release-name: janssen
    # meta.helm.sh/release-namespace: jans
    nginx.ingress.kubernetes.io/affinity: cookie
    nginx.ingress.kubernetes.io/proxy-next-upstream: error timeout invalid_header
      http_500 http_502 http_503 http_504
    nginx.ingress.kubernetes.io/session-cookie-hash: sha1
    nginx.ingress.kubernetes.io/session-cookie-name: fido2-route
  generation: 1
  labels:
    app: janssen-nginx-ingress-fido2
    # app.kubernetes.io/managed-by: Helm
  name: janssen-nginx-ingress-fido2
  namespace: jans
spec:
  ingressClassName: nginx
  rules:
  - host: sso.[my domain].io
    http:
      paths:
      - backend:
          service:
            name: fido2
            port:
              number: 8080
        path: /jans-fido2
        pathType: Prefix
  tls:
  - hosts:
    - '*.[my domain].io'
    secretName: my-ssl-cert
status:
  loadBalancer:
    ingress:
    - ip: 127.0.0.1

^^ I commented out the Helm annotations so as not to confuse the deployment tool.

Exposing the FIDO2 endpoints by adding the required Ingress Resource fixes this problem

If I have time today or tomorrow I'll try to open a PR for the fix.

I have not tried to log in with the created FIDO key, but it is saved...

Idea 3 - Malformed LDAP (and/or SQL?) query?

Nope.

Unorthodox as this LDAP structure is, it works fine, and stores jansFido2RegistrationEntry Objects beneath an ou attached to each user in the LDAP hierarchy.
image
I guess this is better for referential integrity when a user gets deleted...? 🤷

@tailnet-h-usky-io tailnet-h-usky-io changed the title Unable to register FIDO2 devices FIDO2 endpoint Ingress missing from Helm charts Feb 29, 2024
@iromli iromli self-assigned this Mar 1, 2024
@iromli iromli reopened this Mar 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants