sh 脚本 获取环境变量_0614-同一OS用户并行Shell脚本中kinit不同的Principal串掉问题...

1.文档编写目的

在前面的文章《0552-5.15.0-同一OS用户不同Kerberos用户执行脚本Principal串掉》中Fayson主要介绍了同一个OS用户下并发调度Python脚本时会导致Principal账号串掉,通过在Python代码中指定KRB5CCNAME环境变量解决问题,本篇文章Fayson主要介绍通过同一OS用户下并发调度Shell脚本进行不同用户Kerberos认证时Principal账号串掉问题分析及解决。

  • 测试环境

1.RedHat7.3

2.CDH5.16.1

2.问题描述

Fayson通过一段简单的shell脚本示例代码说明问题,在代码中执行kinit命令初始化Kerberos信息,通过hadoop命令去统计各自用户目录下子目录大小,具体代码如下:

a_fayson.sh脚本内容如下:

[root@cdh4 shell-test]# more a_fayson.sh kinit -kt /root/shell-test/fayson.keytab faysonklisthadoop fs -du -h /user/fayson

a_cdhadmin.sh脚本内容如下:

[root@cdh4 shell-test]# more a_cdhadmin.sh kinit -kt /root/shell-test/cdhadmin.fayson cdhadminklisthadoop fs -du -h /user/cdhadmin
ca9297de360458a7bd0268e25ef55af0.png

在同一个用户的OS下创建a_fayson.sh和a_cdhadmin.sh的两个shell脚本,分别使用fayson和cdhadmin用户初始化Kerberos信息。

在crontab中添加两个定时任务,使两个任务同时并发

cdf6c6102e7a0f99cc5a321be3b2e4b4.png

在生成的a_fayson.log和a_cdhadmin.log中可以看到两个脚本会获取到对方的Principal信息

02fc638bbf7b6509b35dfe9db887efe5.png

通过两个脚本输出的日志可以看到a_fayson.log中kinit的是fayson用户,但在执行hadoop命令的时候显示的为cdhadmin,此时Principal账号串掉导致命令执行失败。

3.问题分析

1.首先在客户端进行Kinit操作后,默认的Ticket Cache是存储在tmp/krb5cc_0临时文件中(Ticket cache文件是根据当前用户的uid在/tmp目录下生成一个以krb5cc_开头的临时文件)。

2.由于上述的两个脚本是在同一个OS用户下,所以两个不同的Kerberos用户在进行Kinit操作后都会覆盖/tmp/krb5cc_{uid}文件

f53afab8eee45c9f79b0e7cec78401d6.png

根据上述两点基本可以定位问题的原因,因为Ticket cache文件被覆盖导致Kerberos的票据信息串掉。由于两个shell脚本使用了同一份Ticket cache文件导致Kerberos的票据信息串掉。

4.解决方法一

将脚本进行简单的修改,在脚本中指定KRB5CCNAME的环境变量,具体修改在shell脚本中增加如下内容:

a_fayson.sh脚本内容如下:

[root@cdh4 shell-test]# more a_fayson.sh export KRB5CCNAME=/tmp/fayson_ccnamekinit -kt /root/shell-test/fayson.keytab faysonklisthadoop fs -du -h /user/fayson
fef267a9bf039ed427a5f070cc541b9d.png

a_cdhadmin.sh脚本内容如下:

[root@cdh4 shell-test]# more a_cdhadmin.sh export KRB5CCNAME=/tmp/cdhadmin_ccnamekinit -kt /root/shell-test/cdhadmin.keytab cdhadminklisthadoop fs -du -h /user/cdhadmin
c82f02cd16ce08f44fb948f5654ebd69.png

将脚本进行如上修改后,再次运行发现问题解决,未出现Principal串掉的问题

b8aaf5aa4a79c19c159c3b923df420cd.png
75c6a656d434fac10c56f9e0903ec852.png

5.解决方法二

在脚本中使用了C shell(csh)命令,C shell是一个交互式命令解释器和一种编程语言,采用的语法类型于C编程语言。在C shell中我们可以指定KRB5CCNAME环境变量,具体实现方式如下:

1.在OS命令行执行如下命令安装csh命令

[root@cdh4 shell-test]# yum -y install csh
dbf4ddc0fcfed20e6e613bfdcb50474f.png

2.修改上述的两个脚本,具体修改如下:

a.sh脚本内容如下:

[root@cdh4 shell-test]# more a.sh #!/usr/bin/cshsetenv KRB5CCNAME /tmp/fayson_ccnameenv |grep KRB5CCNAMEkinit -kt /root/shell-test/fayson.keytab faysonklisthadoop fs -du -h /user/fayson
e3fe51c6483745e4bd164bd746f0f2cf.png

