Mudando todas as senhas de uma rede Linux heterogênea

Me deparei esses dias com o seguinte problema: alterar as senhas de um grupo de servidores ao mesmo tempo. De inicio parece um problema simples, mas depois vimos que havia o problema dos certificados de autenticação com o que alguns usuários entravam nos servidores e para piorar, alguns servidores precisam se comunicar entre eles e por se fosse pouco, o gestor queria aproveitar para limpar os certificados de acesso para deixar só o mínimo necessários.

Requisitos mínimos

Bom, se há um mínimo necessário -pensei- é por ai que começaremos. Desenvolvi um script que faço aqui publico tendo como ponto de partida duas coisas: Uma lista de servidores e um conjunto dos certificados mínimos que é necessário para garantir que certos usuários possam acessar o conjunto de servidores.

Para poder rodar o script, você precisa ter o netcat instalado em sua máquina assim como acesso certificado aos servidores em questão (no nosso caso mais de 7 servidores usando CentOS, Redhat, Debian e Ubuntu).

Instalar o netcat se resume a puxar ele do repositório. Por exemplo, em Ubuntu fica assim:

sudo apt-get install nc

Para certificar-se perante os servidores, você primeiro cria um par de chaves assim:

ssh-key-gen

E mande enter em tudo

Depois você copia sua chave para os servidores como no seguinte exemplo:

ssh-copy-id root@192.168.0.9

Isso supondo que se trata do servidor com ip 192.168.0.9 e o usuário root. Falando nisso, sem acesso root aos servidores, nada feito.

Repita esta última operação para cada servidor da sua rede.

Depois crie uma pasta na qual colocará o script que está no final deste post.

Além do script, crie um arquivo chamado newPassword dentro da pasta contendo unicamente a nova senha.

Também crie um arquivo chamado servers.txt contendo a lista dos IPs dos seus servidores.

Crie um arquivo authorized_keys nessa pasta contendo as chaves públicas que você deseja permitir acesso em todos os servidores da lista. Ou seja, em cada linha deste arquivo vá sua chave pública, a chave do seu colega, do seu chefe, e assim por diante.

Garanta direitos de execução ao script assim:

chmod +x updateServerPasswords.sh

E finalmente rode o script.

./updateServerPasswords.sh

Como funciona

O scrips percorrera a lista de IPs, verificará o tipo de servidor que é (a linhagem, na realidade) e se lhe for possível (redhat e debian) alterará a senha do root para a indicada. Recolherá a chave pública desse servidor para disponibilizá-la ao grupo de servidores. Dessa forma, eles passam a se conhecer e não precisam de senha.

Cria um arquivo temporário authorized_keys contendo os certificados liberados para os usuários mais os certificados de cada servidor da lista.

Finalmente. Coloca o novo authorized_keys em cada servidor. Limpa a entrada correspondente a cada servidor substituindo-as pelas novas.

 O script

#!/bin/bash
#
# The MIT License (MIT)
#
# Copyright (c) 2015 Esteban Daniel Dortta
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

function checkPort
{
    nc -z $1 $2
    if [ $? -lt 1 ]; then
      echo 1
    else
      echo 0
    fi
}

if [ ! -d ssh-backup ]; then
  mkdir ssh-backup
fi

echo "~/.ssh/known_hosts" > /tmp/remove_known_hosts.sh

known=''
winHosts=''

if [ $# -lt 1 ]; then
  serverList=`(cat servers.txt)`
else
  if [ -f "$1" ]; then
    serverList=`(cat "$1")`
  else
    serverList=$1
  fi
fi
for ip in $serverList; do
  ping -c 1 $ip > /dev/null
  ret=$?
  ret=`(echo $ret | awk '{ print $1 }')`
  if [ $ret -gt 0 ]; then
    ret=""
  else
    ret="OK"
  fi

  port=''
  if [ "$ret" == "OK" ]; then
    ok22=$(checkPort $ip 22)
    if [ $ok22 -lt 1 ]; then
      ok2002=$(checkPort $ip 2002)
      if [ $ok2002 -lt 1 ]; then
        ok135=$(checkPort $ip 135)
        if [ $ok135 -gt 0 ]; then
          port=135
        fi
      else
        port=2002
      fi
    else
      port=22
    fi

    unknownDistro="UNKNOWN"
    RHDistro="Redhat"
    DebianDistro="Debian"

    if [ "$port" == "22" ] || [ "$port" == "2002" ]; then
      redhat=`(ssh -p $port root@$ip [[ -f /etc/redhat-release ]] && echo $?)`
      debian=`(ssh -p $port root@$ip [[ -f /etc/debian_version ]] && echo $?)`
      distro="$unknownDistro"

      if [ $redhat -eq 0 ]; then
        distro="$RHDistro"
      else
        if [ $debian -eq 0 ]; then
          disto="$DebianDistro"
        fi
      fi

      echo -e "$port\t$ip\t$distro ---------------------------------------------";
      if [ $distro != "$unknownDistro" ]; then
          scp -P $port newPassword root@$ip:/tmp/newPassword
          if [ "$distro" == "$RHDistro" ]; then
            echo "Changing Redhat style password"
            ssh -p $port root@$ip "passwd root --stdin < /tmp/newPassword"
          else
            if [ "$distro" == "$DebianDistro" ]; then
              echo "Changing Debian style password"
              ssh -p $port root@$ip "sed 's/^/root\:/' /tmp/newPasswd | chpasswd"
            fi
          fi
          ssh -p $port root@$ip rm /tmp/newPassword
      fi

      scp -P $port root@$ip:/root/.ssh/id_rsa.pub ssh-backup/id_rsa_$ip.pub
      scp -P $port root@$ip:/root/.ssh/authorized_keys ssh-backup/authorized_keys.$ip

      echo "ssh-keygen -R [$ip]:$port" >> /tmp/remove_known_hosts.sh
      echo "ssh-keyscan -p $port -H $ip >> ~/.ssh/known_hosts" >> /tmp/remove_known_hosts.sh
      known="$known$ip:$port ";
    fi

    if [ "$port" == "135" ]; then
      winHosts="$winHosts ";
    fi
  fi

  if [ "$port" == "" ]; then
    echo -e "(n/a)\t$ip ---------------------------------------------"
  fi

done

cat authorized_keys > /tmp/authorized_keys
for server in $known; do
  ip=`echo $server | awk -F: '{ print $1 }'`
  cat ssh-backup/id_rsa_$ip.pub >> /tmp/authorized_keys
done

for server in $known; do
  ip=`echo $server | awk -F: '{ print $1 }'`
  port=`echo $server | awk -F: '{ print $2 }'`
  echo "Copying to $ip:$port ---------------------------------------"
  scp -P $port /tmp/remove_known_hosts.sh root@$ip:/tmp/remove_known_hosts.sh
  ssh -p $port root@$ip chmod +x /tmp/remove_known_hosts.sh
  ssh -p $port root@$ip /tmp/remove_known_hosts.sh

  scp -P $port /tmp/authorized_keys root@$ip:/root/.ssh/authorized_keys
  ssh -p $port root@$ip chmod 0600 /root/.ssh/authorized_keys
done

echo "Windows hosts: $winHosts"

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 383
Posted in Servidores