Sincronização unidirecional simples da lista de senhas de usuários entre servidores

5

Usando uma distro derivada do RedHat (CentOS), gostaria de manter a lista de usuários regulares (UID acima de 500) e agrupar (e arquivos de sombra) enviados para um servidor de backup.
A sincronização é unidirecional, do servidor principal ao servidor de backup.

Eu realmente não quero ter que lidar com LDAP ou NIS.
Tudo o que preciso é de um script simples que possa ser executado todas as noites para manter o servidor de backup atualizado.
O servidor principal pode fazer o SSH no sistema de backup.

Alguma sugestão?

Editar:
Obrigado pelas sugestões até agora, mas acho que não fiquei claro o suficiente.
Estou apenas analisando a sincronização de usuários normais cujo UID está em ou acima de 500 . Usuários de sistema / serviço (com UID abaixo de 500) podem ser diferentes em ambos os sistemas. Então você não pode simplesmente sincronizar os arquivos inteiros, estou com medo.

    
por Renaud Bompuis 03.06.2009 / 06:04

7 respostas

2

Bem, eu pensei que existia algo que eu pudesse usar sem ter que rolar minha própria solução, mas eu tive que fazer algo rápido.

Abaixo está um script que fará exatamente o que eu precisava.

Instruções

Para que funcione, apenas altere as poucas variáveis de configuração para o UID mínimo e máximo a ser considerado como um usuário normal e o nome do host remoto ou endereço IP.

Você deve configurar o servidor remoto para aceitar as sessões SSH de entrada do usuário root do servidor local sem precisar digitar uma senha.
Commander Keen insinuou como é feito em sua resposta nesta página, mas você também pode se referir a login SSH sem senha para detalhes instruções.

Como funciona

O que o script faz é copiar cada um dos arquivos passwd , grupo , sombra , gshadow do o servidor remoto para um local temporário no servidor lcoal.
Em seguida, ele remove esses arquivos temporários de todos os usuários "normais", mantendo apenas as referências aos usuários do sistema.

O próximo passo é passar por cada uma das versões locais de passwd , grupo , sombra , gshadow e anexando apenas os usuários "normais" aos seus arquivos temporários correspondentes e, em seguida, fazendo o upload de cada um deles de volta ao servidor remoto para substituir o antigo.

Aviso

Antes de tentar qualquer coisa, certifique-se de fazer uma cópia do seu passwd , grupo , sombra , gshadow nos servidores locais e remotos.

Segurança

A propriedade e os atributos dos arquivos são preservados.
Os arquivos temporários são salvos em /tmp e excluídos, independentemente de a sincronização ter sido bem-sucedida ou não.
O servidor local deve ter root de acesso sem senha ao backup (mas não o contrário). Isso é necessário para que possamos obter os arquivos de configuração de contas de usuários (que são restritos).

O código

Esta é uma primeira tentativa e é um pouco confusa (não é um código bonito), mas faz o trabalho muito bem e outra pessoa pode achar útil.

É um script em Perl que só depende do Net::SCP módulo para copiar arquivos com segurança entre servidores.

#!/usr/bin/perl -w
use Net::SCP qw(scp);
use strict;

use constant TRUE  => (1==1);
use constant FALSE => (1==0);

#--------------------------------------------------------
# Configuration
# Modify as needed
#--------------------------------------------------------
my $remoteHost = '10.13.113.2';  # email backup server
my $minUID     = 500;
my $maxUID     = 30000;
my $minGID     = 500;
my $maxGID     = 30000;

#--------------------------------------------------------
# Internal variables, normally not to be modified.
#--------------------------------------------------------
my $systemConfigDir = '/etc';
my $tmpDir = $ENV{TMPDIR} || $ENV{TMP} || $ENV{TEMP} || '/tmp';

#--------------------------------------------------------
#  Main
#--------------------------------------------------------
# STEP 1
# Get the remote files to /tmp and
# clean them of their normal users
ProcessFiles('remote');

# STEP 2
# Append the local normal users to the temp files
# and then send them back to the remote
ProcessFiles('local');

