在 Linux 中如何使用需要密码的命令进行身份验证?

在 Linux 中如何使用需要密码的命令进行身份验证?

我有一个问题,如果我出于某种原因在服务器中运行 nohup,当我注销服务器时,权限会发生变化并且崩溃。

所以我被建议运行这个:

/afs/cs/software/bin/reauth

在 tmux/screen 中。但我想使用 tmux。所以我想将该命令放入main.sh脚本中,但它要求我输入密码。有没有办法在命令中提供/输入密码,以便它位于main.sh脚本中,并且当我运行它时,它只需运行而无需用户交互?

目前我这样做:

/afs/cs/software/bin/reauth

它要求我的互动

(metalearning_gpu) brando9~/diversity-for-predictive-success-of-meta-learning $ /afs/cs/software/bin/reauth
Password for brando9: 

但希望它通过我输入一次密码来工作/验证。

来自服务器维基的详细信息:

Long-running jobs

Problem
You start a screen session on one of our servers. Everything runs fine, you detach the screen and log out. You log back into the server, reattach the screen and realize that things are failing left and right because you lost file system permissions.

Solution
Use krbscreen and reauth.

How to use krbscreen and reauth
Below are the steps you need to take to successfully run a long-lived session on our machines:

kill all the existing reauth processes that you might be running
ssh to the relevant host: ssh [email protected]
run krbscreen on the host: /afs/cs/software/bin/krbscreen; run krbtmux on the host: /afs/cs/software/bin/krbtmux
run reauth: /afs/cs/software/bin/reauth
your commands inside krbscreen
detach the screen as you would normally
When you decide to re-attach your screen session you can use the regular screen command:

ssh to the relevant host: ssh [email protected]
re-attach your screen session: screen -x
krbscreen is just a wrapper around regular screen that runs aklog and makes copies of your current kerberos tickets.

万一链接https://ilwiki.stanford.edu/doku.php?id=hints:long-jobs不起作用。

内容rauth

(metalearning_gpu) brando9~ $ cat /afs/cs/software/bin/reauth
#!/usr/bin/perl
# $Id: reauth 2737 2011-06-20 18:14:05Z miles $
#
# Original version (C) Martin Schulz, 2'2002
# University Karlsruhe
#
# Modifications by Miles Davis <[email protected]>
#  Super minimal -- call programs rather than functions to reduce dependence
#  on extra perl modules.
#
# Heimdal patches thanks to Georgios Asimenos <[email protected]>
#

# General:
##########

# This little script aims at maintaining a valid AFS token from a
# users password for long running jobs.

# As everybody knows (or should know) Kerberos tickets and AFS tokens
# only have a limited lifetime. This is so by design and is usually
# reasonable. After 12 hours, it is no more obvious that it is really
# that user sitting in front of the computer that once typed the
# correct password in. Furthermore the damage caused by compromized
# AFS tokens is limited to the lifetime of that ticket.

# However, there are situations when users want to use long running
# jobs that will write to AFS filespace for several days. Renewable
# tickets are not so much of help here, since they can only be renewed
# if ....

# Therefore the secret has somehow deposited on the local computer
# that will run the long time job. This can be eiter done by storing a
# keytab on the local disk, maybe with a cron(*) principal with
# reduces priviledges. The approach taken here is to work with the
# original password and keep it in RAM only.

# When starting this program, the user is asked for his principal and
# the corresponding password. Then the TGT and AFS token is obtained
# and displayed, afterwards, a background process is forked and the
# main process will return to the system prompt. The workload program
# can now be started.

# The background process will periodically attempt to obtain krb
# tickets and AFS tokens. If this fails for some reason (Kerberos
# server not available or anything, the program aborts.

# aklog does not create a new pag if not told so. If you want your
# background process have a separate pag, create it beforehand.

# The reauth.pl program will work until eternity if is not stopped
# somehow. The canonical way is kill it by "kill $pid", where $pid is
# the process id printed before the return of the initial call to
# reauth.pl or found in the output of "ps".


# (*) Cron jobs are another issue. Our institute introduced
# user.cron-style principals to enable cron to obtain a token and then
# work on restricted parts of the users home directories.


# Security issues:
##################

# reauth.pl will run forever if you do not stop it, so don't forget that!

# The password is kept in RAM (of the child process). AFAIK, this can
# only be recovered by local root (who you need to trust anyway). It
# will not survive a reboot of the local machine.

# The password is not kept on any disk. Therefore any bootfloppy
# (reboot to single user mode..)  or screwdriver (take disk away..)
# attacks are not promising.

# Be aware that your NSA-, FBI-, MI5-, KGB-, ElQaida-, or (*insert
# your favorite opponent or competitor here*)-sponsored cleaning
# personnel or coworkers might have even more elaborate means... :-)


