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

Improvements to Teleport PAM support. #3317

Merged
merged 7 commits into from
Feb 6, 2020
Merged

Improvements to Teleport PAM support. #3317

merged 7 commits into from
Feb 6, 2020

Conversation

russjones
Copy link
Contributor

@russjones russjones commented Jan 30, 2020

Description

Added ability to read in PAM environment variables from PAM handle and pass environment variables to PAM module TELEPORT_USERNAME, TELEPORT_LOGIN, and TELEPORT_ROLES.

Refactored launching of shell to call PAM first. This allows a PAM module to create the user and home directory before attempting to launch a shell for said user.

To do this the command passed to Teleport during re-exec has changed. Before the Teleport master process would resolve the user fully (UID, GUID, supplementary groups, shell, home directory) before re-launching itself to then launch a shell. However, if PAM is used to create the user on the fly and PAM has not been called yet, this will fail.

Instead that work has now been pushed to occur in the child process. This means the Teleport master process now creates a payload with the minimum needed from *srv.ServerContext and will then re-exec itself. The child process will call PAM and then attempt to resolve the user (UID, GUID, supplementary groups, shell, home directory).

Examples

Using pam_exec.so

Using pam_exec.so is the easiest way to use the PAM stack to create a user if the user does not already exist. The advantage of using pam_exec.so is that it usually ships with the operating system. The downside is that it doesn't provide access to some additional environment variables that Teleport sets (see the pam_script.so example for those) to use additional identity metadata in the user creation process.

You can either add pam_exec.so to your existing PAM stack for your application or write a new one for Teleport. In this example we'll write a new one to simplify how to use pam_exec.so with Teleport.

Start by creating a file /etc/pam.d/teleport with the following contents.

account   required   pam_exec.so /etc/pam-exec.d/teleport_acct
session   required   pam_motd.so

Note the inclusion of pam_motd.so under the session facility. While pam_motd.so is not required for user creation, Teleport requires a module set for both the account and session facility to work.

Next create the script that will be run by pam_exec.so like below. This script will check if the user passed in PAM_USER exists and if it does not, it will create it. Any error from useradd will be written to /tmp/pam.error.

mkdir -p /etc/pam-exec.d
cat > /etc/pam-exec.d/teleport_acct <<EOF
#!/bin/sh
id -u "${PAM_USER}" &>/dev/null  || /sbin/useradd -m "${PAM_USER}" 2> /tmp/pam.error
exit 0
EOF
chmod +x /etc/pam-exec.d/teleport_acct

Next update /etc/teleport.yaml to call the above PAM stack by both enabling PAM and setting the service_name.

ssh_service:
   pam:
     enabled: yes
     service_name: "teleport"

Now attempting to login as an existing user should result in the creation of the user and successful login.

Using pam_script.so

If more advanced functionality is needed pam_script.so is a good choice. It typically has to be installed from packages but richer scripts with more identity information from Teleport can be used during the process of user creation.

To start install pam_script.so. On Debian based systems this would be apt-get install libpam-script and on RHEL based systems yum install pam-script.

You can either add pam_script.so to your existing PAM stack for your application or write a new one for Teleport. In this example we'll write a new one to simplify how to use pam_script.so with Teleport.

Start by creating a file /etc/pam.d/teleport with the following contents.

account   required   pam_script.so
session   required   pam_motd.so

Note the inclusion of pam_motd.so under the session facility. While pam_motd.so is not required for user creation, Teleport requires a module set for both the account and session facility to work.

Next create the script that will be run by pam_script.so like below. This script will check if the user passed in TELEPORT_LOGIN exists and if it does not, it will create it. Any error from useradd will be written to /tmp/pam.error. Note the additional environment variables TELEPORT_USERNAME, TELEPORT_ROLES, and TELEPORT_LOGIN. These can be used to write richer scripts that may change the system in other ways based off identity information.

mkdir -p /etc/pam-script.d
cat > /etc/pam-script.d/teleport_acct <<EOF
#!/bin/sh
COMMENT="User ${TELEPORT_USERNAME} with roles ${TELEPORT_ROLES} created by Teleport."
id -u "${TELEPORT_LOGIN}" &>/dev/null  || /sbin/useradd -m -c "${COMMENT}" "${TELEPORT_LOGIN}" 2> /tmp/pam.error
exit 0
EOF
chmod +x /etc/pam-script.d/teleport_acct

Next update /etc/teleport.yaml to call the above PAM stack by both enabling PAM and setting the service_name.

ssh_service:
   pam:
     enabled: yes
     service_name: "teleport"

Now attempting to login as an existing user should result in the creation of the user and successful login.

Related Issues

Fixes #3270
Fixes #3021
Fixes #2863

Copy link
Contributor

@webvictim webvictim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM in theory with a few nits

Copy link
Contributor

@fspmarshall fspmarshall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pam_teleport.so is being tracked. This is probably unintended.

Added method that reads in PAM environment variables from PAM handle.
Added ability to pass additional metadata about the user to PAM modules
through the PAM_RUSER field.
Refactored launching of shell to call PAM first. This allows a PAM
module to create the user and home directory before attempting to launch
a shell for said user.

To do this the command passed to Teleport during re-exec has changed.
Before the Teleport master process would resolve the user fully (UID,
GUID, supplementary groups, shell, home directory) before re-launching
itself to then launch a shell. However, if PAM is used to create the
user on the fly and PAM has not been called yet, this will fail.

Instead that work has now been pushed to occur in the child process.
This means the Teleport master process now creates a payload with the
minimum needed from *srv.ServerContext and will then re-exec itself. The
child process will call PAM and then attempt to resolve the user (UID,
GUID, supplementary groups, shell, home directory).
Added support for "pam_putenv" and "pam_get_item" to fetch PAM_RUSER to
pam_teleport.so. This is used for test coverage.
Don't call os.Exit() from RunCommand() as any defers won't be called.
Instead wrap RunCommand() in RunAndExit() to allow defers to be called.
@russjones russjones merged commit 61ffec8 into master Feb 6, 2020
@russjones russjones deleted the rjones/pam-cgo branch February 6, 2020 19:15
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