- cftotalcontrol is a module for creating a special account environment with SSH access to other infrastructure sites and performing mass routine tasks in parallel.
- Abstracted from the implementation of the theory of the organization of safe and controlled access to infrastructure.
- Describes the practical application of a specific solution.
Of course, this article is not an exhaustive guide. However, for clarity, we consider a classic example of admin access to servers, in which each admin has a private key and direct access to any server controlled by him:
This approach has certain disadvantages:
For comparison, consider access with a conditional infrastructure administrator in the form of a domain group:
This approach is called differently, but somehow it has long existed in integrated commercial solutions. Usually this is implemented through a certain domain group of privileged users, which has access to all or part of infrastructure systems. This approach has some (2, 3 and 5) drawbacks of the previous one, plus an obvious nuance - the need for the constant availability of authentication and authorization services (of course, not without caching). By the way, it is not too difficult to organize something similar with the help of PAM and LDAP.
So, we quickly got to the core of the implemented access concept in cftotalcontrol
:
In essence, this approach combines the two previous ones:
This implies that the infrastructure is built on the previously considered cfnetwork
, cfauth
and cfpuppetserver
, but cftotalcontrol
will live perfectly without conflicts and in a mixed environment.
First of all, in order to sleep peacefully, it is better to have at least one SSH key, which will be registered on all systems through the cfauth
module, but which will not be used for "domestic" needs. Of course, you should not forget about access to the hardware via IPMI and to virtual machines via the serial / GUI console for an emergency.
Secondly, just look at the example and:
cftotalcontrol
module to Puppetfile
mod 'codingfuture/cftotalcontrol'
classes
list of all nodes ( common.yaml
file) classes: # , "" - cftotalcontrol::auth
classes
list of the node configuration with the control user (hereinafter referred to as the "control node") classes: # - cftotalcontrol
/opt/puppetlabs/bin/puppet agent --test
) in the following order:After these simple manipulations, a cftotalcontrol
will be created on the nodes with the cftotalcontrol
class with a specially sharpened Bash environment and SSH client configuration. It is strongly recommended to change the username to a non-standard user through the parameter cftotalcontrol::control_user
.
All standard admin keys from cfauth
will be cfauth
to this user, but in order to organize ideologically correct access, admin keys must be registered only in cftotalcontrol::ssh_auth_keys
. Of course, you should first check that everything works and there is access to all servers.
In a large infrastructure, almost always only a small part of the systems looks to the outside world and through them it is required to organize access to the other systems.
In an SSH client, this is easily implemented through the ProxyCommand
option with the value ssh -W target:port proxyhost
. This approach is more secure than using SSH Agent Forwarding, which allows you to steal the admin's private key on a remote system. In principle, knowledge of these technical details is not necessary to use the cftotalcontrol
module, since all necessary configuration is generated based on the cftotalcontrol::pool_proxy
.
Of course, the enumeration of the proxy node for each target node is not only inefficient, but also necessarily leads to frequent errors when adding new systems. Instead, the cf_location
and cf_location_pool
facts described in the previous sections are used for "navigation". Usually these facts are set upon initial installation by the client initialization script cf_gen_puppet_client_init
, but can be changed through the parameters of the cfsystem
module.
When generating the SSH client config, the proxy nodes are searched in the following order:
$cftotalcontrol::pool_proxy["$cf_location/$cf_location_pool"]
$cftotalcontrol::pool_proxy["$cf_location"]
$cftotalcontrol::pool_proxy["$certname"]
- yes, for exceptional cases, a loophole was left to indicate the proxy node based on the full name of the target node.Of course, the whole thing is integrated with cfnetwork
and without unnecessary gestures adds everything that is needed in the network filter configuration.
Typically, specific tasks of the same type need to be run only on nodes with certain attributes (OS, set of services, role, etc.). In order not to fence your garden by segregation of nodes, this is easily done through the parameter cftotalcontrol::host_groups
, which is an associative array, where the key is the name of the group, and the value can be a hard-coded list of node or string in the form of a Puppet DB query There is an opportunity to read in the description of the puppetdbquery module.
Example:
cftotalcontrol::host_groups: puppetserver: "Package['puppetserver']" infra: "cf_location_pool = 'infra'" custom: - 'web.example.com' - 'db.example.com'
It should be clear without further explanation:
cftotalcontrol::standard_commands: helloworld: 'echo "Hello world!"' gethostname: 'hostname --fqdn'
Here begins the virtual post admin. When you first log in, the system will kindly offer to generate a private key, and on subsequent runs, launch the SSH Agent and add a private key to it, asking for its password along the way.
But so that life does not seem honey, the system will remind you to update your private key if it is older than cftotalcontrol::ssh_old_key_days = 180
days. If you don’t even log in, cron will do the same, angrily sending out daily letters. You can generate a new key using the cftc_gen_key
command, which also automatically installs it on all monitored nodes, without requiring other actions. If something goes wrong, the old key can always be found in the ~/.ssh/
with the UNIX timestamp extension in seconds at the time the new key is generated. This may occur due to a connection error, Puppet configuration, or a banal offline-controlled system.
In general, the following is happening under the hood:
~/.bash_aliases
- the line with the connection ~/.cftotalcontrol_aliases
is necessarily present~/.cftotalcontrol_aliases
- all the magic of the Bash environment~/.ssh/cftotalcontrol_config
is a special SSH config with the correct users, ports and ProxyCommand
. Needless to say, the data is also pulled out of PuppetDB.~/.ssh/cftchostsall
- a list of all controlled nodes.~/.ssh/cftchosts_${grp}
- list of controlled nodes of a specific group.~/.ssh/cftc_id_${ssh_key_type}
- current private key.~/.ssh/cftc_id_${ssh_key_type}.${backup_timestamp}
are old private keys that are not registered anywhere in the normal case.Utility bash environment commands:
cftc_ssh
is the correct launch of SSH with all the necessary parameters.cftc_scp
- correct SCP launch with all necessary parameters.cftc_gen_key
- manual regeneration of a private key (automatically called when entering in the absence of a key).cftc_add_key
— Launch SSH Agent and add private key (automatically invoked upon login).cftc_check_old_key
- manual check of the old key (it is called automatically upon entry and daily on cron).Directly work with nodes:
ssh_${hostname} [$cmd]
- go to a specific node or run an arbitrary command on it interactively. Note: dots are replaced with underscores in ${hostname}
ssh_${hostname}_{stdcmd} [args]
- run one of the standard commands on a specific node.ssh_masscmd {cmd}
- sequentially run {cmd}
on all nodes in interactive mode.ssh_mass_{stdcmd} [args]
- sequentially run one of the standard commands on all nodes in interactive mode.pssh_masscmd {cmd}
- run {cmd}
in parallel on all nodes.pssh_mass_{stdcmd} [args]
- run in parallel one of the standard commands on all nodes.sshgrp_{group}_*
and psshgrp_{group}_*
are the same as the previous "bulk", but for a limited named node group.Significant environment variables:
PSSH_COUNT=$cftotalcontrol::parallel
- the maximum number of concurrent calls. It is worth remembering that a large load will go to the proxy nodes and connections can be hacked up using the MaxStartups option. Unfortunately, the approach with the ControlMaster does not justify itself with a large number of connections, since multiplexing works rather mediocre - it is more suitable for accelerating the work of successive calls.PSSH_OPTS=-i
- additional parameters for parallel-ssh
(pssh)SSH_OPTS=
- advanced options for ssh
SCP_OPTS=
- advanced parameters for scp
The standard commands are the same as those added to cfauth
for calling through sudo
without a password:
aptupdate
- sudo /usr/bin/apt-get update
aptdistupgrade
- sudo DEBIAN_FRONTEND=noninteractive /usr/bin/apt-get dist-upgrade -o Dpkg::Options::="--force-confold" -qf
aptautoremove
- sudo DEBIAN_FRONTEND=noninteractive /usr/bin/apt-get autoremove
puppetdeploy
- sudo /opt/puppetlabs/puppet/bin/puppet agent --test
pssh_mass_aptupdate
, psshgrp_grpname_aptdistupgrade -sy
, ssh_host_example_com_puppetdeploy
Sooner or later, certain admin powers need to be given to people. whose area of responsibility is not the administration of the entire infrastructure. These include DevOps, DBA, Release Manager, and others. Some clustering tools also rely on SSH access to fellow nodes, which is conveniently configured by the same module, including automatic generation of a private key without a password.
In short, the standard way to create unprivileged admins is through the parameter cftotalcontrol::extra_users
, which correctly creates resources like cftotalcontrol::admin
. Specific differences from the user of "total" control:
There remains only the question of how to designate the target node. This is done via the cftotalcontrol::auth::control_scope
. You can hang several spheres on the same node at once. Example:
cftotalcontrol::auth::control_scope: - web - devops
cftotalcontrol
module cftotalcontrol
cftotalcontrol
classpool_proxy = {}
. Pairs key => "name.proxy.node". Key format:control_user = 'cftcuser'
is the name of the controlling user.control_home = undef
- home folder. Default: /home/$control_user
.host_groups = {}
- definition of host_groups = {}
groups for commands of type (p)sshgrp_*
. The key is the name of the group. Value:parallel = 10
- the number of parallel SSH calls.standard_commands = {}
- standard routine commands to add to the list.ssh_key_type = 'rsa'
is a private key type. It is also worth paying attention to the new type of 'ed25519'.ssh_key_bits = 4096
- the length of the private key, is ignored for ed25519.autogen_ssh_key = false
- automatically generate a private key without a password (not worth it for "total" control).ssh_old_key_days = 180
- the age of the private key after which, the system starts crying in cron and when entering the account.ssh_auth_keys = undef
- additional user access keys besides those specified in cfauth
extra_users = undef
- additional users of limited access to the infrastructure => cftotalcontrol::admin
cftotalcontrol::auth
control_scope = []
- a string or an array of strings with restricted access zone names that apply to this systemcftotalcontrol::admin
Usually initialized via cftotalcontrol::extra_users
. All parameters are the same as for cftotalcontrol
, except for extra_users
itself.
control_scope = undef
- name of the restricted area, if applicable. When created via extra_users
matches the user's name. If not specified, a user with unlimited access is created.Source: https://habr.com/ru/post/279375/
All Articles