b.sh脚本内容如下:

[root@cdh4 shell-test]# more b.sh #!/usr/bin/cshsetenv KRB5CCNAME /tmp/cdhadmin_ccnameenv |grep KRB5CCNAMEkinit -kt /root/shell-test/cdhadmin.keytab cdhadminklisthadoop fs -du -h /user/cdhadmin
721a7db6ea3c16a11b8aeedd71f27acf.png

3.使用crontab定义两个并发的定时任务

*/1 * * * * source /etc/profile & csh /root/shell-test/a.sh >> /root/shell-test/a.log 2>&1 &*/1 * * * * source /etc/profile & csh /root/shell-test/b.sh >> /root/shell-test/b.log 2>&1 &
8dfa674f6aa27ff53c3e44f5883335e2.png

4.通过修改上述两个脚本,在两个脚本中都指定KRB5CCNAME环境变量为不同的文件,再次进行测试未发现两个应用的票据信息串掉的问题。

8b09084c71829e3dc4d4ee316894541a.png

6.总结

1.默认Ticket cache文件的生成是根据用户的uid在/tmp目录下生成一个以krb5cc_开头的缓存文件。

2.如果在同一个OS用户下使用不同的Kerberos用户进行kinit会覆盖/tmp/krb5cc_{uid}文件,从而导致应用中的票据信息串掉。

3.可以通过在shell脚本中为不同的Kerberos用户指定一个独立的Ticket cache文件,以防止票据信息串掉。

4.本篇文章中主要讲述了shell脚本的两种实现方式一种在脚本中使用export的方式指定环境变量,一种使用C shell命令通过setenv方式指定。脚本中的环境变量这里可以理解为局部环境变量,只在当前脚本内有效。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
The `kinit` command is typically used to obtain and cache a Kerberos ticket-granting ticket (TGT) for a user or service principal. The `-kt` option specifies the path to the keytab file containing the service principal's key, and the principal name `kafka/tos_demo@DEMO.TDH` specifies the service principal to use for authentication. Here is an example Java code snippet that shows how to use the `javax.security.auth.Subject` and `javax.security.auth.login.LoginContext` classes to obtain a Kerberos TGT using a keytab file: ```java import javax.security.auth.Subject; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; import java.io.File; public class KerberosAuthenticator { public static void main(String[] args) { String keytabPath = "/etc/keytabs/keytab"; String principalName = "kafka/tos_demo@DEMO.TDH"; // Set up the Kerberos login configuration System.setProperty("java.security.auth.login.config", "/etc/krb5.conf"); // Create a new subject to hold the Kerberos credentials Subject subject = new Subject(); // Create a new login context using the keytab and principal try { LoginContext loginContext = new LoginContext("KafkaClient", subject, null, new KeytabPrincipalAuthenticationModule(keytabPath, principalName)); loginContext.login(); } catch (LoginException e) { System.err.println("Failed to login: " + e.getMessage()); return; } // Print out the Kerberos ticket details System.out.println("Kerberos ticket granted to:"); subject.getPrincipals().forEach(System.out::println); } private static class KeytabPrincipalAuthenticationModule implements javax.security.auth.spi.LoginModule { private final String keytabPath; private final String principalName; private boolean succeeded = false; public KeytabPrincipalAuthenticationModule(String keytabPath, String principalName) { this.keytabPath = keytabPath; this.principalName = principalName; } @Override public void initialize(Subject subject, CallbackHandler callbackHandler, java.util.Map<String, ?> sharedState, java.util.Map<String, ?> options) { } @Override public boolean login() throws LoginException { // Create a new Kerberos login configuration based on the specified keytab and principal javax.security.auth.login.Configuration config = new javax.security.auth.login.AppConfigurationEntry[] { new javax.security.auth.login.AppConfigurationEntry( "com.sun.security.auth.module.Krb5LoginModule", javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, java.util.Map.of( "useKeyTab", "true", "keyTab", keytabPath, "principal", principalName, "storeKey", "true", "doNotPrompt", "true" ) ) }; // Attempt to authenticate using the keytab and principal javax.security.auth.login.LoginContext context = new javax.security.auth.login.LoginContext("", null, null, config); context.login(); // Add the Kerberos credentials to the subject succeeded = true; subject.getPrivateCredentials().add(context.getTicket()); return true; } @Override public boolean commit() throws LoginException { return succeeded; } @Override public boolean abort() throws LoginException { return false; } @Override public boolean logout() throws LoginException { subject.getPrivateCredentials().clear(); return true; } } } ``` This code defines a `K
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值