goauthentik / authentik

The authentication glue you need.
https://goauthentik.io
Other
12.96k stars 865 forks source link

Allow adding SSH Keys in user Profile #2145

Closed ikogan closed 2 years ago

ikogan commented 2 years ago

Is your feature request related to a problem? Please describe. Not really

Describe the solution you'd like Several services support pulling SSH Authorized Keys from LDAP including sssd as well as some git tools. For Linux systems in particular, if you're using a network filesystem, another source of SSH keys is crucial as they might not be available on login until you mount the filesystem.

This can already be achieved by manually setting the sshPublicKey attribute manually on a user, which is wonderful. Unfortunately this has to be done by an administrator. It would be great if this is something that could be managed by a user on their profile.

Describe alternatives you've considered Manually adding SSH keys by administrators.

Additional context Relatedly, I believe that the sshPublicKey attribute is multi-valued. Is it possible to specify multi valued LDAP attributes right now? I honestly haven't tried it.

ikogan commented 2 years ago

This seems to be possible with the new customizable user attributes flow, here's how I'm doing it in case anyone comes here from Google:

Add a prompt called attributes.sshPublicKey. Check "Interpret placeholder as expression" and set the expression to:

try:
    return user.attributes.get("sshPublicKey", "")
except:
    return ''

Create a new expression policy with the following expression:

request.context['prompt_data'].get('attributes', {}).pop('attributes.sshPublicKey', None)

Create a new prompt stage that uses the standard fields of the default stage plus the new prompt and expression policy. I'm not sure exactly why the last one is necessary and I think there's some sort of a bug. It looks like if the value is blank, attributes.sshPublicKey will be left with the prompt expression, which is not JSON serializable.

samip5 commented 2 years ago

How would one use this for multiple pub keys? :D

ikogan commented 2 years ago

So, I have not tested this with multiple keys, here's what I would want to do:

  1. Manually add a YAML list to the user like this:
    ...
    sshPublicKey:
      - { one key }
      - { second key }
    ...
  2. Use Apache Directory Studio or ldapSearch to see what the LDAP outpost returns. I would hope it would return multiple values but I haven't tested it. If it doesn't, submit a feature request or, even better, a pull request that fixes that.
  3. Assuming it does, update the code above to work with multiple keys. I would expect each key would be a single line in a larger field, so maybe something like (haven't tested this at all):

    try:
     keys = user.attributes.get("sshPublicKey", "")
    
     if type(keys) is str:
       return keys
     else:
       return "\n".join(keys)
    except:
     return

    I'm honestly not sure what we should do with the second expression, I'd need to test it out more because we'll at least need to transform the single string value into a list by splitting it by newlines.

samip5 commented 2 years ago

So, I have not tested this with multiple keys, here's what I would want to do:

1. Manually add a YAML list to the user like this:
   ```yaml
   ...
   sshPublicKey:
     - { one key }
     - { second key }
   ...
   ```

2. Use Apache Directory Studio or `ldapSearch` to see what the LDAP outpost returns. I would hope it would return multiple values but I haven't tested it. If it doesn't, submit a feature request or, even better, a pull request that fixes that.

3. Assuming it does, update the code above to work with multiple keys. I would expect each key would be a single line in a larger field, so maybe something like (haven't tested this at all):
   ```python
   try:
     keys = user.attributes.get("sshPublicKey", "")

     if type(keys) is str:
       return keys
     else:
       return "\n".join(keys)
   except:
     return
   ```

   I'm honestly not sure what we should do with the second expression, I'd need to test it out more because we'll at least need to transform the single string value into a list by splitting it by newlines.

That's one way to not get the user settings to load at all anymore. :dagger:

Lagertonne commented 6 months ago

Just quickly mentioning here that I found a solution for multiple SSH-keys which I documented in https://github.com/goauthentik/authentik/issues/3134?notification_referrer_id=NT_kwDOADe-R7IzODY0MDgxODQ5OjM2NTMxOTE#issuecomment-1975270490