z/OS 中启动的任务缺少 RACF 权限

z/OS 中启动的任务缺少 RACF 权限

我希望测试在 z/OS 下运行的 JDBC 服务器实现。通常的方法是定义一个 JCL 过程并将其作为启动任务运行。启动任务需要运行该任务的用户 ID。JDBC jar 放置在已安装在 OMVS 中的 ZFS 文件系统中。

启动任务的用户需要特定的 RACF 权限,该权限由以下 JCL 提供

//RUNRACF  EXEC PGM=IKJEFT01
//SYSUADS  DD DSN=SYS1.UADS,DISP=SHR
//SYSLBC   DD DSN=SYS1.BRODCAST,DISP=SHR
//SYSTSPRT DD SYSOUT=*
//SYSTSIN  DD *
AU JDBCUSR NAME('JDBC STC USER') PASSWORD(JDBCUSR) -
    OWNER(IBMUSER) DFLTGRP(STCGROUP) -
    UACC(READ)  OMVS(HOME(/u/zfs4svr) PROGRAM(/bin/sh) UID(3005) -
FILEPROCMAX(131072))

RDEFINE STARTED SVRPROC.** STDATA(USER(JDBCUSR) GROUP(STCGROUP) -
TRUSTED(NO))

SETROPTS CLASSACT(STARTED)
SETROPTS RACLIST(STARTED) REFRESH

PERMIT BPX.SERVER ACCESS(READ) CLASS(FACILITY) -
  ID(JDBCUSR)

SETROPTS CLASSACT(FACILITY)
SETROPTS RACLIST(FACILITY) REFRESH

当我启动任务时,SYSOUT 中出现以下错误消息:

JVMJZBL1001N JZOS 批处理启动器版本:2.4.4 2013-05-07
JVMJZBL1002N (C) 版权所有 IBM Corp. 2005, 2012
JVMJZBL1009E 子 shell 进程退出时未打印环境;//STDENV 不应包含“exit”JVMJZBL1042E JZOS 批处理启动器失败,返回代码 = 101

在查阅了这篇文章并阅读了IBM 支持文档不得不说,我和我的同事们都很困惑。然后我尝试将服务器作为一项直接的作业启动。该作业的用户具有系统管理员权限。这有效,我们可以测试 JDBC 服务器。尝试使用该过程的用户运行该作业会导致与上面所示的相同错误。

很明显,JDBCUSR 缺少某些权限。要将服务器作为启动任务运行,我需要知道缺少哪些权限。我们当然不希望授予启动任务用户系统管理员权限。

有没有什么办法可以找出丢失的东西?这很令人沮丧。

编辑 2016.10.11

<user>以下 JCL 是在具有系统管理员权限时执行工作的 JOB :

//V4JSRV   JOB USER=<user>,PASSWORD=<password>,REGION=200M
//*
//*******************************************************************
//* Call the server as a job
//*******************************************************************
//PROCS    JCLLIB ORDER=(ACHIM.JDBCSRV.CNTL)
//SRV      EXEC PROC=SRVPROC
//STDENV   DD DISP=SHR,DSN=ACHIM.JDBCSRV.CNTL(SRVENV)
//STRCTREP DD DISP=SHR,DSN=ACHIM.JDBCSRV.STRCTREP

该过程如下:

//JDBCPROC  PROC JAVACLS='de.ubs.du.jdbcserver.Server',
//   ARGS='-p 5431 LOG-LEVEL=FINE',
//   LEPARM='',
//   LOGLVL='+T'
//JAVAJVM  EXEC PGM=JVMLDM70,REGION=200M,
//   PARM='&LEPARM/&LOGLVL &JAVACLS &ARGS'
//*JDBCPROC  PROC
//*JAVAJVM  EXEC PGM=JVMLDM70,REGION=200M,
//*   PARM='de.ubs.du.jdbcserver.Server -p 5431 LOG-LEVEL=FINE'
//STEPLIB  DD DSN=JVA700.SIEALNKE,DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSOUT   DD SYSOUT=*
//STDOUT   DD SYSOUT=*
//STDERR   DD SYSOUT=*
//CEEDUMP  DD SYSOUT=*
//ABNLIGNR DD DUMMY

