Project: Teleport (Provisioning / Security & Compliance)
File: 0057-automatic-user-provisioning.md

authors: Alex McGrath (alex.mcgrath@goteleport.com) state: implemented (v10.0.0) Automatically create non-existing users and optionally add them to `sudoers` on Teleport nodes. Users will be removed after all sessions have logged out. Currently, when logging into an SSH node, the user must be pre-created. Adding automatic user and `sudoer` provisioning would make it so that any Teleport user would be able to login and have the account created automatically without manual intervention. The following are required for this feature: Ability to automatically provision a Linux user if it's not present on the node. Ability to automatically provision a Linux group if it's not present on the node. Ability to add the provisioned user to existing Linux groups defined in the user traits/role. Ability to add the provisioned user to sudoers. Clean up the provisioned user / sudoers changes upon logout (being careful not to remove pre-existing users). Several new fields will need to be added to to the role `options` and `allow` sections: ```yaml kind: role version: v5 metadata: name: example spec: options: createhostuser: true allow: host_groups: [ubuntu, "{{internal.groups}}", "{{external.xxx}}"] host_sudoers: ["{{internal.logins}} ALL=(ALL) ALL", ...] ``` An individual `ssh_service` can be configured disable auto user creation with the below config: ```yaml ssh_service: disablecreatehost_user: true ``` In order to create users `useradd` will be executed from teleport after a user has tried to access a Teleport SSH node. When a user is created they will be added to the specified groups from the `host_groups` field in the role. In addition the user will be added to a special `teleport-system` group which can be used to indicate that the user was created by teleport and that its safe for it to be deleted. The groups will be created via `groupadd` at startup if they do not already exist and users will be added to groups via `usermod -aG <list of groups> <username>` The set of valid names that are valid on Linux varies between distros and are generally more restrictive than the allowed usernames in Teleport. This will require that names containing invalid characters have those characters removed/replaced. Information on the valid characters between Linux distros is available . The common core of valid characters is `^{0,30}$`. Each user with entries in `host_sudoers` will have a file created in `/etc/sudoers.d`, with one entry per line. If a user is in multiple rules that specify `host_sudoers` they will be all be concatenated

If a system has `visudo` present, validation could be performed by executing `visudo -c -f path/to/sudoersfile`, where if it fails to validate, the user fails to have the shell start and the error is reported. In order to stop users from being able to edit the sudoers file a command allow list must be used, as or equivalent to below: ``` ${USERNAME} ALL = (${USER TO RUN AS}) NOPASSWD: /bin/cmd1 args, /bin/cmd2 args ``` Should a user be given `root` access to all commands, they will be able to modify any file, including sudoers files. After all of a users sessions are logged out the created user and any `sudoers` files that were created for that user will be deleted if that user is also a member of the `teleport-system` group. Users can not be deleted while they have running processes so each time a session ends, an attempt to delete the user can happen, if it succeeds the sudoers file can also be removed. If it does not succeed a cleanup process will run every 5 minutes, that will attempt to delete users if they no longer have running processes. This clean up process will also ensure that users with running sessions during a restart will be cleaned up appropriately. Groups will not be cleaned up and will be created once and be reused this is to avoid files created with specified groups will remain accessible between sessions to users in those groups. Automatic user provisioning will require that all roles matching a node via `labels` have `createhostuser=true` This will deprecate the current `createhostuser` option and replace it with an option called `createhostuser_mode`. The new option will have 3 possible settings: `off`: disables host user creation `drop`: deletes users after the session ends (current behaviour) `keep`: leaves host users after the session ends. If the deprecated `createhostuser` option is specified and `createhostuser_mode` is not, it will default to using `drop` when it is true, and `off` when it is false. If `createhostuser_mode` is set, its setting will always be used instead of the `createhostuser` setting. If multiple roles matching a node specify the `createhostuser_mode` option with both `drop` and `keep`, teleport will default to `keep` Once `createhostuser` is to be removed, a role migration will be triggered and any roles including `createhostuser` will be migrated to use `createhostuser_mode` setting it to `drop` if `createhostuser` was set. ```yaml kind: role version: v5 metadata: name: auto-user-groups spec: options: createhostuser: true allow: logins: [

] ``` will be equivalent to: ```yaml kind: role version: v5 metadata: name: auto-user-groups spec: options: createhostuser_mode: drop allow: logins: [ "{{external.username}}" ] ``` ```yaml kind: role version: v5 metadata: name: auto-user-groups spec: options: createhostuser_mode: keep allow: logins: [ "{{external.username}}" ] ``` Multiple roles specify `createhostuser_mode`, teleport will default to `keep` ```yaml kind: role version: v5 metadata: name: auto-user-groups spec: options: createhostuser_mode: keep allow: logins: [ "{{external.username}}" ] ``` ```yaml kind: role version: v5 metadata: name: auto-user-groups-other spec: options: createhostuser_mode: drop allow: logins: [ "{{external.username}}" ] ``` This will require adding new traits to users -- `teleport.dev/uid` and `teleport.dev/gid`. These will be settable manually or automatically via an SSO provider attributes if one is setup. Creating a user with a specific GID requires that a group with that GID already exists, if it does not yet exist for the specified GID, a group with that GID will be created with the same name as the user logging in. Role configuration remains the same: ```yaml kind: role version: v5 metadata: name: auto-user-groups spec: options: createhostuser_mode: drop allow: logins: [ "{{internal.username}}" ] ``` ```yaml kind: user metadata: name: alex.mcgrath@goteleport.com spec: created_by: connector: id: okta identity: user@okta.com type: saml roles: editor access auditor saml_identities: connector_id: okta username: ... traits: teleport.dev/gid: "1239" teleport.dev/uid: "1239" ``` When set like this, the user created upon login will have the `--gid` and `--uid` options specified when calling `useradd` ```yaml kind: role version: v5 metadata: name: auto-user-groups spec: options: createhostuser: true allow: logins: [ "{{external.username}}" ] ``` ```yaml kind: role version: v5 metadata: name: auto-user-groups spec: options: createhostuser: true allow: host_groups: [ubuntu, docker, ...] logins: [ "{{external.username}}" ] ``` ```yaml kind: role version: v5 metadata: name: users-as-sudoers spec: options: createhostuser: true allow: host_groups: [wheel] host_sudoers: ["%wheel ALL=(ALL) NOPASSWD: ALL"] ``` ```yaml kind: role version: v5 metadata: name: specify-commands-as-sudoers spec: options: createhostuser: true allow: host_sudoers: ["{{internal.logins}} ALL = (root) NOPASSWD: /usr/bin/systemctl restart nginx.service"] ``` Include the below config for the Teleport node that should not allow automatic user creation: ```yaml ssh_service: enabled: "yes" disablecreatehost_user: true ``` Nodes where `diablecreatehost_user` is `false` will still be able to have users be automatically created. In the situation where a user has roles as below, the user would not be able to make use of automatically provisioning users as both roles do not enable `createhostuser`. ```yaml kind: role version: v5 metadata: name: allow-access-and-auto-create spec: options: createhostuser: true node_labels: 'env': 'example' ``` ```yaml kind: role version: v5 metadata: name: specify-commands-as-sudoers spec: options: node_labels: 'env': 'example' ```