GNU/Linux >> Linux の 問題 >  >> Linux

サーバー間のユーザーパスワードリストの単純な一方向同期

解決策 1:

awk を使用して、ID が 500 以上のユーザー/グループを抽出できます。また、ユーザー ID 65534 を自由に除外しました。これは、多くの場合、「nobody」ユーザー用に予約されています (ディストリビューションによって異なります。CentOS がそうするかどうかはわかりません):

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

次に、rsync、scp、または選択したファイル転送方法を使用して、ファイルをバックアップ システムにコピーします。これらのファイルは、復元する必要がある場合に、「クリーンな」passwd、グループ、またはシャドウ ファイルの最後に追加できます (つまり、ID/ユーザー名の意図しない重複を防ぐために、デフォルトのシステム ユーザー/グループのみ)。

cat passwd.new >> /etc/passwd
cat group.new >> /etc/group
cat shadow.new >> /etc/shadow

解決策 2:

NIS/NIS+ はまさにこの理由で発明されました。

しかし、それらは一種の醜いものであり、集中型 (LDAP/Kerberos/SMB/など) の認証を行うことができれば、はるかに優れたアイデアです。 NIS/NIS+ をセットアップするには、以下が必要です:

パッケージ:

yp-tools ypbind ypserv portmap

そして /etc/yp.conf のようなもの:

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

次に、/etc/sysconfig/network:

NISDOMAIN=example.org

そして、私は怠け者になりました.ここに良いハウツーがあります:http://www.wains.be/index.php/2007/02/28/setting-up-nis-under-centos-4/.

個人的には、バックアップのために /etc/ ディレクトリ全体をバックアップするだけで済みます。せいぜい数メガです。

解決策 3:

cppw と 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.

解決策 4:

ここには多くの方法と解決策がありますが、元の質問に答えるには 3 つのステップがあります:

<オール>
  • サーバーでパスワードなしの SSH キーを作成します:

    ssh-keygen -b 4096

  • .ssh/id_rsa.pub をクライアントの .ssh/authorized__keys2 にコピーします:

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

  • 次のようなものを /etc/crontab に追加します (または crontab -e で編集します):

    0 0 * * * scp /etc/{passwd,shadow,group} [email protected]:/var/mybackupdir

  • 解決策 5:

    ええと、独自のソリューションを展開しなくても使用できる既存のものがあると思っていましたが、すぐに何かをしなければなりませんでした.

    以下は、私が必要としていたことを実行するスクリプトです。

    手順

    機能させるには、最小および最大の UID が 通常 と見なされるように、いくつかの構成変数を変更するだけです。 ユーザーとリモート ホスト名または IP アドレス。

    ローカル サーバーの root からの着信 SSH セッションを受け入れるように、リモート サーバーをセットアップする必要があります。 ユーザーは、パスワードを入力する必要はありません。
    Commander Keen は、このページの彼の回答でそれがどのように行われるかを示唆しましたが、パスワードなしの SSH ログイン も参照できます。 詳細な手順については、

    仕組み

    スクリプトが行うことは、それぞれのリモート passwd をコピーすることです 、グループgshadow ファイルをリモート サーバーから lcoal サーバー上の一時的な場所にコピーします。
    次に、すべての「通常の」ユーザーからこれらの一時ファイルを削除し、システム ユーザーへの参照のみを保持します。

    次のステップでは、各ローカル バージョンの passwd を調べます。 、グループgshadow 「通常の」ユーザーのみを対応する一時ファイルに追加し、それぞれをリモート サーバーにアップロードして古いサーバーと置き換えます。

    警告

    何かを試みる前に、必ず passwd のコピーを作成してください 、グループgshadow ローカル サーバーとリモート サーバーの両方で。

    セキュリティ

    ファイルの所有権と属性は保持されます。
    一時ファイルは /tmp に保存されます 同期が成功したかどうかに関係なく、削除されます。
    ローカル サーバーにはパスワードなしの root が必要です バックアップへのアクセスを許可します (ただし、その逆はできません)。これは、ユーザー アカウントの構成ファイルを取得できるようにするために必要です (それ以外の場合は制限されます)。

    コード

    これは初めての試みで、少し面倒です (美しいコードではありません) が、かなりうまく機能し、他の誰かが役に立つと思うかもしれません.

    Net::SCP のみに依存する Perl スクリプトです。 サーバー間でファイルを安全にコピーするためのモジュール。

    #!/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;
            }
    }
    

    2010 年 5 月 21 日更新:グループ ID の同期を改善するためにコードを更新


    Linux
    1. Linux でのパニック パスワード

    2. CentOS で root ユーザーの単純なパスワードを有効にする

    3. sudoers と root グループへのユーザーの追加の違いは何ですか?

    1. セキュリティ上の理由から、単純な Linux サーバーに非 root ユーザーが本当に必要ですか?

    2. との差 !対!! vs * /etc/shadow 内

    3. BASH:ユーザーのパスワードがロックされている場合は、/etc/shadow をチェックインします

    1. ユーザーグループルートの機能??

    2. Linuxのグループのメンバーを一覧表示する

    3. Linuxでユーザーパスワードを設定または変更する