如您所见,该作业只执行运行该过程的操作。当<user>启动过程的用户名是 时,会产生上述错误,当用户名是管理员时,作业将正常运行。显然,要将其作为启动任务启动,需要将过程复制到公共过程库(准确地说是 USER.PROCLIB)。

这一切并没有什么特别引人注目的地方。事实上,这很平庸。这就是为什么我们怀疑这是一个 RACF 问题。

编辑 (2) 2016.10.11

目前这还不是解决方案,但我已经设法将问题定位。如果已分配 TRUSTED 属性,则启动的程序将运行。这实际上意味着已启动的任务在 z/OS Unix 中被视为“超级用户”(换句话说,它具有 root 权限)。因此,现在的问题就是确定我们的服务器需要什么,到目前为止,只有由超级用户运行时才可用。当我找到答案时,我会发布解决方案。

编辑 (3) 2016.12.12

添加跟踪后(参见上面修改后的过程),出现以下错误:

JVMJZBL2999T ->invokeMain()                                                           
JVMJZBL2999T javaClassName: 'de.ubs.du.jdbcserver.Server'                              
JVMJZBL2999T Arg 1='-p'                                                                
JVMJZBL2999T Arg 2='5431'                                                              
JVMJZBL2999T Arg 3='LOG-LEVEL=FINE'                                                    
JVMJZBL1023N Invoking de.ubs.du.jdbcserver.Server.main()...                            
JVMJZBL1056I Arguments to main...                                                      
JVMJZBL1057I -p                                                                        
JVMJZBL1057I 5431                                                                      
JVMJZBL1057I LOG-LEVEL=FINE                                                            
JVMJZBL2999T -> JniUtil.convert()                                                      
JVMJZBL2999T <- JniUtil.convert()                                                      
JVMJZBL2008E Could not find or load class: de.ubs.du.jdbcserver.Server                 
JVMJZBL2999T -> JniUtil.writeStackTrace()                                              
JVMJZBL2007E Stack trace follows:                                                      
java.lang.NoClassDefFoundError: de.ubs.du.jdbcserver.Server                            
Caused by: java.lang.ClassNotFoundException: de.ubs.du.jdbcserver.Server               
.at java.net.URLClassLoader.findClass(URLClassLoader.java:588)                         
.at java.lang.ClassLoader.loadClassHelper(ClassLoader.java:756)                        
.at java.lang.ClassLoader.loadClass(ClassLoader.java:724)                              
.at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:313)                      
.at java.lang.ClassLoader.loadClass(ClassLoader.java:703)                              
JVMJZBL2999T <- JniUtil.writeStackTrace()                                              

JVMJZBL2999T <- invokeMain()                                                           
JVMJZBL2999T <- run()                                                                  
JVMJZBL2999T -> cleanup()                                                              
JVMJZBL1014I Waiting for non-deamon Java threads to finish before exiting...           
JVMJZBL2999T JvmExitHook entered with exitCode=0, javaMainReturnedOrThrewException=0   
JVMJZBL1042E JZOS batch launcher failed, return code=100                               
JVMJZBL2999T DestroyJavaVM elapsed time=0.031311 seconds, cpu time=0.021000 seconds    
JVMJZBL2999I JZOS batch launcher elapsed time=7 seconds, cpu time=5.090000 seconds     
JVMJZBL1047W JZOS batch launcher completed with Java exception, return code=100        
JVMJZBL2999T <- cleanup()

我们为什么会遇到这个运行时错误还不清楚。目前看来,它不再是权限问题。

答案1

我终于有时间回过头来研究这个问题了。最初的问题相当模糊。在查看了多个论坛后,我终于明白了成员 ACHIM.JDBCSRV.CNTL(SRVENV) 中存在错误。它包含以下行:

. /etc/profile