# BUGS:
#######

# Only mildly tested only on Linux and Solaris.

# Uses kinit, aklog, klist and tokens programs for a KerberosV/ Ken
# Hornstein's migration kit centered AFS setup. Please adjust to your
# config.




###########################################################################
# Configs:


# kinit program, add path if necessary
if ( -e "/usr/kerberos/bin/kinit" ) {
    $kinit="/usr/kerberos/bin/kinit";
} elsif ( -e "/usr/lib/heimdal/bin/kinit" ) {
    $kinit = "/usr/lib/heimdal/bin/kinit";
} elsif ( -e "/usr/bin/kinit" ) {
    $kinit="/usr/bin/kinit";
} else {
    die("Couln't find kinit.\n");
}


# aklog program, add path if necessary
if ( -e "/usr/bin/aklog" ) {
    $aklog="/usr/bin/aklog";
} elsif ( -e "/usr/lib/heimdal/bin/afslog" ) {
    # or, afslog, for heimdal weirdos
    $aklog="/usr/lib/heimdal/bin/afslog";
} else {
    die("Couln't find aklog or afslog.\n");
}

# klist program, add path if necessary
$klist="/usr/kerberos/bin/klist";

# tokens program, add path if necessary
$tokens="/usr/bin/tokens";


#################################################################
# Program:

use Getopt::Long;
use POSIX qw(setuid);
use POSIX qw(setgid);
use POSIX qw(setsid);

# Defaults for command line options.
my $keytab = '';
my $command = '';
my $username = '';
my $debug = 0;
my $verbose = 0;
my $interval=15000; # time interval in seconds: 4+ hours:

my %opts = (
    # Keytab
    'k=s' => sub {
                    $keytab = @_[1];
                    $kinit_opts .= "-k -t $keytab ";
                },
    # Run command
    'c=s' => sub {
                    $command = @_[1];
                },
    # Run command as user
    'u=s' => sub {
                    $username = @_[1];
                },
    # Time interval to sleep
    'i=i' => sub {
                    $interval = @_[1];
                },
    # Debug
    'd'   => sub {
                    $debug++;
                },
    # Be versbose
    'v'   => sub {
                    $verbose++;
                },
);


GetOptions(%opts) or die "Usage: reauth [ -k=keytab ] [ -u user ] [ -i <sleep_interval ] [ -v ] [ -c <command> ]\n";




if(@ARGV) {
    $princ = $ARGV[0];
    debug_print(2, "Principal name provided by argument = $princ");
} else {
   # Assume we want the login name as the principal name
    $princ = getpwuid($<);
    debug_print(2, "Principal name provided by argument = $princ");
}

if ($keytab) {
    # Don't ask for password, a keytab was provided.
    debug_print(1, "Keytab provided = $keytab");
} else {
    # read password, but turn off echo before:
    print "Password for $princ: ";
    system "stty -echo";
    $passwd = <STDIN>;
    system "stty echo";
    printf "\n";
    chomp $passwd;
    # Actually get the tickets/tokens
    if(obtain_tokens()!=0) {
        die "Can't obtain kerberos tickets\n";
    }
    if ($verbose) {
        show_tokens();
    }
}

# fork to go into background:
# a) the parent will exit
# b) the child will work on
$pid = fork();
if ($pid) {
    # I am the parent.
    printf "Background process pid is: $pid\n";
    if ($command) {
        debug_print(1,"Waiting for child to die.");
        wait;
        debug_print(1,"Child is dead.");
    }
    exit 0;
} else {
    # I am the child.
    debug_print(2,"I am process $$");
    print "Can't set session id\n" unless setsid();

    debug_print(2,"KRB5CCNAME: " . $ENV{KRB5CCNAME});
    #if ($ENV{KRB5CCNAME}) {
        #$ENV{KRB5CCNAME} =  $ENV{KRB5CCNAME} . "_reauth_$$";
    #} else {
        #$ENV{KRB5CCNAME} =  "/tmp/krb5cc_reauth_$$";
    #}

    #debug_print(2,"Creating " . $ENV{KRB5CCNAME});
    #system "touch $ENV{KRB5CCNAME}";


    if ($username) {
        debug_print(1, "Looking up UID for $username");
        ($name,$passwd,$UID,$GID, @junk) = getpwnam($username);
        debug_print(1, "Changing to UID $UID, GID $GID");
        print "Can't set group id\n" unless setgid($GID);
        print "Can't set user id\n" unless setuid($UID);
        if ($ENV{KRB5CCNAME}) {
            $ENV{KRB5CCNAME} =  $ENV{KRB5CCNAME} . "_reauth_$$";
        } else {
            $ENV{KRB5CCNAME} =  "/tmp/krb5cc_reauth_$$";
        }
    }

    debug_print(2, "Running as uid " . $<);
    # Actually get the tickets/tokens
    if(obtain_tokens()!=0) {
        die "Can't obtain kerberos tickets\n";
    }

    if ($verbose) {
        show_tokens();
    }

    # If I was told to run a command, do it.
    if ($command) {
        debug_print(1,"About to exec $command");
        exec($command) or die "Can't execute '$command'.\n";
        exit
    }

    debug_print(2,"Going into auth loop (interval is $interval).");

    #close(STDOUT);
    #close(STDERR);

    # Otherwise, work until killed:
    while (1) {
        debug_print(2,"Waking up to obtain new tokens.");
        obtain_tokens();
        if ($verbose) {
            show_tokens();
        }
        sleep $interval;
    };
}