#--------------------------------------------------------
# ProcessFiles sub does one of two things:
# - if the passed argument is 'remote', then fetch each
#   user account file from the remote server, then remove
#   all normal users from each file, only keeping the
#   system users.
# - if the passed argument is 'local', then appends all
#   normal local users to the previously fetched and
#   cleaned-up files, then copies them back to the remote.
#--------------------------------------------------------
sub ProcessFiles {
        my $which = shift;
        my $tmpfile;
        my %username = ();
        my %usergroup = ();
        my %userUID = ();
        my %userGID = ();
        my @info;
        foreach my $f ('passwd','group','shadow','gshadow') {
                my $tmpfile = "$tmpDir/$f.REMOTE";
                if ($which eq 'remote') {
                        # Fetch the remote file
                        unlink $tmpfile if -e $tmpfile;
                        scp("$remoteHost:$systemConfigDir/$f", $tmpfile)
                                or die ("Could not get '$f' from '$remoteHost'");
                }
                # Glob the file content
                open CONFIGFILE, (($which eq 'remote') ? $tmpfile : "$systemConfigDir/$f");
                my @lines = <CONFIGFILE>;
                close CONFIGFILE;
                # Open the temp file, either truncating it or in append mode
                open TMPFILE,  (($which eq 'remote') ? ">$tmpfile" : ">>$tmpfile" )
                        or die "Could not open '$tmpfile' for processing";
                foreach my $line (@lines) {
                         # Skip comments, although they should be illegal in these files
                        next if $f =~ /^\s*#/;
                        @info = (split ':', $line);
                        if ($f eq 'passwd') {
                                my $uid = $info[2];
                                my $isnormaluser = ($uid > $minUID) && ($uid < $maxUID);
                                next if (($which eq 'remote') ? $isnormaluser : !$isnormaluser);
                                $username{$info[0]} = TRUE;
                                $userUID{$uid} = TRUE;
                                $userGID{$info[3]} = TRUE;
                        } elsif ($f eq 'group') {
                                my $gid = $info[2];
                                my $isnormalgroup = ($gid > $minGID) && ($gid < $maxGID);
                                next if (($which eq 'remote') ? $isnormalgroup : !$isnormalgroup);
                                $usergroup{$info[0]} = TRUE;
                        } elsif ($f eq 'shadow') {
                                next if !exists $username{$info[0]};
                        } else {
                                next if !exists $usergroup{$info[0]};
                        }
                        # Any line that reaches this point is valid
                        print TMPFILE $line;
                }
                close TMPFILE;
                if ($which eq 'local') {
                        # send the file back
                        scp($tmpfile, "$remoteHost:$systemConfigDir/$f") or
                                die ("Could not send '$f' to '$remoteHost'");
                        unlink $tmpfile;
                }
        }
}

#--------------------------------------------------------
# Make sure we cleanup the temp files when we exit
#--------------------------------------------------------
END {
        my $tmpfile;
        foreach my $f ('passwd','group','shadow','gshadow') {
                $tmpfile = "$tmpDir/$f.REMOTE";
                unlink $tmpfile if -e $tmpfile;
        }
}

Atualização 21MAY2010: código atualizado para melhorar a sincronização do ID do grupo

    
por 03.06.2009 / 13:41
10

Você pode usar o awk para extrair usuários / grupos com IDs de 500 ou mais. Eu também tomei a liberdade de excluir o ID de usuário 65534, que é frequentemente reservado para o usuário "nobody" (dependendo da distro; nenhuma pista se o CentOS fizer isso):

awk -F: '($3>=500) && ($3!=65534)' /etc/passwd > passwd.new
awk -F: '($3>=500) && ($3!=65534)' /etc/group > group.new
awk -F: '($3>=500) && ($3!=65534) {print $1}' /etc/passwd | grep -f - /etc/shadow > shadow.new

Em seguida, use o rsync, scp ou o método de transmissão de arquivo escolhido para copiar os arquivos para o sistema de backup. Esses arquivos podem ser anexados ao final de um arquivo passwd, group ou shadow 'limpo' quando você precisar restaurá-los (isto é: usuários / grupos padrão do sistema apenas, para evitar duplicações não intencionais de ID / nome de usuário).

cat passwd.new >> /etc/passwd
cat group.new >> /etc/group
cat shadow.new >> /etc/shadow
    
por 03.06.2009 / 07:42
3

NIS / NIS + foram inventados por esse motivo exato.

Mas eles são feios e centralizados (LDAP / Kerberos / SMB / etc.) autenticação é uma idéia muito melhor se você puder fazê-lo. Para configurar o NIS / NIS + você precisará:

Pacotes:

yp-tools ypbind ypserv portmap

e um /etc/yp.conf com algo como:

domain example.org server nis.example.org
ypserver nis.example.org

e depois em / etc / sysconfig / network:

NISDOMAIN=example.org

E eu tenho preguiça, aqui está um bom howto: link que o guiará por ele.

Pessoalmente, para backup, eu apenas fiz backup de todo o diretório / etc / e terminei com ele. São apenas alguns megas no máximo.

    
por 03.06.2009 / 06:41
3

use cppw e cpgr:

CPPW (8)

NAME
       cppw, cpgr - copia com o bloqueio do arquivo fornecido para a senha ou arquivo de grupo

SINOPSE
       cppw [-h] [-s] password_file        cpgr [-h] [-s] group_file

DESCRIÇÃO
       cppw e cpgr copiarão, com bloqueio, o arquivo fornecido para / etc / passwd e / etc / group, respectivamente. Com o sinalizador -s, eles copiarão as versões de sombra do        esses arquivos, / etc / shadow e / etc / gshadow, respectivamente.        Com o sinalizador -h, os comandos exibem uma pequena mensagem de ajuda e saem silenciosamente.

VEJA TAMBÉM
       vipw (8), vigr (8), grupo (5), passwd (5), sombra (5), gshadow (5)

AUTOR
       cppw e cpgr foram escritos por Stephen Frost, baseado em vipw e vigr escrito por Guy Maor.

    
por 03.06.2009 / 16:45
2

Existem muitas formas e soluções aqui, mas para responder à pergunta original, há três etapas:

  1. Crie uma chave SSH sem senha no servidor:

    ssh-keygen -b 4096

  2. Copie .ssh / id_rsa.pub para .ssh / authorized__keys2 no cliente:

    scp ~/.ssh/id_rsa.pub client:.ssh/authorized_keys2

  3. Adicione algo assim ao seu / etc / crontab (ou edite com crontab -e):

    0 0 * * * scp /etc/{passwd,shadow,group} root@backupbox:/var/mybackupdir

por 03.06.2009 / 06:32
0

Eu uso o rsync em uma entrada crontab para fazer um backup simples que realiza a mesma coisa. Infelizmente eu não faço mais de ssh. Minha entrada no crontab é assim:

0 4 * * 0 rsync -av --delete / etc / / backup / etc /

Na verdade, meu crontab inicia meu servidor NAS, ou seja, o segundo caminho que você vê listado acima, via wake-on-lan e, em seguida, faz vários backups com este sendo apenas um deles. O Cron então me envia um e-mail informando o que foi feito em backup, ou seja, quais arquivos foram sincronizados, etc.

Eu não tentei fazer isso com o ssh, mas espero que isso ajude.

    
por 03.06.2009 / 06:22
0

Você precisa apenas de uma sincronização parcial, o script deve ser muito mais complexo e, portanto, mais propensos a ter algum tipo de bugs. Pessoalmente, eu levaria algum tempo e investigaria quanto esforço seria simplesmente consertar essas outras contas. Não sei quantos serviços estamos falando, mas eu acho que tudo o que você teria que fazer depois de alterar os ajustes das IDs das contas de serviço seria atualizar o proprietário de alguns arquivos.

Se você quisesse fazer algo realmente simples, poderia configurar como rdist ( intro ) para simplesmente enviar os arquivos para o outro servidor. Para manter isso seguro, você precisaria configurar o acesso ssh baseado em chave para o processo rdist usar.

    
por 03.06.2009 / 06:08