
Usando uma distribuição derivada do RedHat (CentOS), gostaria de manter a lista de usuários regulares (UID acima de 500) e grupos (e arquivos shadow) enviados para um servidor de backup.
A sincronização é unidirecional, do servidor principal para o servidor de backup.
Eu realmente não quero ter que lidar com LDAP ou NIS.
Tudo que preciso é de um script simples que possa ser executado todas as noites para manter o servidor de backup atualizado.
O servidor principal pode usar SSH no sistema de backup.
Alguma sugestão?
Editar:
Obrigado pelas sugestões até agora, mas acho que não fui claro o suficiente.
Estou apenas procurando sincronizar usuários normais cujosUID é igual ou superior a 500.
Os usuários do 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, infelizmente.
Responder1
Você pode usar o awk para extrair usuários/grupos com IDs de 500 ou mais. Também tomei a liberdade de excluir o ID do usuário 65534, que geralmente é reservado para o usuário "ninguém" (dependendo da distribuição; não tenho ideia se o CentOS faz 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 rsync, scp ou o método de transmissão de arquivos de sua preferência para copiar os arquivos para o sistema de backup. Esses arquivos podem então ser anexados ao final de uma senha, grupo ou arquivo shadow 'limpo' quando você precisar restaurá-los (ou seja: apenas usuários/grupos padrão do sistema, 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
Responder2
NIS/NIS+ foram inventados exatamente por esse motivo.
Mas eles são meio feios e centralizados (LDAP/Kerberos/SMB/etc.). A autenticação é uma idéia muito melhor se você puder fazê-lo. Para configurar o NIS/NIS+ você precisará de:
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 fiquei com preguiça, aqui está um bom tutorial:http://www.wains.be/index.php/2007/02/28/setting-up-nis-under-centos-4/isso irá orientá-lo.
Pessoalmente, para backup, eu apenas faria backup de todo o diretório /etc/ e terminaria com ele. São apenas alguns megas, no máximo.
Responder3
use cppw e cpgr:
CPPW(8)
NAME
cppw, cpgr - copy with locking the given file to the
password or group file
SYNOPSIS<br>
cppw [-h] [-s] password_file
cpgr [-h] [-s] group_file
DESCRIPTION
cppw and cpgr will copy, with locking, the given file to
/etc/passwd and /etc/group, respectively. With the -s flag,
they will copy the shadow versions of those files,
/etc/shadow and /etc/gshadow, respectively.
With the -h flag, the commands display a short help message
and exit silently.
SEE ALSO
vipw(8), vigr(8), group(5), passwd(5), shadow(5), gshadow(5)
AUTHOR
cppw and cpgr were written by Stephen Frost, based on vipw
and vigr written by Guy Maor.
Responder4
Bem, pensei que havia algo que eu pudesse usar sem ter que criar minha própria solução, mas precisava fazer algo rápido.
Abaixo está um script que fará exatamente o que eu precisava.
Instruções
Para que funcione, basta alterar algumas variáveis de configuração para que o UID mínimo e máximo seja considerado como umnormalusuário e o nome do host remoto ou endereço IP.
Você deve ter configurado o servidor remoto para aceitar sessões SSH recebidas do usuário do servidor local root
sem precisar inserir uma senha.
Comandante Keensugeriu como isso é feito em sua resposta nesta página, mas você também pode consultarlogin SSH sem senhapara obter instruções detalhadas.
Como funciona
O que o script faz é copiar cada um dos controles remotossenha,grupo,sombra,sombraarquivos do 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.
A próxima etapa é passar por cada uma das versões locais dosenha,grupo,sombra,sombrae anexar apenas os usuários "normais" aos arquivos temporários correspondentes e, em seguida, enviar 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 senha,grupo,sombra,sombranos servidores locais e remotos.
Segurança
A propriedade e os atributos do arquivo são preservados.
Os arquivos temporários são salvos /tmp
e excluídos, independentemente de a sincronização ter sido bem-sucedida ou não.
O servidor local deve ter acesso ao backup sem senha root
(mas não o contrário). Isso é necessário para que possamos obter os arquivos de configuração das contas de usuário (que de outra forma seriam restritos).
O código
Esta é uma primeira tentativa e é um pouco confusa (não é um código bonito), mas funciona muito bem e outra pessoa pode achar útil.
É um script Perl que depende apenas doNet::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