#################################################################


sub obtain_tokens() {

  # ignore sigpipes' (according to perlopentut)
  $SIG{PIPE} = 'IGNORE';

    #debug_print(1,"Running: | $kinit -f $kinit_opts -p $princ 1>/dev/null 2>&1");

  # run kinit
  open(KINIT, "| $kinit -f $kinit_opts -p $princ 1>/dev/null 2>&1");

  # pass password to stdin, password does not show up on command line
  if (! $keytab) {
      print(KINIT "${passwd}\n");
  }

  # close pipe and get status
  close(KINIT); $status=$?;

    debug_print(1,"kinit exited with status $status\n");
  # act on status..
  if($status == 256) {
        if ($verbose) {
            print "WARNING: kinit is not able to obtain Kerberos ticket ($status).\n";
            print "         Possible DNS or network problem. Continuing anyway...\n";
        }
        return 1;
  } elsif($status!=0) {
    print "kinit is not able to obtain Kerberos ticket: $status\n";
     return 2;
  };

    debug_print(1,"Running $aklog...\n");
  $status = system "$aklog >/dev/null" ;
    debug_print(1,"aklog exited with status $status\n");
  if($status!=0) {
    print "aklog is not able to obtain AFS token: $status\n";
     return 3;
  };

  return 0;

};

##################################################################

sub show_tokens() {
    system $klist ;
    system $tokens ;
};

##################################################################

sub debug_print($$) {
    my $level = shift;
    my $message = shift;

    if ($debug >= $level) {
        print "DEBUG$debug: $message\n";
    }
}

##################################################################

有关的:如何发送新命令运行到已经运行的 nohup 进程或在 nohup 中一起/同时运行两个命令?尝试在 nohup 命令中与其他命令一起运行 reauth(更新 kerberos 票证)。

答案1

由于不知道reauth详细信息,所以很难猜测什么可以解决您的情况,但我相信您不必在任何地方传递密码。

所以,情况是这样的:您正在访问的系统使用 Kerberos 进行身份验证。这意味着当您登录时,您的密码(或其他身份验证方式)将用于请求。门票本质上是访问代码。登录时请求的票证称为票证授予票证,这样您就可以向您需要访问的软件的其他部分提供门票;特别是通过 NFS(网络文件系统)访问目录。

该票证授予票证定期到期;运行klist查看它,以及它的到期时间。您还会看到一行“续订直至”;您可以在该期限内更新此类票据,而无需证明您知道某些身份验证秘密(密码)。期间是通常一周。

因此,如果您没有运行时间超过“续订截止”时间的作业,则无需密码即可续订您的票证授予票证,并且将继续能够访问您需要的所有文件。

kinit -R只需在票证“过期”之前运行即可。在大多数系统上,票证会在 10 小时后过期,但您的系统可能有所不同。不管怎样,假设它在 4 小时后过期,那么每 1.5 小时更新一次门票是一种非常明智的方式(而且不会太烦人)。您可以简单地通过在单独的 tmux 窗口中运行的小 while 循环来解决该问题

while true; do kinit -R; sleep $((60 * 60 * 3 / 2)); done

现在,如果您的工作运行时间超过“续订截止”日期,那么运气不好,在某些时候,您必须获得一张带有密码的新票证授予票证。幸运的是,kinit它并不挑剔从哪里获取密码。因此,您可以将密码输入到kinit;就像是

echo 'totally secret password' | kinit [email protected]

会做的,与您在“默认主体”[email protected]中看到的相同。klist

由于在您的计算机上运行的脚本reauth无法知道您的密码,因此它需要询问;但我打赌最终它主要是这样做的:在没有密码的情况下尽可能长时间地更新可更新的票证授予票证,并且每周一次,使用启动时要求的密码请求新的票证授予票证。

相关内容