sudo_pair
Plugin for sudo that requires another human to approve and monitor privileged sudo sessions
Top Related Projects
Lynis - Security auditing tool for Linux, macOS, and UNIX-based systems. Assists with compliance testing (HIPAA/ISO27001/PCI DSS) and system hardening. Agentless, and installation optional.
A tool for secrets management, encryption as a service, and privileged access management
The easiest, and most secure way to access and protect all of your infrastructure.
OpenVPN is an open source VPN daemon
Quick Overview
Sudo_pair is a plugin for the sudo command that requires a second person to approve and monitor privileged sudo sessions. It enhances security by implementing the four-eyes principle, ensuring that sensitive operations are overseen by an additional authorized user.
Pros
- Improves security by requiring two-person authorization for privileged actions
- Provides real-time monitoring of sudo sessions
- Helps prevent accidental or malicious misuse of privileged access
- Integrates seamlessly with existing sudo infrastructure
Cons
- Requires additional setup and configuration
- May slow down operations that require frequent sudo usage
- Depends on the availability of a second authorized user
- Could potentially be bypassed if both users collude
Code Examples
// Example 1: Basic configuration in /etc/sudo.conf
Plugin sudo_pair sudo_pair.so
// Example 2: Configuring approved pairs in /etc/sudo_pair.conf
user1 user2
user3 user4,user5
// Example 3: Exempting specific commands from pairing
Defaults!EXEMPTED_COMMAND unpair
Getting Started
-
Install sudo_pair:
git clone https://github.com/square/sudo_pair.git cd sudo_pair make sudo make install
-
Add the following line to
/etc/sudo.conf
:Plugin sudo_pair sudo_pair.so
-
Configure approved pairs in
/etc/sudo_pair.conf
:user1 user2 user3 user4,user5
-
Restart the sudo service or reboot the system to apply changes.
Competitor Comparisons
Lynis - Security auditing tool for Linux, macOS, and UNIX-based systems. Assists with compliance testing (HIPAA/ISO27001/PCI DSS) and system hardening. Agentless, and installation optional.
Pros of Lynis
- Comprehensive security auditing tool for Unix/Linux systems
- Extensive checks covering various security aspects
- Active development and regular updates
Cons of Lynis
- More complex setup and usage compared to sudo_pair
- Requires root access for full functionality
- May generate false positives in some cases
Code Comparison
Lynis (shell script):
#!/bin/sh
# Lynis - Security auditing and system hardening for Unix/Linux systems
# Copyright 2007-2013, Michael Boelen (michael.boelen@cisofy.com)
# Web site: https://cisofy.com/lynis/
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
sudo_pair (Rust):
#[macro_use]
extern crate failure;
#[macro_use]
extern crate sudo_plugin;
use sudo_plugin::prelude::*;
Key Differences
- Lynis is a comprehensive security auditing tool, while sudo_pair focuses on pair programming for sudo commands
- Lynis is written in shell script, whereas sudo_pair is implemented in Rust
- Lynis performs system-wide checks, while sudo_pair operates specifically on sudo command execution
A tool for secrets management, encryption as a service, and privileged access management
Pros of Vault
- Comprehensive secret management solution with advanced features like dynamic secrets and encryption as a service
- Highly scalable and designed for enterprise-level deployments
- Extensive documentation and community support
Cons of Vault
- More complex setup and configuration compared to sudo_pair
- Requires additional infrastructure and resources to run effectively
- Steeper learning curve for users and administrators
Code Comparison
sudo_pair (Ruby):
def pair!
if !env_var_set? && !ssh_connection? && !allowed_without_pair?
$stderr.puts "sudo: This command requires a pair!"
exit(1)
end
end
Vault (Go):
func (c *Core) unsealInternal(ctx context.Context, key []byte) error {
if c.Sealed() {
return nil
}
// Attempt to decrypt the master key
unlocked, err := c.barrier.Unseal(key)
if err != nil {
return err
}
if !unlocked {
return nil
}
// ... (additional code)
}
The code snippets demonstrate the different focus areas of the two projects. sudo_pair is centered around pair programming enforcement, while Vault deals with complex cryptographic operations for secret management.
The easiest, and most secure way to access and protect all of your infrastructure.
Pros of Teleport
- Comprehensive access management solution for servers, databases, and applications
- Supports multiple protocols (SSH, Kubernetes, databases) and cloud environments
- Offers advanced features like session recording and auditing
Cons of Teleport
- More complex setup and configuration compared to sudo_pair
- Requires additional infrastructure and resources to run
- May be overkill for simple sudo access control scenarios
Code Comparison
sudo_pair (Ruby):
def start_pair_session
spawn_pair_terminal
wait_for_pair
grant_access
end
Teleport (Go):
func (s *Server) StartSSHSession(ctx context.Context, req *proto.SSHSessionRequest) (*proto.SSHSessionResponse, error) {
// Implementation for starting an SSH session
}
Key Differences
- sudo_pair focuses specifically on sudo access control, while Teleport is a broader access management platform
- Teleport offers more extensive features and integrations, but sudo_pair is simpler and easier to implement for basic sudo pairing
- sudo_pair is written in Ruby, while Teleport is primarily written in Go
- Teleport requires a dedicated server infrastructure, whereas sudo_pair can be installed directly on target systems
Use Cases
- sudo_pair: Ideal for organizations needing simple sudo access control and pairing
- Teleport: Better suited for larger enterprises requiring comprehensive access management across various systems and protocols
OpenVPN is an open source VPN daemon
Pros of openvpn
- Widely adopted and mature VPN solution with extensive documentation
- Supports a variety of platforms and operating systems
- Offers robust security features and encryption protocols
Cons of openvpn
- More complex setup and configuration process
- Requires additional infrastructure for deployment
- May have higher resource usage compared to simpler solutions
Code Comparison
openvpn configuration example:
port 1194
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key
dh dh2048.pem
sudo_pair configuration example:
Sudo::Pair.configure do |config|
config.user_pair_whitelist = %w[alice bob]
config.command_blacklist = %w[reboot shutdown]
end
Summary
While openvpn is a comprehensive VPN solution for secure network access, sudo_pair focuses on enhancing sudo command security through pair programming. openvpn offers broader network-level protection, but sudo_pair provides a simpler, targeted approach to improving system administration security. The choice between them depends on specific security needs and infrastructure requirements.
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
sudo_pair
sudo_pair
is a plugin for sudo that requires another
human to approve and monitor privileged sudo sessions.
About
sudo
is used by engineers daily to run commands as privileged users.
But on some sensitive systems, you really want to ensure that no
individual can act entirely autonomously. At Square, this includes
applications that manage our internal access-control systems, store
accounting ledgers, or even move around real money. This plugin allows
us to ensure that no user can act entirely on their own authority within
these systems.
This plugin and its components are still in prerelease, as we want to get feedback from the open-source community before officially releasing 1.0.
Installation
WARNING: Misconfiguring sudo can lock you out of your machine. Test this in a throwaway environment.
For now, sudo_pair
must be compiled from source. It is a standard
Rust project, and the following should suffice to build it on any recent
version of Rust:
git clone https://github.com/square/sudo_pair.git
cd sudo_pair
cargo build --release
Once built, the plugin itself will need to be installed in a place where
sudo
can find it. Generally this is under /usr/libexec/sudo
(on
macOS hosts it's /usr/local/libexec/sudo
). An appropriate approval
script must be installed into the PATH
. A directory must be created
for sudo_pair
to manage the sockets it uses for communication between
plugin and client. And finally, sudo
must be configured to load and
use the plugin.
# WARNING: these files may not be set up in a way that is suitable
# for your system. Proceed only on a throwaway host.
# install the plugin shared library
install -o root -g root -m 0644 ./target/release/libsudopair.dylib /usr/libexec/sudo
# create a socket directory
install -o root -g root -m 0644 -d /var/run/sudo_pair
# install the approval script; as currently configured, it denies access
# to users approving their own sudo session and may lock you out
install -o root -g root -m 0755 ./sample/bin/sudo_approve /usr/bin/sudo_approve
# your `/etc/sudo.conf` may already have entries necessary for sudo to
# function correctly; if this is the case, the two files will need to be
# merged
install -o root -g root -m 0644 ./sample/etc/sudo.conf /etc/sudo.conf
# if these prompts don't work for you, they're configurable via a simple
# templating language explained later in the README
install -o root -g root -m 0644 ./sample/etc/sudo.prompt.user /etc/sudo.prompt.user
install -o root -g root -m 0644 ./sample/etc/sudo.prompt.pair /etc/sudo.prompt.pair
This only places the plugin files into their expected locations. The plugin will not be enabled yet until you follow the configuration steps below.
Configuration
/etc/sudoers
By default, /etc/sudoers
will not tell logging plugins to log output for
any commands. You will need to enable this by either telling sudo
to enable
logging for all commands (and opt out any commands you wish to bypass pairing
for) or by opting individual commands into logging.
Example (default to log, opt out of individual commands):
Defaults log_output
%wheel ALL = (ALL) NOLOG_OUTPUT: /bin/cat, /bin/ls
Example (opt into individual commands)
%wheel ALL = (ALL) LOG_OUTPUT: /usr/bin/visudo
/etc/sudo.conf
The plugin can be provided several options to modify its behavior. These
options are provided to the plugin by adding them to the end of the
Plugin
line in /etc/sudo.conf
.
Example:
Plugin sudo_pair sudo_pair.so socket_dir=/var/tmp/sudo_pair gids_exempted=42,109
The full list of options are as follows:
-
binary_path
(default:/usr/bin/sudo_approve
)This is the location of the approval binary. The approval command itself needs to run under the privileges of the destination user or group, and this is done so using sudo, so it must be exempted from requiring its own pair approval.
-
user_prompt_path
(default:/etc/sudo_pair.prompt.user
)This is the location of the prompt template to display to the user invoking sudo; if no template is found at this location, an extremely minimal default will be printed. See the Prompts section for more details.
-
pair_prompt_path
(default:/etc/sudo_pair.prompt.pair
)This is the location of the prompt template to display to the user being asked to approve the sudo session; if no template is found at this location, an extremely minimal default will be printed. See the Prompts section for more details.
-
socket_dir
(default:/var/run/sudo_pair
)This is the path where this plugin will store sockets for sessions that are pending approval. This directory must be owned by root and only writable by root, or the plugin will abort.
-
gids_enforced
(default:0
)This is a comma-separated list of gids that sudo_pair will gate access to. If a user is
sudo
ing to a user that is a member of one of these groups, they will be required to have a pair approve their session. -
gids_exempted
(default: none)This is a comma-separated list of gids whose users will be exempted from the requirements of sudo_pair. Note that this is not the opposite of the
gids_enforced
flag. Whereasgids_enforced
gates access to groups,gids_exempted
exempts users sudoing from groups. For instance, this setting can be used to ensure that oncall sysadmins can respond to outages without needing to find a pair.Note that root is always exempt.
Prompts
This plugin allows you to configure the prompts that are displayed to
both users being asked to find a pair and users being asked to approve
another user's sudo
session. If prompts aren't
configured (or can't be found on the filesystem),
extremely minimal ones are provided as a default.
The contents of the prompt files are raw bytes that should be printed to the user's terminal. This allows fun things like terminal processing of ANSI escape codes for coloration, resizing terminals, and setting window titles, all of which are (ab)used in the sample prompts provided.
These prompts also implement a simple %
-escaped
templating language. Any known directive preceded by a %
character is
replaced by an expansion, and anything else is treated as a literal
(e.g., %%
is a literal %
, and %a
is a literal a
).
Available expansions:
%b
: the name of the appoval _b_inary%B
: the full path to the approval _B_inary%C
: the full _C_ommandsudo
was invoked as (recreated as best-effort)%d
: the cw_d_ of the command being run undersudo
%h
: the _h_ostname of the machinesudo
is being executed on%H
: the _H_eight of the invoking user's terminal, in rows%g
: the real _g_id of the user invokingsudo
%p
: the _p_id of thissudo
process%u
: the real _u_id of the user invokingsudo
%U
: the _U_sername of the user runningsudo
%W
: the _W_idth of the invoking user's terminal, in columns
Approval Scripts
The provided approval script is just a small
(but complete) example. As much functionality as possible has been moved
into the plugin, with one (important, temporary) exception: currently,
the script must verify that the user approving a sudo
session is not
the user who is requesting the session.
Other than that, the only thing required of the "protocol" is to:
- connect to a socket (as either the user or group being
sudo
ed to) - wire up the socket's input and output to the user's STDIN and STDOUT
- send a
y
to approve, or anything else to decline - close the socket to terminate the session
As it turns out, you can pretty much just do this with socat
:
socat STDIO /path/to/socket
The script included with this project isn't much more than this. It
performs a few extra niceties (implicitly sudo
s if necessary, turns
off terminal echo, disables Ctrl-C, and kills the session on Ctrl-D),
but not much more. Ctrl-C was disabled so a user who's forgotten that
this terminal is being used to monitor another user's session doesn't
instinctively kill it with Ctrl-C.
Limitations
Sessions under sudo_pair
can't be piped to.
Allowing piped data to standard input, as far as I can tell, likely
results in a complete bypass of the security model here. Commands can
often accept input on stdin
, and there's no reasonable way to show
this information to the pair.
Security Model
This plugin allows users to sudo -u ${user}
to become a user or
sudo -g ${group}
to gain an additional group.
When a user does this, a socket is created that is owned and only
writable by ${user}
(or ${group}
). In order to connect to that
socket, the approver must be able to write to files as that ${user}
(or ${group}
). In other words, they need to be on the other side of
the airtight hatchway. In practical terms, this
means the approver needs to also be able to sudo
to that user or
group.
To facilitate this, the plugin exempts the approval script from the
requirement to have a pair. And the sample approval script automatically
detects the user or group you need to become and runs sudo -u ${user}
(or sudo -g ${group}
) implicitly.
As a concrete example, these are the sockets opened for sudo -u root
,
sudo -u nobody
, and sudo -g sys
:
drwxr-xr-x 3 root wheel 96 May 8 09:17 .
s-w------- 1 root wheel 0 May 8 09:16 1882.29664.sock # sudo -u root
s-w------- 1 nobody wheel 0 May 8 09:17 1882.29921.sock # sudo -u nobody
s----w---- 1 root sys 0 May 8 09:18 1882.29994.sock # sudo -g sys
The only people who can approve a sudo
session to a user or group must
also be able to sudo
as that user or group.
Due to limitations of the POSIX filesystem permission model, a user may sudo to a new user (and gain its groups) or sudo to a new group (preserving their current user), but not both simultaneously.
Project Layout
This project is composed of three Rust crates:
sudo_plugin-sys
: raw Rust FFI bindings to thesudo_plugin(8)
interfacesudo_plugin
: a set of Rust structs and macros to simplify writing pluginssudo_pair
: the implementation of this plugin
Dependencies
Given the security-sensitive nature of this project, it is an explicit goal to have a minimal set of dependencies. Currently, those are:
Contributions
Contributions are welcome! This project should hopefully be small (~500loc for the plugin itself, ~1kloc for the wrappers around writing plugins) and well-documented enough for others to participate without difficulty.
Pick a TODO and get started!
Bugs
Please report non-security issues on the GitHub tracker. Security issues are covered by Square's bug bounty program.
License
sudo_pair
is distributed under the terms of the Apache License
(Version 2.0).
See LICENSE-APACHE for details.
Top Related Projects
Lynis - Security auditing tool for Linux, macOS, and UNIX-based systems. Assists with compliance testing (HIPAA/ISO27001/PCI DSS) and system hardening. Agentless, and installation optional.
A tool for secrets management, encryption as a service, and privileged access management
The easiest, and most secure way to access and protect all of your infrastructure.
OpenVPN is an open source VPN daemon
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot