SSH: Setting Env Variables Without SendEnv - A Quick Guide

by Andrew McMorgan 59 views

Hey guys! Ever found yourself in a situation where you needed to set environment variables within an SSH session but couldn't use SendEnv? It's a common issue, especially when dealing with shared user accounts or specific security configurations. Let's dive into how you can achieve this, making your life a whole lot easier. We'll explore various methods, focusing on practical solutions and real-world scenarios. So, buckle up and let's get started!

Understanding the Challenge: Why No SendEnv?

First off, let's quickly address why you might not be able to use SendEnv. In many corporate or secured environments, the SendEnv directive in the SSH client configuration is often disabled for security reasons. This is because allowing clients to send arbitrary environment variables can open up potential security vulnerabilities. Think of it like this: if any client can set any environment variable, malicious actors could potentially inject harmful settings, compromising the server's security. So, while SendEnv is a convenient way to pass environment variables, it's not always the safest or most viable option.

The core issue we're tackling is how to maintain user-specific configurations in a shared environment. Imagine a scenario where multiple admins are using the same shared account to manage servers. Each admin might have their own preferences, tools, and workflows. Setting environment variables allows you to tailor the environment to each user's needs, even when they're all logging in under the same account. This is where the challenge lies: how do you differentiate these sessions without the standard SendEnv method?

To effectively address this, we need to explore alternative methods that are secure, reliable, and easy to implement. We'll look at approaches that range from modifying the .bashrc file to leveraging SSH configurations and even using scripting techniques. The goal is to find a solution that fits your specific needs and constraints, ensuring a smooth and secure workflow for everyone involved. So, keep reading, and let's explore these options together!

Method 1: Leveraging .bashrc and SSH Keys

The first method we'll explore involves a combination of .bashrc modifications and leveraging SSH keys. This approach is particularly useful when you have a shared user account for administrative tasks, and you want to differentiate sessions based on the user's SSH key. The idea here is to use an environment variable to hold the initiator of the SSH session, allowing your .bashrc to execute user-dependent configurations.

Setting the Stage: SSH Keys

Before diving into the .bashrc modifications, let's quickly recap SSH keys. SSH keys provide a secure way to authenticate to a server without using passwords. Each user has a private key (which they keep secret) and a public key (which is placed on the server). When a user connects to the server, SSH uses these keys to verify the user's identity. This method is far more secure than password-based authentication and is a recommended practice for managing SSH access. So, make sure each user who needs access to the shared account has their own SSH key pair.

Modifying .bashrc

