Subject: bug#51487: The openssh service does not allow multiple authorized key files per user

From: Ludovic Courtès <[email-masked]>
Date: Mon, 15 Nov 2021 15:42:28 +0100

Hi,

Vivien Kraus <[email-masked]> skribis:

>  (define (extend-openssh-authorized-keys config keys)
>    "Extend CONFIG with the extra authorized keys listed in KEYS."
> -  (openssh-configuration
> -   (inherit config)
> -   (authorized-keys
> -    (append (openssh-authorized-keys config) keys))))
> +  (let generate-keys
> +      ((user-keys
> +        (append (openssh-authorized-keys config) keys))
> +       ;; The by-user vhash indexes a list of list of keys for each user, the
> +       ;; list of list is not concatenated eagerly to avoid quadratic
> +       ;; complexity.
> +       (by-user (alist->vhash '())))
> +    (match user-keys
> +      (()
> +       (openssh-configuration
> +        (inherit config)
> +        (authorized-keys
> +         (vhash-fold
> +          (lambda (user keys other-users)
> +            `((,user ,@(apply append (reverse keys))) ,@other-users))
> +          '() by-user))))
> +      (((user keys ...) other-user-keys ...)
> +       (let ((existing
> +              (match (vhash-assoc user by-user)
> +                ((_ . keys) keys)
> +                (#f '()))))
> +         (generate-keys
> +          other-user-keys
> +          (vhash-cons user `(,keys ,@existing) by-user)))))))

I find it a bit hard to read.  What I had in mind is along these lines:

  (match (openssh-authorized-keys config)
    (((users _ ...) ...)
     ;; Build a user/key-list mapping.
     (let ((user-keys (fold (lambda (spec table)
                              (match spec
                                ((user keys ...)
                                 (vhash-cons user keys table))))
                            vlist-null
                            (openssh-authorized-keys config))))
       ;; Coalesce the key lists associated with each user.
       (map (lambda (user)
              (concatenate (vhash-fold* cons '() user user-keys)))
            users))))

WDYT?

Thanks,
Ludo’.