Solución 1:
Puede usar awk para extraer usuarios/grupos con ID de 500 o más. También me he tomado la libertad de excluir el ID de usuario 65534, que a menudo está reservado para el usuario "nadie" (dependiendo de la distribución; no tengo idea si CentOS lo hace):
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
A continuación, utilice rsync, scp o el método de transmisión de archivos que prefiera para copiar los archivos en su sistema de copia de seguridad. Estos archivos se pueden agregar al final de un archivo de contraseña, grupo o sombra 'limpio' cuando necesite restaurarlos (es decir, solo usuarios/grupos predeterminados del sistema, para evitar duplicaciones no intencionales de ID/nombre de usuario).
cat passwd.new >> /etc/passwd
cat group.new >> /etc/group
cat shadow.new >> /etc/shadow
Solución 2:
NIS/NIS+ se inventaron exactamente por esta razón.
Pero son un poco feos y centralizados (LDAP/Kerberos/SMB/etc.) la autenticación es una idea mucho mejor si puede hacerlo. Para configurar NIS/NIS+ necesitará:
Paquetes:
yp-tools ypbind ypserv portmap
y un /etc/yp.conf con algo como:
domain example.org server nis.example.org
ypserver nis.example.org
y luego en /etc/sysconfig/network:
NISDOMAIN=example.org
Y me dio pereza, aquí hay un buen tutorial:http://www.wains.be/index.php/2007/02/28/setting-up-nis-under-centos-4/ que lo guiará.
Personalmente, para la copia de seguridad, simplemente haría una copia de seguridad de todo el directorio /etc/ y terminaría con eso. Son solo unos pocos megas como máximo.
Solución 3:
usa cppw y 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.
Solución 4:
Aquí hay muchas formas y soluciones, pero para responder a la pregunta original hay tres pasos:
-
Cree una clave SSH sin contraseña en el servidor:
ssh-keygen -b 4096
-
Copie .ssh/id_rsa.pub a .ssh/authorized__keys2 en el cliente:
scp ~/.ssh/id_rsa.pub client:.ssh/authorized_keys2
-
Agregue algo como esto a su /etc/crontab (o edite con crontab -e):
0 0 * * * scp /etc/{passwd,shadow,group} [email protected]:/var/mybackupdir
Solución 5:
Bueno, pensé que había algo existente que podría usar sin tener que implementar mi propia solución, pero tenía que hacer algo rápido.
A continuación se muestra un script que hará justo lo que necesitaba.
Instrucciones
Para que funcione, simplemente cambie las pocas variables de configuración para que el UID mínimo y máximo se considere como normal usuario y el nombre del host remoto o la dirección IP.
Debe haber configurado el servidor remoto para aceptar sesiones SSH entrantes desde el root
del servidor local usuario sin tener que introducir una contraseña.
El comandante Keen insinuó cómo se hace en su respuesta en esta página, pero también puede consultar inicio de sesión SSH sin contraseña para obtener instrucciones detalladas.
Cómo funciona
Lo que hace el script es copiar cada una de las contraseñas remotas , grupo , sombra , gsombra archivos del servidor remoto a una ubicación temporal en el servidor local.
Luego, elimina estos archivos temporales de todos los usuarios "normales", conservando solo las referencias a los usuarios del sistema.
El siguiente paso es revisar cada una de las versiones locales de passwd , grupo , sombra , gsombra y agregando solo los usuarios "normales" a sus archivos temporales correspondientes, luego subiendo cada uno de ellos al servidor remoto para reemplazar el anterior.
Advertencia
Antes de intentar cualquier cosa, asegúrese de hacer una copia de su contraseña , grupo , sombra , gsombra tanto en el servidor local como en el remoto.
Seguridad
Se conservan la propiedad y los atributos de los archivos.
Los archivos temporales se guardan en /tmp
y eliminado, ya sea que la sincronización haya sido exitosa o no.
El servidor local debe tener root
sin contraseña acceso a la copia de seguridad (pero no al revés). Esto es necesario para que podamos obtener los archivos de configuración de las cuentas de usuario (que de lo contrario están restringidos).
El Código
Este es un primer intento y es un poco complicado (no es un código hermoso), pero hace el trabajo bastante bien y alguien más puede encontrarlo útil.
Es un script de Perl que solo tiene una dependencia en el Net::SCP
módulo para copiar archivos de forma segura 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;
}
}
Actualización del 21 de mayo de 2010:código actualizado para mejorar la sincronización del ID de grupo