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

Ach*_*itz 5 java host authorization zos

我希望测试在 z/OS 下运行的 JDBC 服务器实现。通常的方法是定义一个 JCL 过程并将其作为启动任务运行。启动的任务需要一个用户 ID,它将在该用户 ID 下运行。JDBC jars 放置在已挂载在 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
Run Code Online (Sandbox Code Playgroud)

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

JVMJZBL1001N JZOS batch Launcher Version: 2.4.4 2013-05-07
JVMJZBL1002N (C) Copyright IBM Corp. 2005, 2012
JVMJZBL1009E 子壳进程退出,没有打印环境;//STDENV 不应包含 'exit' JVMJZBL1042E JZOS 批处理启动器失败,返回码=101

在查看并阅读IBM 支持文档的内容后,我和我的同事们非常困惑。然后我尝试将服务器作为一项直接的工作启动。该作业的用户具有系统管理员权限。这有效,我们可以测试 JDBC 服务器。尝试与用户一起运行该过程的作业会导致与上述相同的错误。

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

有什么方法可以找出缺少的东西吗?这是非常令人沮丧的。

2016 年 10 月 11 日编辑

以下 JCL 是<user>具有系统管理员权限时起作用的 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
Run Code Online (Sandbox Code Playgroud)

该过程如下所示:

//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
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,该作业只不过是运行该过程。当<user>是为启动程序的用户名,上述错误产生,当它是一个管理员用户,则该作业正常运行。显然,要将其作为启动任务启动,proc 被复制到公共 proc 库(准确地说是 USER.PROCLIB)。

没有什么特别引人注目的。事实上,这是非常平庸的。这就是为什么我们怀疑这是 RACF 问题的原因。

编辑 (2) 11.10.2016

这还不是解决方案,但我已经设法解决了问题。如果它被分配了受信任的属性,则启动的过程会起作用。这实际上意味着启动的任务在 z/OS Unix 中被视为“超级用户”(换句话说,它具有 root 权限)。所以现在是确定我们的服务器需要什么的问题,迄今为止只有在由超级用户运行时才可用。当我发现时,我会发布一个解决方案。

编辑 (3) 12.12.2016

添加trace后(见上面修改后的proc),出现如下错误:

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()
Run Code Online (Sandbox Code Playgroud)

不清楚为什么我们会收到这个运行时错误。在这个阶段,它看起来不再是权限问题。

Ach*_*itz 0

终于我有时间回到这个问题上来了。原来的问题相当模糊。在查看了多个论坛后,终于清楚了成员 ACHIM.JDBCSRV.CNTL(SRVENV) 中存在错误。它包含以下行:

. /etc/profile
Run Code Online (Sandbox Code Playgroud)

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

此后又出现了新的错误:

java.lang.NoClassDefFoundError: de.ubs.du.jdbcserver.Server
Run Code Online (Sandbox Code Playgroud)

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

OMVS(HOME(/u/zfs4svr)...
Run Code Online (Sandbox Code Playgroud)

当任务启动时,这指定包含 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')        
Run Code Online (Sandbox Code Playgroud)

这里的困难在于,所有者和权限/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)              
...
Run Code Online (Sandbox Code Playgroud)

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

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