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

FR: Limit ssh access based on OAuth groups/roles #547

Open
LecrisUT opened this issue Apr 20, 2021 · 4 comments
Open

FR: Limit ssh access based on OAuth groups/roles #547

LecrisUT opened this issue Apr 20, 2021 · 4 comments

Comments

@LecrisUT
Copy link
Contributor

Use case

If we have multiple machines, or a machine can have custom ssh access, e.g. Github or Gitea access, it would be better to have control over the user+domain the user can have ssh access. Currently this can be done with modifying the ssh template, but it would be great to have something accessible via cli/default template.

Also this would make it easier to integrate with LDAP's group management.

Implementation

Server side

For the host certificate either in the extension or critical options (still don't know the difference between them), we could add a key-value pair for principal or for a default group to .Token.Groups array so that we can query the membership of users later on.

On the sshd.config side, the simplest implementation would be to create a simple command (preferably baked in step-cli for security) to input in AuthorizedPrincipalsCommand, and upon success it would output the contents of .ssh/authorized_principals or the username (and .Token.preferred_username?) if the file does not exist, otherwise output an empty string so that it fails authentication. A mock-up command of this would be:

# Check sshd_config TOKENS for more token options
# %h expands to user's home
# %k expands to user_certificate
# %D expands to the routing domain
AuthorizedPrincipalsCommand step ssh check-user %k --domain %D --home %h --host-key /path/to/host/key
# Might need to comment out AuthorizedPrincipalsFiles

Client side

For the client if authenticating via OAuth, simply store the groups it belongs to into an extension/critical options which are obtained via the .Token. This can be done either via roles or specific mappers on the OAuth. From my default keycloak setting I have added a scope based on roles (/resource_access/ClientID/roles) and one based on custom mappers (groups), and here's a stripped down version of it:

{
  "aud": [ "StepCA_ClientID" ],
  "azp": "StepCA_ClientID",
  "allowed-origins": [ "/" ],
  "realm_access": {
    "roles": [ "Some_Keycloak_roles" ]
  },
  "resource_access": {
    "StepCA_ClientID": {
      "roles": [ "Group1" ]
    }
  },
  "scope": "openid email profile",
  "groups": [
    "/Group2",
    "/Group2/Group3"
  ],
  "preferred_username": "username",
}

IMO the mappers is easier to setup as it takes all of the groups it belongs to, but with roles, we can change the name to better suit the certificate's names.

Some customization could be to allow/deny gitea@gitea.example.com out of the gate based on role mapping, although it shouldn't be necessary.

Things to consider

  • It should be compatible with Github's organization/team tokens
  • Make sure that the user cannot override this command with their own .ssh/authorized_principals
@maraino
Copy link
Contributor

maraino commented Apr 22, 2021

Hi @LecrisUT this is part of our paid solution.

As you mention one of the options to solve this is using the AuthorizedPrincipalsCommand. You can use ssh certificate templates to add custom extension that the script can use to limit the access to a server. You can access the token payload using the .Token variable in the template. For example, .Token.resource_access.StepCA_ClientID.roles will return the array ["Group1"].

The difference between extensions and critical options is that a server/client must understand the critical options, but it can ignore unknown extensions.

@LecrisUT
Copy link
Contributor Author

I will try this out on a cloud node to see how it would affect other implementations. Will this become available to self-hosted step-ca, or only through smallstep.com?

@LecrisUT
Copy link
Contributor Author

Any info on how the sshd can process custom Critical options? I want to make a simple AuthorizedPrincipalsCommands to specify which machines and URLs it is allowed to access. I was thinking of using the extensions, but might be helpful to setup a critical options, maybe so as to limit the certificate's usage. Actually there might be no practical usage for it, but would be helpful to know in the future.

Otherwise, can someone suggest some methods of reading the ssh certificate options in script? Probably I'll have to use openssl, but if there is a more convenient tool, it would be much appreciated.

@maraino
Copy link
Contributor

maraino commented May 6, 2021

@LecrisUT you might want to use extensions because the sshd implementation might refuse to authenticate a cert with an unknown critical option. Right now only 2 critical options are defined for a client cert.

The docs about SSH certificates are in /~https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.certkeys

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

No branches or pull requests

2 participants