删除此设置可修复第一个错误,该错误是由任何 bash 脚本末尾的隐式“退出”引起的。如果您正在执行类似操作并且确实需要脚本中的设置/etc/profile,那么我只能建议您将脚本的内容复制到您的//STDENV数据中。

随后出现了新的错误:

java.lang.NoClassDefFoundError: de.ubs.du.jdbcserver.Server

这在上面的编辑 (3) 中有所显示。这确实是权限问题。在设置 RACF 权限的作业中,SYSTSIN DD 中有以下内容:

OMVS(HOME(/u/zfs4svr)...

当任务启动时,这将指定包含 JDBCUSR 使用的 jar 的 ZFS 文件系统的挂载点。相应的挂载作业由管理员用户运行。相关作业步骤如下:

//REPRO    EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
  DELETE '<HLQ>.JDBCSRV.ZFS'
  SET MAXCC = 0
  DEFINE CLUSTER ( -
     NAME('<HLQ>.JDBCSRV.ZFS') -
     LINEAR CYL(50 1) -
     SHAREOPTIONS(3,3) -
  )
  REPRO INDATASET(<HLQ>.JDBCSRV.REPRO) -
         OUTDATASET(<HLQ>.JDBCSRV.ZFS)
//****************************************************
//SHELLCMD EXEC PGM=BPXBATCH,COND=(4,LT),
//    PARM='SH mkdir -p /u/zfs4fb'
//SYSPRINT DD SYSOUT=*
//SYSOUT   DD SYSOUT=*
//STDOUT   DD SYSOUT=*
//STDERR   DD SYSOUT=*
//*************************************************
//SHELLCMD EXEC PGM=BPXBATCH,COND=(4,LT),
//    PARM='SH chown -R JDBCUSR:STCGROUP /u/zfs4fb'
//SYSPRINT DD SYSOUT=*
//SYSOUT   DD SYSOUT=*
//STDOUT   DD SYSOUT=*
//STDERR   DD SYSOUT=*
//**************************************************
//SHELLCMD EXEC PGM=BPXBATCH,COND=(4,LT),
//    PARM='SH chmod -R 770 /u/zfs4fb'
//SYSPRINT DD SYSOUT=*
//SYSOUT   DD SYSOUT=*
//STDOUT   DD SYSOUT=*
//STDERR   DD SYSOUT=*
//**************************************************
//MOUNT    EXEC PGM=IKJEFT01,COND=(4,LT)
//SYSTSPRT DD SYSOUT=*
//SYSTSIN  DD *
  MOUNT -
     FILESYSTEM('''<HLQ>.JDBCSRV.ZFS''') -
     TYPE(HFS) -
     MODE(RDWR) -
     MOUNTPOINT('/u/zfs4fb')        

这里的难点在于,虽然 的所有者和权限/u/zfs4fb设置为允许 JDBCUSR 访问,但是,其中的包仍然归运行该作业的用户所有。我们直接在 OMVS 中更改了内容的读/写访问权限。这解决了问题。要在脚本中修复此问题,需要更改作业步骤的顺序。在这种情况下,将 2 个//SHELCMD步骤与chmodchown命令放在//MOUNT步骤之后可以解决问题

我们的任务还存在其他问题。在服务器初始化过程中,user.dir使用了该属性。我不确定具体在哪里,但似乎与 z/OS 的 JVM 有关。我们花了些时间研究,因为我们无法确定该值的来源。当作为管理员用户 (IBMUSER) 提交的作业运行时,该值为“/u/ibmuser”。但是,当作为已启动任务运行时,该值为“。”,这会导致错误:

java.lang.ExceptionInInitializerError                         
.at java.lang.J9VMInternals.initialize(J9VMInternals.java:258)
...
Caused by: java.lang.RuntimeException: default directory must be absolute 
.at sun.nio.fs.UnixFileSystem.<init>(UnixFileSystem.java:55)              
...

解决方法是将命令放在环境脚本cd /u/zfs4fb的末尾//STDENV。这实际上可以是 STC 用户(在本例中为 JDBCUSR)有读取权限的任何目录。

希望这次探索之旅能够帮助其他试图解决类似问题的人。

相关内容