The heart of this method lies in the .bashrc file. This file is executed every time a new interactive, non-login shell is started. By adding some logic to your .bashrc, you can set environment variables based on who is connecting. Here's a basic outline of how you can do it:

  1. Identify the SSH Key: When a user connects via SSH, the SSH_CONNECTION environment variable is set. This variable contains information about the connection, including the client's IP address and port. However, it doesn't directly tell you which user is connecting. This is where SSH keys come in handy. You can configure your SSH server to set an environment variable based on the key used for authentication.

  2. Configure authorized_keys: In the authorized_keys file (located in the .ssh directory of the shared user's home directory), you can add the environment option to set an environment variable when a specific key is used. For example:

    environment="SSH_INITIATOR=user1" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC...
    environment="SSH_INITIATOR=user2" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC...
    

    Here, user1 and user2 are identifiers for different users, and the long string starting with AAAAB3 is the user's public key. When user1 connects using their key, the SSH_INITIATOR environment variable will be set to user1.

  3. Use in .bashrc: Now, in your .bashrc file, you can use this variable to set other environment variables or execute user-specific commands:

    if [ -n "$SSH_INITIATOR" ]; then
        echo "SSH session initiated by: $SSH_INITIATOR"
        # Set user-specific environment variables
        if [ "$SSH_INITIATOR" = "user1" ]; then
            export EDITOR="vim"
        elif [ "$SSH_INITIATOR" = "user2" ]; then
            export EDITOR="nano"
        fi
    fi
    

    This snippet checks if SSH_INITIATOR is set (meaning the session was initiated via SSH with a key that set this variable). Then, based on the value of SSH_INITIATOR, it sets the EDITOR environment variable differently for user1 and user2. This is just a simple example; you can extend this to customize the environment in many ways.

Advantages and Considerations

This method provides a secure and flexible way to differentiate SSH sessions. It leverages the security of SSH keys and allows for fine-grained control over the environment. However, it requires managing the authorized_keys file and ensuring that each user has their key configured correctly. Additionally, if a user connects without using their key (e.g., via password authentication if it's enabled), the SSH_INITIATOR variable won't be set, and the .bashrc won't be able to differentiate the session. So, it's essential to enforce key-based authentication for this method to work reliably.

Method 2: Using SSH Configuration Files

Another powerful way to set environment variables in SSH sessions without relying on SendEnv is by using SSH configuration files. These files allow you to define settings for SSH connections, including the ability to execute commands upon connection. This method is particularly useful for setting global or user-specific environment variables that should always be present in SSH sessions.

The Power of SSH Config Files

SSH configuration files provide a flexible way to customize SSH behavior. There are two main types of SSH config files:

  • Global Configuration: Located at /etc/ssh/ssh_config (for client-side settings) and /etc/ssh/sshd_config (for server-side settings). These files affect all users and connections on the system.
  • User Configuration: Located at ~/.ssh/config (for client-side settings) and ~/.ssh/authorized_keys (for server-side settings related to key-based authentication). These files affect only the user who owns them.

For our purpose of setting environment variables, we'll primarily focus on the server-side configuration, specifically the authorized_keys file and the sshd_config file.

Setting Environment Variables in authorized_keys

As we touched on in the previous method, the authorized_keys file allows you to specify options for each SSH key. One of these options is the environment directive, which lets you set environment variables when a specific key is used to authenticate. Here's how it works:

  1. Open authorized_keys: Log in to the shared user account and open the ~/.ssh/authorized_keys file in a text editor.

  2. Add the environment option: For each user's public key, add the environment option followed by the variable you want to set. For example:

    environment="USER_ROLE=admin" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC... user1@example.com
    environment="USER_ROLE=developer" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC... user2@example.com
    

    In this example, we're setting the USER_ROLE environment variable to admin for user1 and developer for user2. The ssh-rsa string indicates the key type, followed by the actual public key, and an optional comment (e.g., user1@example.com).

  3. Restart SSH Service (if needed): In some cases, you might need to restart the SSH service for the changes to take effect. This depends on your system's configuration and how it handles SSH configuration updates. Usually, you can restart the service using a command like sudo systemctl restart sshd or sudo service sshd restart.

Using ForceCommand in authorized_keys

Another powerful option in authorized_keys is ForceCommand. This directive allows you to specify a command that will be executed whenever a user logs in using a particular key. You can use ForceCommand to set environment variables or perform other actions before the user's shell is started. Here's an example:

ForceCommand /usr/local/bin/ssh-env-setup

In this case, whenever a user logs in using the key associated with this line, the /usr/local/bin/ssh-env-setup script will be executed. This script can then set environment variables or perform other setup tasks. Let's look at a simple example of what this script might contain:

#!/bin/bash

# Set environment variables
export CUSTOM_VAR="some_value"

# Start the user's shell
exec bash

This script sets the CUSTOM_VAR environment variable and then starts the user's default shell (bash in this case). The exec bash command replaces the script process with the shell process, ensuring that the user gets a normal interactive shell.

Advantages and Considerations

Using SSH configuration files provides a robust and flexible way to manage environment variables in SSH sessions. It allows you to set variables globally or on a per-user basis, and it integrates seamlessly with SSH key-based authentication. However, it requires careful management of the configuration files, especially authorized_keys, as incorrect entries can lock users out of the system. Additionally, the ForceCommand option should be used with caution, as it can restrict what users can do in their SSH sessions if not configured properly.

Method 3: Scripting Solutions and Environment Wrappers

For those seeking a more dynamic and flexible approach, scripting solutions and environment wrappers offer a powerful way to manage environment variables in SSH sessions. This method involves creating scripts that set up the environment before the user's shell is started, allowing for complex logic and customization.

The Power of Scripting

Scripting provides a high degree of control over the environment setup process. You can use scripts to set environment variables based on various factors, such as the user's identity, the time of day, or the system's current state. This level of flexibility is particularly useful in complex environments where static configurations are not sufficient.

Creating an Environment Wrapper

The basic idea behind an environment wrapper is to create a script that sets the necessary environment variables and then starts the user's shell. This script acts as a