2016-2 Real Time Statistics (RTS) Revisited – Information missing (part 1)

Easy Real Time Statistics (RTS) data initialization from DB2 9 to DB2 11:

Special query to run before a REORG, RUNSTAT or a DB2 Migration. How many RTS rows did you find?

 

Hands up who knows nothing about the RTS? Good, all hands are down! I had an interesting experience the other day with one of my customers as they are in the process of doing the big bang “REORG the world” to get from a six byte RBA/LRSN to a 10 Byte RBA/LRSN due to problems with data cloning in a mixed DB2 release Environment.

 

RTS Database Maintenance

They use the RTS to drive the creation of REORG, RUNSTAT, and COPY utilities as this is the modern and correct way to go, right? Well, they ended up with a bunch of objects that refused to REORG. I looked high and low for *any* reason as to why they would be excluded from processing and found none. Well, actually, I lie – there was one, and that was the fact that the candidate list was based upon a SELECT from the RTS tables and then joining to the DB2 Catalog to refine the data and then finally generating the required REORG jobs.

 

RTS data missing

It was noticed that these tablespaces were either empty or very small and it was seen that they did not even *exist* in the RTS! Now cast your mind way way way back to DB2 V7 when the RTS were introduced as an “optional” feature. I wrote a little SQL INSERT to populate the RTS for any missing elements as the IBM way of populating the RTS was to “REORG the world” (remember those halcyon days?) Anyway these days, about 11 years later, it is *always* assumed that:

– The RTS data exists
– The RTS data is correct (mainly!)
– RTS data initialization made easy

So, to save you all from trying to find my SQL from those days, here’s the DB2 9 and above version which you can, perhaps must, run to make sure you have no “bodies in the cellar” like my customer did!

 

RTS data initialization made easy

So, to save you all from trying to find my SQL from those days, here’s the DB2 9 and above version which you can, perhaps must, run to make sure you have no “bodies in the cellar” like my customer did!

 

------------------------------------------------------------------------
-- THESE TWO QUERIES WILL FILL THE RTS TABLES SYSIBM.SYSTABLESPACESTATS
-- AND SYSIBM.SYSINDEXSPACESTATS WITH DEFAULT AND, WHEN POSSIBLE,     --
-- WITH CATALOG DATA FOR MISSING ENTRIES                              --
-- (OBJECTS FOUND IN THE CATALOG BUT NOT IN RTS TABLES)               --
------------------------------------------------------------------------
-- LOCK TABLE SYSIBM.SYSTABLESPACESTATS IN EXCLUSIVE MODE ;         

INSERT INTO SYSIBM.SYSTABLESPACESTATS
 (UPDATESTATSTIME,NACTIVE,EXTENTS)
 ,LOADRLASTTIME
 ,REORGLASTTIME,REORGINSERTS,REORGDELETES,REORGUPDATES,REORGUNCLUSTINS
 ,REORGDISORGLOB,REORGMASSDELETE,REORGNEARINDREF,REORGFARINDREF
 ,STATSLASTTIME,STATSINSERTS,STATSDELETES,STATSUPDATES,STATSMASSDELETE
 ,COPYLASTTIME,COPYUPDATEDPAGES,COPYCHANGES
 ,IBMREQD
 ,DBID,PSID,PARTITION,INSTANCE,SPACE,TOTALROWS 
 ,DBNAME,NAME)
 SELECT CURRENT TIMESTAMP 
 ,CASE A.SPACEF 
  WHEN -1 THEN CASE A.SPACE 
               WHEN 0 THEN NULL 
               ELSE A.SPACE / B.PGSIZE 
               END
  ELSE MIN( 2147483647 , ( MAX(A.SPACEF , A.SPACE) / B.PGSIZE ) )
  END
 ,CASE A.EXTENTS
  WHEN -1 THEN NULL
  ELSE A.EXTENTS
  END
  ,TIMESTAMP('0001-01-01-00.00.00.000000')
  ,TIMESTAMP('0001-01-01-00.00.00.000000'), 0 , 0 , 0 , 0   
  , 0 , 0 , 0 , 0  
  ,CASE 
    WHEN A.STATSTIME = TIMESTAMP('0001-01-01-00.00.00.000000') 
    THEN A.STATSTIME 
    WHEN A.STATSTIME < A.CREATEDTS THEN 
                       TIMESTAMP('0001-01-01-00.00.00.000000')
    ELSE A.STATSTIME
    END
  , 0 , 0 , 0 , 0 
  ,TIMESTAMP('0001-01-01-00.00.00.000000'), 0 , 0   
  , 'N'   
  ,B.DBID,B.PSID,A.PARTITION,B.INSTANCE  
  ,CASE A.SPACEF 
    WHEN -1 THEN CASE A.SPACE 
                 WHEN 0  THEN NULL  
                 ELSE A.SPACE 
                 END 
    ELSE MAX( MIN( 2147483647 , A.SPACEF ) , A.SPACE)
    END 
   ,CASE A.CARDF 
    WHEN -1 THEN NULL  
    ELSE A.CARDF 
    END 
   ,A.DBNAME,A.TSNAME  
    FROM SYSIBM.SYSTABLEPART  A 
        ,SYSIBM.SYSTABLESPACE B 
    WHERE NOT EXISTS (SELECT C.*  
                     FROM SYSIBM.SYSTABLESPACESTATS C 
                     WHERE A.DBNAME = C.DBNAME 
                       AND A.TSNAME = C.NAME  
                       AND A.PARTITION = C.PARTITION)    
     AND NOT A.SPACE  = -1   
     AND A.DBNAME     = B.DBNAME   
     AND A.TSNAME     = B.NAME    
  ; 
COMMIT ;
-- LOCK TABLE SYSIBM.SYSINDEXSPACESTATS IN EXCLUSIVE MODE ;
INSERT INTO SYSIBM.SYSINDEXSPACESTATS
 (UPDATESTATSTIME
 ,NLEVELS,NLEAF,NACTIVE,SPACE,EXTENTS
 ,LOADRLASTTIME
 ,REBUILDLASTTIME
 ,REORGLASTTIME,REORGINSERTS,REORGDELETES,REORGAPPENDINSERT
 ,REORGPSEUDODELETES,REORGMASSDELETE,REORGLEAFNEAR,REORGLEAFFAR
 ,REORGNUMLEVELS
 ,STATSLASTTIME,STATSINSERTS,STATSDELETES,STATSMASSDELETE
 ,COPYLASTTIME,COPYUPDATEDPAGES,COPYCHANGES
 ,IBMREQD
 ,DBID,ISOBID,PSID,PARTITION,INSTANCE
 ,TOTALENTRIES,DBNAME,NAME,CREATOR,INDEXSPACE)
  SELECT CURRENT TIMESTAMP
 ,CASE B.NLEVELS
   WHEN -1 THEN NULL
   ELSE B.NLEVELS
   END
  ,CASE B.NLEAF
   WHEN -1 THEN NULL
   ELSE B.NLEAF
   END
  ,CASE A.SPACEF
   WHEN -1 THEN CASE A.SPACE
                WHEN 0  THEN NULL
                ELSE A.SPACE / B.PGSIZE
                END
  ELSE MIN( 2147483647 , ( MAX(A.SPACEF , A.SPACE) / B.PGSIZE ) )
  END
 ,CASE A.SPACEF
  WHEN -1 THEN CASE A.SPACE
               WHEN 0  THEN NULL
               ELSE A.SPACE
               END
  ELSE MAX( MIN( 2147483647 , A.SPACEF ) , A.SPACE)
  END
 ,CASE A.EXTENTS
   WHEN -1 THEN NULL
   ELSE A.EXTENTS
   END
 ,TIMESTAMP('0001-01-01-00.00.00.000000')
 ,TIMESTAMP('0001-01-01-00.00.00.000000')
 ,TIMESTAMP('0001-01-01-00.00.00.000000'), 0 , 0 , 0
 , 0 , 0 , 0 , 0 , 0
 ,CASE
  WHEN A.STATSTIME = TIMESTAMP('0001-01-01-00.00.00.000000')
  THEN A.STATSTIME
  WHEN A.STATSTIME < A.CREATEDTS THEN
                     TIMESTAMP('0001-01-01-00.00.00.000000')
  ELSE A.STATSTIME
  END
 , 0 , 0 , 0
 ,TIMESTAMP('0001-01-01-00.00.00.000000'), 0 , 0
 , 'N'
 ,B.DBID,B.ISOBID, C.PSID
 ,A.PARTITION,C.INSTANCE
 ,CASE A.CARDF
  WHEN -1 THEN NULL
  ELSE A.CARDF
  END
 ,B.DBNAME,B.NAME,B.CREATOR,B.INDEXSPACE
  FROM SYSIBM.SYSINDEXPART  A
      ,SYSIBM.SYSINDEXES    B
      ,SYSIBM.SYSTABLESPACE C
      ,SYSIBM.SYSTABLES     D
 WHERE NOT EXISTS (SELECT E.*
                   FROM SYSIBM.SYSINDEXSPACESTATS E
                   WHERE B.DBNAME = E.DBNAME
                     AND B.INDEXSPACE = E.INDEXSPACE
                     AND A.PARTITION  = E.PARTITION)
   AND B.CREATOR    = A.IXCREATOR
   AND B.NAME       = A.IXNAME
   AND NOT A.SPACE  = -1
   AND B.TBCREATOR  = D.CREATOR
   AND B.TBNAME     = D.NAME
   AND D.DBNAME     = C.DBNAME
   AND D.TSNAME     = C.NAME
;
COMMIT ;

 

It may even be a good idea to run these two queries on a regular basis… just in case!

I would like to know how many rows these queries INSERTed at your shops – Here in Düsseldorf, in the labs, it found two TS’s and three IX’s in a DB2 11 NFM system.

As always, any questions or comments would be most welcome!

TTFN,

Roy Boxwell

2016-01 Simply Synonyms in DB2 z/OS (again)

As SYNONYMS are dying out, it is a good idea to start DROPping them as soon as you can…

In this short newsletter I wish to remind you all that SYNONYMS are dead! They may still be nailed to their perch (old Monty Python reference here!), but they are dead! Even the DB2 documentation has removed them and a big sign says DEPRECATED over the SQL syntax. So much for the preamble… The question is: What can you do? I will attempt to show you how to discover what size of problem you have, and provide some help in sorting out the mess of synonyms.

UPDATE!

On Friday the 08.04.2016 Pat posted this update on the DB2-L LISTSERV:

Hello,

I wanted to share an update on synonyms.

Synonyms are similar to aliases, but are supported only for compatibility with previous releases. Synonyms behave differently with DB2 for z/OS than with the other DB2 family products. It is recommended that you not create or use synonyms when writing new SQL statements or creating portable applications; use aliases instead. The publications currently state that synonyms are deprecated. The publications are being updated to reflect that synonyms are not being removed from DB2 for z/OS at this time and are no longer considered deprecated.

Best regards,

Pat Bossman
DB2 for z/OS Query Optimizer Team at IBM’s Silicon Valley Lab (SVL)

Synonyms were a good idea many years ago but they brought with them a few problems: one is that you lose the connection between a synonym and the alias it is created on, another is that GRANTs on synonyms actually are recorded in the DB2 Catalog against the base tables, and finally the SYNONYM did not agree with the rest of the world’s SQL Standards.

On Thursday the 28.04.2016 Pat posted this correction on the DB2-L LISTSERV:

Hello,

I need to issue a correction on information I previously disseminated.  I apologize for inconvenience this caused.

Update on synonyms: I understand there are a lot of questions about the status of synonyms now. In hindsight, the original communication that synonyms were being removed from the deprecation list was based on an internal misunderstanding and miscommunication. This resulted in premature dissemination of inaccurate information. This disclosure should have been more thoroughly vetted, and I apologize for the confusion caused.

What is the status of synonyms? Synonyms remain deprecated. However, synonyms continue to be supported for compatibility with prior releases in DB2 12. Removing synonyms from the product is an incompatible change and that incompatible change has not yet been scheduled or planned for implementation.

Documentation changes coming to the effect of: Synonyms are similar to aliases, but are supported only for compatibility with previous releases. Synonyms behave differently with DB2 for z/OS than with the other DB2 family products. Aliases behave the same for the DB2 family of products. Recommendation: When writing new SQL statements or creating portable applications, use aliases instead. The publications currently state that synonyms are deprecated, however, IBM has no current plans to remove support for synonyms from DB2 for z/OS.

Addendum: There has been some confusion related to the meaning of deprecation as it relates to a feature of software, as opposed to removing support for a feature of software. Deprecation is the discouragement of use of some feature, design or practice, typically because it has been superseded or is no longer considered safe, without (at least for the time being) removing it from the system of which it is a part or prohibiting its use. This is distinct from blocking or removing support, where the feature is no longer available. For clarity, a definition of deprecation will be to our software Gallery.

Patrick Bossman
DB2 for z/OS Query Optimizer Team at IBM’s Silicon Valley Lab (SVL)

 

Finding the bad guys

Here’s a triplet of SQLs to find all the synonym-dependent items:

 

SELECT BSCHEMA    AS CREATOR                
     , BNAME      AS NAME                     
     , BCOLNAME   AS COLUMN_NAME              
     , CASE BTYPE                             
       WHEN 'A' THEN 'ALIAS                   '
       WHEN 'C' THEN 'COLUMN                  '
       WHEN 'F' THEN 'FUNCTION                '
       WHEN 'G' THEN 'GLOBAL TEMPORARY TABLE  '
       WHEN 'M' THEN 'MATERIALIZED QUERY TABLE'
       WHEN 'Q' THEN 'SEQUENCE                '
       WHEN 'S' THEN 'SYNONYM                 '
       WHEN 'T' THEN 'TABLE                   '
       WHEN 'V' THEN 'VIEW                    '
       WHEN 'W' THEN 'SYSTEM_TIME PERIOD      '
       WHEN 'Z' THEN 'BUSINESS_TIME PERIOD    '
       ELSE          'UNKNOWN                 '
       END        AS TYPE                     
     , BOWNER     AS OWNER                    
     , CASE BOWNERTYPE                        
       WHEN 'L' THEN 'ROLE   '                
       WHEN ' ' THEN 'AUTH ID'                
       ELSE          'UNKNOWN'                
       END        AS BOWNERTYPE               
     , DSCHEMA    AS DEP_CREATOR              
     , DNAME      AS DEP_NAME                 
     , DCOLNAME   AS DEP_COLUMN_NAME          
     , CASE DTYPE                             
       WHEN 'C' THEN 'GENERATED COLUMN'       
       WHEN 'F' THEN 'FUNCTION        '       
       WHEN 'I' THEN 'INDEX           '       
       WHEN 'X' THEN 'ROW PERMISSION  '       
       WHEN 'Y' THEN 'COLUMN MASK     '       
       ELSE          'UNKNOWN         '       
       END        AS DEP_TYPE                  
     , DOWNER     AS DEP_OWNER                
     , CASE DOWNERTYPE                        
       WHEN 'L' THEN 'ROLE   '                
       WHEN ' ' THEN 'AUTH ID'                
       ELSE          'UNKNOWN'                
       END        AS DEP_OWNERTYPE            
FROM SYSIBM.SYSDEPENDENCIES                
WHERE BTYPE = 'S'                             
ORDER BY 1 , 2 , 3 , 5 , 7 , 8 , 9 , 11       
WITH UR                                       
;
SELECT BQUALIFIER AS CREATOR                 
     , BNAME      AS NAME                             
     , CASE BTYPE                                 
       WHEN 'A' THEN 'ALIAS                      '    
       WHEN 'B' THEN 'BUSINESS_TIME              '  
       WHEN 'C' THEN 'SYSTEM_TIME                '    
       WHEN 'F' THEN 'UDF OR CAST FUNCTION       '    
       WHEN 'G' THEN 'GLOBAL TEMPORARY TABLE     '    
       WHEN 'I' THEN 'INDEX                      '    
       WHEN 'M' THEN 'MATERIALIZED QUERY TABLE   '    
       WHEN 'O' THEN 'STORED PROCEDURE           '    
       WHEN 'P' THEN 'LARGE OR DSSIZE PART. SPACE'    
       WHEN 'Q' THEN 'SEQUENCE OBJECT            '    
       WHEN 'R' THEN 'TABLESPACE                 '    
       WHEN 'S' THEN 'SYNONYM                    '    
       WHEN 'T' THEN 'TABLE                      '    
       WHEN 'U' THEN 'DISTINCT TYPE              '    
       WHEN 'V' THEN 'VIEW                       '    
       WHEN 'W' THEN 'SYSTEM_TIME PERIOD         '    
       WHEN 'Z' THEN 'BUSINESS_TIME PERIOD       '    
       ELSE          'UNKNOWN                    '    
       END        AS OBJECT_TYPE                       
     , DCOLLID AS COLLECTION                          
     , DNAME   AS PACKAGE                             
     , HEX(DCONTOKEN) AS DCONTOKEN                    
     , CASE DTYPE                                     
       WHEN 'F' THEN 'COMPILED SQL SCALAR FUNCTION    '
       WHEN 'N' THEN 'NATIVE SQL ROUTINE PACKAGE      '
       WHEN 'O' THEN 'ORIGINAL COPY OF A PACKAGE      '
       WHEN 'P' THEN 'PREVIOUS COPY OF A PACKAGE      '
       WHEN 'R' THEN 'RESERVED FOR IBM USE            '
       WHEN 'T' THEN 'TRIGGER PACKAGE                 '
       WHEN ' ' THEN 'NOT A TRIGGER/NATIVE SQL PACKAGE'
       ELSE          'UNKNOWN                         '
       END        AS PACKAGE_TYPE                     
     , DOWNER     AS OWNER                            
     , CASE DOWNERTYPE                                
       WHEN 'L' THEN 'ROLE   '                        
       WHEN ' ' THEN 'AUTH ID'                        
       ELSE          'UNKNOWN'                         
       END        AS DOWNERTYPE                       
FROM SYSIBM.SYSPACKDEP                                
WHERE BTYPE = 'S'                                     
ORDER BY 1 , 2 , 7                                    
WITH UR                                                
;

SELECT BCREATOR   AS CREATOR
     , BNAME      AS NAME
     , CASE BTYPE
       WHEN 'A' THEN 'ALIAS                      '
       WHEN 'E' THEN 'INSTEAD OF TRIGGER         '
       WHEN 'F' THEN 'UDF OR CAST FUNCTION       '
       WHEN 'G' THEN 'GLOBAL TEMPORARY TABLE     '
       WHEN 'I' THEN 'INDEX                      '
       WHEN 'M' THEN 'MATERIALIZED QUERY TABLE   '
       WHEN 'O' THEN 'STORED PROCEDURE           '
       WHEN 'P' THEN 'LARGE OR DSSIZE PART. SPACE'
       WHEN 'Q' THEN 'SEQUENCE OBJECT            '
       WHEN 'R' THEN 'TABLESPACE                 '
       WHEN 'S' THEN 'SYNONYM                    '
       WHEN 'T' THEN 'TABLE                      '
       WHEN 'V' THEN 'VIEW                       '
       ELSE          'UNKNOWN                    '
       END        AS OBJECT_TYPE
     , DNAME   AS PLAN_NAME
FROM SYSIBM.SYSPLANDEP
WHERE BTYPE = 'S'
ORDER BY 1 , 2
WITH UR
;

If you get no data from using these queries, then that is very good indeed! If you do get data, then you must make a note of all the objects listed, as they will be affected by what we are going to do next. “Affected”, in this case, could be as simple as a REBIND, but could also be as complex as recreating UDFs.

 

Generate the drop

-- CREATE DRIVER TABLE FOR CARTESIAN JOIN PROCESSING
DECLARE GLOBAL TEMPORARY TABLE DRIVER (NUMBER SMALLINT) ;
INSERT INTO SESSION.DRIVER VALUES 1 ;
INSERT INTO SESSION.DRIVER VALUES 2 ;
INSERT INTO SESSION.DRIVER VALUES 3 ;
INSERT INTO SESSION.DRIVER VALUES 4 ;
INSERT INTO SESSION.DRIVER VALUES 5 ;
-- NOW GENERATE DROP AND CREATE ALIAS COMMANDS
WITH T1 ( CREATOR
        , NAME
        , ALIAS_NAME
        , ALIAS_TABLE
          )
     AS ( SELECT STRIP(CREATOR)
               , STRIP(NAME)
               , STRIP(CREATOR)   CONCAT '.' CONCAT STRIP(NAME)
               , STRIP(TBCREATOR) CONCAT '.' CONCAT STRIP(TBNAME)
          FROM SYSIBM.SYSSYNONYMS
          ORDER BY 1
        )
SELECT CAST(CASE NUMBER
            WHEN 1 THEN 'SET CURRENT SQLID = '''
                        CONCAT CREATOR CONCAT ''' $'
            WHEN 2 THEN 'DROP SYNONYM ' CONCAT NAME CONCAT ' $'
            WHEN 3 THEN 'CREATE ALIAS ' CONCAT ALIAS_NAME
            WHEN 4 THEN 'FOR ' CONCAT ALIAS_TABLE
            WHEN 5 THEN '$'
            END AS CHAR(72))
FROM T1, SESSION.DRIVER
;

 

The output of this contains the “$” as command terminator, so you must either use a “C ALL $ ;” style ISPF command, or just use a “–#SET TERMINATOR $” line in the SPUFI.

One thing to remember, before executing the generated output, is the problem of the GRANTs. Remember that all GRANTs are recorded at the table level not at the synonym level, so you have two choices here:

  1. Ignore the GRANTs and clean up later
  2. Analyze the SYSIBM.SYSTABAUTH table to see if any GRANTs are there

Whichever way you choose, there will be work involved! However, as SYNONYMS are dying out, it is a good idea to start DROPping them as soon as you can.

I hope you liked this month’s Topic.

As always, any questions or comments would be most welcome!

TTFN,

Roy Boxwell

2015-11 z/OS Quick Security Audit – part 2

Which security values and security settings should never be left as default?

Let’s list your ROLES and Authorization IDs with some SQL queries and check the security ZPARMs

 

To complete this two part series, I want to do a deep dive today, down into the security innards of DB2, and to wrap up with a review of default values that can cause security concerns. A long time ago ROLEs were introduced, and, as you saw in the last newsletter, nearly all OWNERs have an associated indicator of whether they are a Role or an Authorization Id. With Roles came Trusted Contexts, and I hope that all of you out there using remote access have set up a whole bunch of Trusted Contexts.

Part 1 proposes a review of any and all GRANTs on the DB2 Directory and Catalog tables. Is your DB2 Catalog opened with a PUBLIC grant? Do you know how your DB2 z/OS System is looking on the security side ?

Role playing

To start this time, we will review the Roles that you have currently defined:

SELECT NAME
     , DEFINER
     , CASE DEFINERTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS DEFINERTYPE
 FROM SYSIBM.SYSROLES
 ORDER BY 1 , 2
 FETCH FIRST 50 ROWS ONLY
 WITH UR
 ;

If this finds no rows, then that is either brilliant – you have no dynamic access – or pretty bad – you are not using Roles.

Having found your list of Roles, make sure that they are all allowed and correct. Remove any that are not supposed to be there!

 

It’s all a matter of context

Now the three Trusted Context Tables are to be queried:

SELECT ENABLED
 , NAME
 , CONTEXTID
 , DEFINER
 , CASE DEFINERTYPE
 WHEN 'L' THEN 'ROLE   '
 WHEN ' ' THEN 'AUTH ID'
 ELSE          'UNKNOWN'
 END        AS DEFINERTYPE
 , DEFAULTROLE
 , CASE OBJECTOWNERTYPE
 WHEN 'L' THEN 'ROLE   '
 WHEN ' ' THEN 'AUTH ID'
 ELSE          'UNKNOWN'
 END        AS OBJECTOWNERTYPE
 , ALLOWPUBLIC
 , AUTHENTICATEPUBLIC
 , DEFAULTSECURITYLABEL
 FROM SYSIBM.SYSCONTEXT
 ORDER BY 3
 FETCH FIRST 50 ROWS ONLY
 WITH UR
 ;

This query just shows you what you have at the moment and whether or not it is active, plus the basic security information. The next two queries list out the actual details:

SELECT CONTEXTID
     , AUTHID 
     , AUTHENTICATE
     , ROLE
     , SECURITYLABEL
FROM SYSIBM.SYSCONTEXTAUTHIDS
ORDER BY 1
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT CONTEXTID
     , NAME
     , VALUE
FROM SYSIBM.SYSCTXTTRUSTATTRS
ORDER BY 1
FETCH FIRST 50 ROWS ONLY
WITH UR
;

Note that the key is always the CONTEXTID. The NAME and VALUE pair is where you actually find the details of how a Trusted Context is defined. Again, check and validate that all these values – and especially the IP addresses – are still valid.

 

Do I have your Permission?

Masks and Permissions came in a while ago but haven’t gained much traction in the DB2 user community yet. However, here is an SQL to show you what you do have:

 

SELECT ENABLE
     , CASE CONTROL_TYPE
       WHEN 'R' THEN 'ROW PERMISSION'
       WHEN 'M' THEN 'COLUMN MASK   '
       ELSE          'UNKNOWN       '
       END        AS CONTROL_TYPE
     , SCHEMA     AS CREATOR
     , NAME
     , OWNER
     , CASE OWNERTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS OWNERTYPE
FROM SYSIBM.SYSCONTROLS
ORDER BY 2 , 3 , 4
FETCH FIRST 50 ROWS ONLY
WITH UR
;

You can then easily see whether or not the permission/mask is active, or not.

 

SECADM to the rescue

If running with SECADM and Audit Policies, then this little query will show you what is going on:

SELECT AUDITPOLICYNAME
     , OBJECTSCHEMA
     , OBJECTNAME
     , CASE OBJECTTYPE
       WHEN 'C' THEN 'CLONE TABLE                  '
       WHEN 'P' THEN 'IMPLICIT TABLE FOR XML COLUMN'
       WHEN 'T' THEN 'TABLE                        '
       WHEN ' ' THEN 'XML, CLONE OR TABLE          '
       ELSE          'ERROR AT POLICY START TIME   '
       END AS OBJECTTYPE
     , CREATEDTS
     , ALTEREDTS
     , CASE DB2START
       WHEN 'Y' THEN 'STARTED AT DB2 START                '
       WHEN 'S' THEN 'STARTED AT DB2 START. SECADM TO STOP'
       WHEN 'N' THEN 'POLICY NOT STARTED AT DB2 START     '
       ELSE          'UNKNOWN                             '
       END AS DB2START
     , CASE CHECKING
       WHEN 'A' THEN 'AUDIT ALL FAILURES        '
       WHEN ' ' THEN 'AUDIT NONE                '
       ELSE          'ERROR AT POLICY START TIME'
       END AS CHECKING
     , CASE VALIDATE
       WHEN 'A' THEN 'AUDIT ALL FAILURES        '
       WHEN ' ' THEN 'AUDIT NONE                '
       ELSE          'ERROR AT POLICY START TIME'
       END AS VALIDATE
     , CASE OBJMAINT
       WHEN 'A' THEN 'AUDIT ALTER/DROP          '
       WHEN ' ' THEN 'AUDIT NONE                '
       ELSE          'ERROR AT POLICY START TIME'
       END AS OBJMAINT
     , CASE EXECUTE
       WHEN 'A' THEN 'AUDIT FIRST ACCESS        '
       WHEN 'C' THEN 'AUDIT FIRST UPDATE        '
       WHEN ' ' THEN 'AUDIT NONE                '
       ELSE          'ERROR AT POLICY START TIME'
       END AS EXECUTE
     , CASE CONTEXT
       WHEN 'A' THEN 'AUDIT ALL UTILITIES       '
       WHEN ' ' THEN 'AUDIT NONE                '
       ELSE          'ERROR AT POLICY START TIME'
       END AS CONTEXT
     , CASE SECMAINT
       WHEN 'A' THEN 'AUDIT ALL                 '
       WHEN ' ' THEN 'AUDIT NONE                '
       ELSE          'ERROR AT POLICY START TIME'
       END AS SECMAINT
     , SYSADMIN
     , DBADMIN
     , DBNAME
     , COLLID
FROM SYSIBM.SYSAUDITPOLICIES
ORDER BY 1
FETCH FIRST 50 ROWS ONLY
WITH UR
;

Now you can see what is happening with your policies, and are they working as designed?

 

Are you a ROLE model?

The next large set of queries returns *all* AUTH relevant DB2 catalog data from any DB2 Table that has any possible link to a ROLE:

 

SELECT GRANTOR
     , CASE GRANTORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTORTYPE
     , GRANTEE
     , CASE GRANTEETYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN 'P' THEN 'PACKAGE'
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTEETYPE
     , CREATOR
     , TNAME AS NAME
     , COLNAME
     , CASE PRIVILEGE
       WHEN 'R' THEN 'REFERENCES'
       WHEN ' ' THEN 'UPDATE    '
       ELSE          'UNKNOWN   '
       END AS PRIVILEGE
     , COLLID
     , HEX(CONTOKEN) AS CONTOKEN
FROM SYSIBM.SYSCOLAUTH
WHERE NOT GRANTOR = GRANTEE
ORDER BY CREATOR , NAME, COLNAME, GRANTOR, GRANTEE
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT GRANTOR
     , CASE GRANTORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTORTYPE
     , GRANTEE
     , CASE GRANTEETYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTEETYPE
     , NAME
     , CASE AUTHHOWGOT
       WHEN 'C' THEN 'DBCTRL    '
       WHEN 'D' THEN 'DBADM     '
       WHEN 'E' THEN 'SECADM    '
       WHEN 'G' THEN 'ACCESSCTRL'
       WHEN 'L' THEN 'SYSCTRL   '
       WHEN 'M' THEN 'DBMAINT   '
       WHEN 'S' THEN 'SYSADM    '
       WHEN ' ' THEN 'N/A       '
       ELSE          'UNKNOWN   '
       END AS AUTHHOWGOT
     , CREATETABAUTH
     , CREATETSAUTH
     , DBADMAUTH
     , DBCTRLAUTH
     , DBMAINTAUTH
     , DISPLAYDBAUTH
     , DROPAUTH
     , IMAGCOPYAUTH
     , LOADAUTH
     , REORGAUTH
     , RECOVERDBAUTH
     , REPAIRAUTH
     , STARTDBAUTH
     , STATSAUTH
     , STOPAUTH
FROM SYSIBM.SYSDBAUTH
WHERE NOT GRANTOR = GRANTEE
ORDER BY NAME, GRANTOR, GRANTEE
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT GRANTOR
     , CASE GRANTORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTORTYPE
     , GRANTEE
     , CASE GRANTEETYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN 'P' THEN 'PLAN   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTEETYPE
     , COLLID
     , NAME
     , CASE AUTHHOWGOT
       WHEN 'A' THEN 'PACKADM (COLLECTION *)    '
       WHEN 'C' THEN 'DBCTRL                    '
       WHEN 'D' THEN 'DBADM                     '
       WHEN 'E' THEN 'SECADM                    '
       WHEN 'G' THEN 'ACCESSCTRL                '
       WHEN 'L' THEN 'SYSCTRL                   '
       WHEN 'M' THEN 'DBMAINT                   '
       WHEN 'P' THEN 'PACKADM (NOT COLLECTION *)'
       WHEN 'S' THEN 'SYSADM                    '
       WHEN 'T' THEN 'DATAACCESS                '
       WHEN ' ' THEN 'N/A                       '
       ELSE          'UNKNOWN                   '
       END AS AUTHHOWGOT
     , BINDAUTH
     , COPYAUTH
     , EXECUTEAUTH
FROM SYSIBM.SYSPACKAUTH
WHERE NOT GRANTOR = GRANTEE
ORDER BY NAME, GRANTOR, GRANTEE
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT GRANTOR
     , CASE GRANTORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTORTYPE
     , GRANTEE
     , CASE GRANTEETYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTEETYPE
     , NAME
     , CASE AUTHHOWGOT
       WHEN 'C' THEN 'DBCTRL    '
       WHEN 'D' THEN 'DBADM     '
       WHEN 'E' THEN 'SECADM    '
       WHEN 'G' THEN 'ACCESSCTRL'
       WHEN 'L' THEN 'SYSCTRL   '
       WHEN 'M' THEN 'DBMAINT   '
       WHEN 'S' THEN 'SYSADM    '
       WHEN ' ' THEN 'N/A       '
       ELSE          'UNKNOWN   '
       END AS AUTHHOWGOT
     , BINDAUTH
     , EXECUTEAUTH
FROM SYSIBM.SYSPLANAUTH
WHERE NOT GRANTOR = GRANTEE
ORDER BY NAME, GRANTOR, GRANTEE
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT GRANTOR
     , CASE GRANTORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTORTYPE
     , GRANTEE
     , CASE GRANTEETYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTEETYPE
     , QUALIFIER
     , NAME
     , CASE AUTHHOWGOT
       WHEN 'A' THEN 'PACKADM (COLLECTION *)    '
       WHEN 'C' THEN 'DBCTRL                    '
       WHEN 'D' THEN 'DBADM                     '
       WHEN 'E' THEN 'SECADM                    '
       WHEN 'G' THEN 'ACCESSCTRL                '
       WHEN 'L' THEN 'SYSCTRL                   '
       WHEN 'M' THEN 'DBMAINT                   '
       WHEN 'P' THEN 'PACKADM (NOT COLLECTION *)'
       WHEN 'S' THEN 'SYSADM                    '
       WHEN 'T' THEN 'DATAACCESS                '
       WHEN ' ' THEN 'N/A                       '
       ELSE          'UNKNOWN                   '
       END AS AUTHHOWGOT
     , CASE OBTYPE
       WHEN 'B' THEN 'BUFFER POOL  '
       WHEN 'C' THEN 'COLLECTION   '
       WHEN 'D' THEN 'DISTINCT TYPE'
       WHEN 'R' THEN 'TABLE SPACE  '
       WHEN 'S' THEN 'STORAGE GROUP'
       WHEN 'J' THEN 'JAR FILE     '
       ELSE          'UNKNOWN      '
       END        AS OBJECT_TYPE
     , USEAUTH
FROM SYSIBM.SYSRESAUTH
WHERE NOT GRANTOR = GRANTEE
ORDER BY QUALIFIER, NAME, GRANTOR, GRANTEE
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT GRANTOR
     , CASE GRANTORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTORTYPE
     , GRANTEE
     , CASE GRANTEETYPE
       WHEN 'L' THEN 'ROLE             '
       WHEN 'P' THEN 'PLAN/PACKAGE     '
       WHEN 'R' THEN 'INTERNAL USE ONLY'
       WHEN ' ' THEN 'AUTH ID          '
       ELSE          'UNKNOWN          '
       END AS GRANTEETYPE
     , SCHEMA       AS CREATOR
     , SPECIFICNAME AS NAME
     , CASE ROUTINETYPE
       WHEN 'F' THEN 'UDF OR CAST FUNCTION'
       WHEN 'P' THEN 'STORED PROCEDURE    '
       ELSE          'UNKNOWN             '
       END        AS ROUTINETYPE
     , CASE AUTHHOWGOT     
       WHEN '1' THEN 'GRANTOR SCHEMA.* AT TIME'
       WHEN 'E' THEN 'SECADM                  '
       WHEN 'G' THEN 'ACCESSCTRL              '
       WHEN 'L' THEN 'SYSCTRL                 '
       WHEN 'S' THEN 'SYSADM                  '
       WHEN 'T' THEN 'DATAACCESS              '
       WHEN ' ' THEN 'N/A                     '
       ELSE          'UNKNOWN                 '
       END AS AUTHHOWGOT
     , EXECUTEAUTH
     , COLLID
     , HEX(CONTOKEN) AS CONTOKEN
FROM SYSIBM.SYSROUTINEAUTH
WHERE NOT GRANTOR = GRANTEE
ORDER BY CREATOR , NAME, GRANTOR, GRANTEE
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT GRANTOR
     , CASE GRANTORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTORTYPE
     , GRANTEE
     , CASE GRANTEETYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTEETYPE
     , SCHEMANAME
     , CASE AUTHHOWGOT
       WHEN '1' THEN 'GRANTOR SCHEMA.* AT TIME'
       WHEN 'E' THEN 'SECADM                  '
       WHEN 'G' THEN 'ACCESSCTRL              '
       WHEN 'L' THEN 'SYSCTRL                 '
       WHEN 'S' THEN 'SYSADM                  '
       ELSE          'UNKNOWN                 '
       END AS AUTHHOWGOT
     , CREATEINAUTH
     , ALTERINAUTH
     , DROPINAUTH
FROM SYSIBM.SYSSCHEMAAUTH
WHERE NOT GRANTOR = GRANTEE
ORDER BY SCHEMANAME, GRANTOR, GRANTEE
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT GRANTOR
     , CASE GRANTORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTORTYPE
     , GRANTEE
     , CASE GRANTEETYPE
       WHEN 'L' THEN 'ROLE             '
       WHEN 'P' THEN 'PLAN/PACKAGE     '
       WHEN 'R' THEN 'INTERNAL USE ONLY'
       WHEN ' ' THEN 'AUTH ID          '
       ELSE          'UNKNOWN          '
       END AS GRANTEETYPE
     , SCHEMA AS CREATOR
     , NAME
     , CASE AUTHHOWGOT
       WHEN ' ' THEN 'N/A       '
       WHEN 'E' THEN 'SECADM    '
       WHEN 'G' THEN 'ACCESSCTRL'
       WHEN 'L' THEN 'SYSCTRL   '
       WHEN 'S' THEN 'SYSADM    '
       WHEN 'T' THEN 'DATAACCESS'
       ELSE          'UNKNOWN   '
       END AS AUTHHOWGOT
     , ALTERAUTH
     , USEAUTH
     , COLLID
     , HEX(CONTOKEN) AS CONTOKEN
FROM SYSIBM.SYSSEQUENCEAUTH
WHERE NOT GRANTOR = GRANTEE
ORDER BY CREATOR, NAME, GRANTOR, GRANTEE
FETCH FIRST 50 ROWS ONLY
WITH UR
;

SELECT GRANTOR
     , CASE GRANTORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTORTYPE
     , GRANTEE
     , CASE GRANTEETYPE
       WHEN 'L' THEN 'ROLE        '
       WHEN 'P' THEN 'PLAN/PACKAGE'
       WHEN ' ' THEN 'AUTH ID     '
       ELSE          'UNKNOWN     '
       END AS GRANTEETYPE
     , DBNAME
     , TCREATOR AS CREATOR
     , TTNAME   AS NAME
     , CASE AUTHHOWGOT
       WHEN ' ' THEN 'N/A         '
       WHEN 'B' THEN 'SYSTEM DBADM'
       WHEN 'C' THEN 'DBCTRL      '
       WHEN 'E' THEN 'SECADM      '
       WHEN 'G' THEN 'ACCESSCTRL  '
       WHEN 'K' THEN 'SQLADM      '
       WHEN 'L' THEN 'SYSCTRL     '
       WHEN 'M' THEN 'DBMAINT     '
       WHEN 'S' THEN 'SYSADM      '
       WHEN 'T' THEN 'DATAACCESS  '
       ELSE          'UNKNOWN     '
       END AS AUTHHOWGOT
     , ALTERAUTH
     , DELETEAUTH
     , INDEXAUTH
     , INSERTAUTH
     , SELECTAUTH
     , UPDATEAUTH
     , REFERENCESAUTH
     , TRIGGERAUTH
     , UPDATECOLS
     , REFCOLS
     , COLLID
     , HEX(CONTOKEN) AS CONTOKEN
FROM SYSIBM.SYSTABAUTH
WHERE NOT GRANTOR = GRANTEE
ORDER BY CREATOR, NAME, GRANTOR, GRANTEE
FETCH FIRST 50 ROWS ONLY
WITH UR
;

SELECT GRANTOR
     , CASE GRANTORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTORTYPE
     , GRANTEE
     , CASE GRANTEETYPE
       WHEN 'L' THEN 'ROLE        '
       WHEN 'P' THEN 'PLAN/PACKAGE'
       WHEN ' ' THEN 'AUTH ID     '
       ELSE          'UNKNOWN     '
       END AS GRANTEETYPE
     , CASE AUTHHOWGOT
       WHEN ' ' THEN 'N/A       '
       WHEN 'C' THEN 'DBCTRL    '
       WHEN 'E' THEN 'SECADM    '
       WHEN 'G' THEN 'ACCESSCTRL'
       WHEN 'K' THEN 'SQLADM    '
       WHEN 'L' THEN 'SYSCTRL   '
       WHEN 'M' THEN 'DBMAINT   '
       WHEN 'O' THEN 'SYSOPR    '
       WHEN 'S' THEN 'SYSADM    '
       ELSE          'UNKNOWN   '
       END AS AUTHHOWGOT
     , BINDADDAUTH
     , BSDSAUTH
     , CREATEDBAAUTH
     , CREATEDBCAUTH
     , CREATESGAUTH
     , DISPLAYAUTH
     , RECOVERAUTH
     , STOPALLAUTH
     , STOSPACEAUTH
     , SYSADMAUTH
     , SYSOPRAUTH
     , TRACEAUTH
     , MON1AUTH
     , MON2AUTH
     , CREATEALIASAUTH
     , SYSCTRLAUTH
     , BINDAGENTAUTH
     , ARCHIVEAUTH
     , CREATETMTABAUTH
     , DEBUGSESSIONAUTH
     , EXPLAINAUTH
     , SQLADMAUTH
     , SDBADMAUTH
     , DATAACCESSAUTH
     , ACCESSCTRLAUTH
     , CREATESECUREAUTH
FROM SYSIBM.SYSUSERAUTH
WHERE NOT GRANTOR = GRANTEE
ORDER BY GRANTOR, GRANTEE
FETCH FIRST 50 ROWS ONLY
WITH UR
;

 

It’s a pretty good idea to modify all of the above with an appropriate GRANTOR = or GRANTEE = predicate, as otherwise there is too much data.

 

You can DEPend on me!

Nearly all objects in DB2 have a dependency on another object. All of this data is stored in the xxxxxDEP tables. Some of them also have ROLE based data that could well be of interest to the security minded Person:

SELECT BSCHEMA
     , BNAME
     , BTYPE
     , DTBCREATOR AS CREATOR
     , DTBNAME    AS NAME
     , DTBOWNER   AS OWNER
     , CASE OWNERTYPE
       WHEN 'R' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS OWNERTYPE
FROM SYSIBM.SYSCONSTDEP
ORDER BY DTBCREATOR , DTBNAME
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT BSCHEMA   AS CREATOR
     , BNAME      AS NAME
     , BCOLNAME   AS COLUMN_NAME
     , CASE BTYPE
       WHEN 'A' THEN 'ALIAS                   '
       WHEN 'C' THEN 'COLUMN                  '
       WHEN 'F' THEN 'FUNCTION                '
       WHEN 'G' THEN 'GLOBAL TEMPORARY TABLE  '
       WHEN 'M' THEN 'MATERIALIZED QUERY TABLE'
       WHEN 'Q' THEN 'SEQUENCE                '
       WHEN 'S' THEN 'SYNONYM                 '
       WHEN 'T' THEN 'TABLE                   '
       WHEN 'V' THEN 'VIEW                    '
       WHEN 'W' THEN 'SYSTEM_TIME PERIOD      '
       WHEN 'Z' THEN 'BUSINESS_TIME PERIOD    '
       ELSE          'UNKNOWN                 '
       END        AS TYPE
     , BOWNER     AS OWNER
     , CASE BOWNERTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS BOWNERTYPE
     , DSCHEMA    AS DEP_CREATOR
     , DNAME      AS DEP_NAME
     , DCOLNAME   AS DEP_COLUMN_NAME
     , CASE DTYPE
       WHEN 'C' THEN 'GENERATED COLUMN'
       WHEN 'F' THEN 'FUNCTION        '
       WHEN 'I' THEN 'INDEX           '
       WHEN 'X' THEN 'ROW PERMISSION  '
       WHEN 'Y' THEN 'COLUMN MASK     '
       ELSE          'UNKNOWN         '
       END        AS DEP_TYPE
     , DOWNER     AS DEP_OWNER
     , CASE DOWNERTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS DEP_OWNERTYPE
FROM SYSIBM.SYSDEPENDENCIES
ORDER BY 1 , 2 , 3 , 5 , 7 , 8 , 9 , 11
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT ROLENAME
     , DEFINER
     , CASE DEFINERTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS DEFINERTYPE
     , DSCHEMA    AS CREATOR
     , DNAME      AS NAME
     , CASE DTYPE
       WHEN 'A' THEN 'ALIAS                   '
       WHEN 'B' THEN 'TRIGGER                 '
       WHEN 'D' THEN 'DATABASE                '
       WHEN 'E' THEN 'DISTINCT TYPE           '
       WHEN 'F' THEN 'USER-DEFINED FUNCTION   '
       WHEN 'I' THEN 'INDEX                   '
       WHEN 'J' THEN 'JAR FILE                '
       WHEN 'L' THEN 'ROLE                    '
       WHEN 'M' THEN 'MATERIALIZED QUERY TABLE'
       WHEN 'N' THEN 'TRUSTED CONTEXT         '
       WHEN 'O' THEN 'STORED PROCEDURE        '
       WHEN 'Q' THEN 'SEQUENCE              '
       WHEN 'R' THEN 'TABLE SPACE             '
       WHEN 'S' THEN 'STORAGE GROUP           '
       WHEN 'T' THEN 'TABLE                   '
       WHEN 'V' THEN 'VIEW                    '
       WHEN 'X' THEN 'ROW PERMISSION          '
       WHEN 'Y' THEN 'COLUMN MASK             '
       ELSE          'UNKNOWN                 '
       END        AS TYPE
FROM SYSIBM.SYSOBJROLEDEP
ORDER BY 1 , 2
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT BQUALIFIER AS CREATOR
     , BNAME      AS NAME
    , CASE BTYPE
       WHEN 'A' THEN 'ALIAS                      '
       WHEN 'B' THEN 'BUSINESS_TIME              '
       WHEN 'C' THEN 'SYSTEM_TIME                '
       WHEN 'F' THEN 'UDF OR CAST FUNCTION       '
       WHEN 'G' THEN 'GLOBAL TEMPORARY TABLE     '
       WHEN 'I' THEN 'INDEX                      '
       WHEN 'M' THEN 'MATERIALIZED QUERY TABLE   '
       WHEN 'O' THEN 'STORED PROCEDURE           '
       WHEN 'P' THEN 'LARGE OR DSSIZE PART. SPACE'
       WHEN 'Q' THEN 'SEQUENCE OBJECT            '
       WHEN 'R' THEN 'TABLESPACE                 '
       WHEN 'S' THEN 'SYNONYM                    '
       WHEN 'T' THEN 'TABLE                      '
       WHEN 'U' THEN 'DISTINCT TYPE              '
       WHEN 'V' THEN 'VIEW                      '
       WHEN 'W' THEN 'SYSTEM_TIME PERIOD         '
       WHEN 'Z' THEN 'BUSINESS_TIME PERIOD       '
       ELSE          'UNKNOWN                    '
       END        AS OBJECT_TYPE
     , DCOLLID AS COLLECTION
     , DNAME   AS PACKAGE
     , HEX(DCONTOKEN) AS DCONTOKEN
     , CASE DTYPE
       WHEN 'F' THEN 'COMPILED SQL SCALAR FUNCTION    '
       WHEN 'N' THEN 'NATIVE SQL ROUTINE PACKAGE      '
       WHEN 'O' THEN 'ORIGINAL COPY OF A PACKAGE      '
       WHEN 'P' THEN 'PREVIOUS COPY OF A PACKAGE      '
       WHEN 'R' THEN 'RESERVED FOR IBM USE            '
       WHEN 'T' THEN 'TRIGGER PACKAGE                 '
       WHEN ' ' THEN 'NOT A TRIGGER/NATIVE SQL PACKAGE'
       ELSE          'UNKNOWN                         '
       END        AS PACKAGE_TYPE
     , DOWNER     AS OWNER
     , CASE DOWNERTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS DOWNERTYPE
FROM SYSIBM.SYSPACKDEP
ORDER BY 1 , 2 , 7
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT BCREATOR   AS CREATOR
     , BNAME      AS NAME
     , CASE BTYPE
       WHEN 'A' THEN 'ALIAS                      '
       WHEN 'E' THEN 'INSTEAD OF TRIGGER         '
       WHEN 'F' THEN 'UDF OR CAST FUNCTION       '
       WHEN 'G' THEN 'GLOBAL TEMPORARY TABLE     '
       WHEN 'I' THEN 'INDEX                      '
       WHEN 'M' THEN 'MATERIALIZED QUERY TABLE   '
       WHEN 'O' THEN 'STORED PROCEDURE           '
       WHEN 'P' THEN 'LARGE OR DSSIZE PART. SPACE'
       WHEN 'Q' THEN 'SEQUENCE OBJECT            '
       WHEN 'R' THEN 'TABLESPACE                 '
       WHEN 'S' THEN 'SYNONYM                    '
       WHEN 'T' THEN 'TABLE                      '
       WHEN 'V' THEN 'VIEW                       '
       ELSE          'UNKNOWN                    '
       END        AS OBJECT_TYPE
     , DNAME   AS PLAN_NAME
FROM SYSIBM.SYSPLANDEP
ORDER BY 1 , 2
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT DCREATOR   AS CREATOR
     , DNAME      AS NAME
     , DCOLNAME   AS COLNAME
     , CASE DTYPE
       WHEN 'F' THEN 'SQL FUNCTION       '
       WHEN 'I' THEN 'IDENTITY COLUMN    '
       WHEN 'X' THEN 'IMPLICIT DOCID     '
       WHEN ' ' THEN 'OLD IDENTITY COLUMN'
       ELSE          'UNKNOWN            '
       END        AS SEQUENCETYPE
     , DOWNER     AS OWNER
     , CASE DOWNERTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS OWNERTYPE
FROM SYSIBM.SYSSEQUENCESDEP
ORDER BY CREATOR , NAME
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT BCREATOR   AS CREATOR
     , BNAME      AS NAME
     , CASE BTYPE
       WHEN 'F' THEN 'UDF OR CAST FUNCTION    '
       WHEN 'G' THEN 'GLOBAL TEMPORARY TABLE  '
       WHEN 'M' THEN 'MATERIALIZED QUERY TABLE'
       WHEN 'T' THEN 'TABLE                   '
       WHEN 'V' THEN 'VIEW                    '
       WHEN 'W' THEN 'SYSTEM_TIME PERIOD      '
       WHEN 'Z' THEN 'BUSINESS_TIME PERIOD    '
       ELSE          'UNKNOWN                 '
       END        AS OBJECT_TYPE
     , DNAME    AS VIEW_NAME
     , DCREATOR AS VIEW_CREATOR
     , CASE DTYPE
       WHEN 'F' THEN 'COMPILED SQL SCALAR FUNCTION'
       WHEN 'M' THEN 'MATERIALIZED QUERY TABLE    '
       WHEN 'V' THEN 'VIEW                      '
       ELSE          'UNKNOWN                     '
       END        AS TABLE_TYPE
     , DOWNER     AS OWNER
     , CASE OWNERTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS OWNERTYPE
FROM SYSIBM.SYSVIEWDEP
ORDER BY 1 , 2 , 4 , 5
FETCH FIRST 50 ROWS ONLY
WITH UR
;

Again, judicious use of extra WHERE predicates is recommended!

 

ROLE based meta-data

Then there is the “base” data of the objects themselves, which can have ROLE based information in it.

SELECT NAME
     , CREATOR
     , CASE CREATORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS CREATORTYPE
FROM SYSIBM.SYSDATABASE
ORDER BY 1 , 2
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT SCHEMA     AS CREATOR
     , NAME
     , OWNER
     , CASE OWNERTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS OWNERTYPE
FROM SYSIBM.SYSDATATYPES
ORDER BY 1 , 2
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT NAME
     , PLNAME AS PLAN_NAME
     , PLCREATOR AS CREATOR
     , CASE PLCREATORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS PLCREATORTYPE
FROM SYSIBM.SYSDBRM
ORDER BY NAME, 2
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT CREATOR
     , NAME
     , OWNER
     , CASE OWNERTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS OWNERTYPE
FROM SYSIBM.SYSINDEXES
ORDER BY 3 , 1 , 2
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT JARSCHEMA AS CREATOR
     , JAR_ID AS NAME
     , OWNER
     , CASE OWNERTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS OWNERTYPE
FROM SYSIBM.SYSJAROBJECTS
ORDER BY 3 , 1 , 2
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT COLLID AS COLLECTION
     , NAME   AS PACKAGE
     , HEX(CONTOKEN) AS CONTOKEN
     , CREATOR
     , OWNER
     , CASE OWNERTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS OWNERTYPE
FROM SYSIBM.SYSPACKAGE
ORDER BY 1 , 2 , 3
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT COLLID AS COLLECTION
     , NAME   AS PACKAGE
     , HEX(CONTOKEN) AS CONTOKEN
     , COPYID
     , CREATOR
     , OWNER
     , CASE OWNERTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS OWNERTYPE
FROM SYSIBM.SYSPACKCOPY
ORDER BY 1 , 2 , 3 , 4
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT SCHEMA     AS CREATOR
     , NAME       AS NAME
     , OWNER      AS OWNER
     , CASE OWNERTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS OWNERTYPE
FROM SYSIBM.SYSPARMS
ORDER BY 1 , 2 , 3
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT CREATOR
     , CASE CREATORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS CREATORTYPE
     , NAME       AS NAME
     , BOUNDBY
FROM SYSIBM.SYSPLAN
ORDER BY 1
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT SCHEMA     AS CREATOR
     , NAME
     , OWNER
     , CASE OWNERTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS OWNERTYPE
     , ACTIVE
     , CASE ROUTINETYPE
       WHEN 'F' THEN 'UDF OR CAST FUNCTION'
       WHEN 'P' THEN 'STORED PROCEDURE    '
       ELSE          'UNKNOWN             '
       END        AS ROUTINETYPE
     , CASE EXTERNAL_SECURITY
       WHEN 'D' THEN 'DB2 - AUTH ID FROM WLM               '
       WHEN 'U' THEN 'SESSION_USER - AUTH ID OF INVOKER    '
       WHEN 'C' THEN 'DEFINER - AUTH ID OF OWNER OF ROUTINE'
       WHEN ' ' THEN 'N/A                                  '
       ELSE          'UNKNOWN                              '
       END        AS ROUTINETYPE
     , SPECIFICNAME
FROM SYSIBM.SYSROUTINES
ORDER BY CREATOR , NAME
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT SCHEMA     AS CREATOR
     , NAME
     , OWNER
     , CASE OWNERTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS OWNERTYPE
     , CASE SEQTYPE
       WHEN 'I' THEN 'IDENTITY COLUMN      '
       WHEN 'S' THEN 'USER-DEFINED SEQUENCE'
       WHEN 'X' THEN 'IMPLICIT DOCID       '
       ELSE          'UNKNOWN              '
       END        AS SEQUENCETYPE
FROM SYSIBM.SYSSEQUENCES
ORDER BY CREATOR , NAME
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT NAME       AS CREATOR
     , PLNAME     AS PLAN_NAME
     , PLCREATOR  AS CREATOR
     , CASE PLCREATORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS PLCREATORTYPE
FROM SYSIBM.SYSSTMT
ORDER BY 2 , 1
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT NAME
     , CREATOR
     , CASE CREATORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS CREATORTYPE
     , CREATEDBY
FROM SYSIBM.SYSSTOGROUP
ORDER BY 1 , 2
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT NAME
     , CREATOR
     , CASE CREATORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS CREATORTYPE
     , TBCREATOR
     , TBNAME
     , CREATEDBY
FROM SYSIBM.SYSSYNONYMS
ORDER BY 1 , 2
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT OWNER
     , CASE OWNERTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS OWNERTYPE
     , NAME
     , CREATOR
     , CASE TYPE
       WHEN 'A' THEN 'ALIAS                                    '
       WHEN 'C' THEN 'CLONE TABLE                              '
       WHEN 'G' THEN 'CREATED GLOBAL TEMPORARY TABLE           '
       WHEN 'H' THEN 'HISTORY TABLE                            '
       WHEN 'M' THEN 'MATERIALIZED QUERY TABLE                 '
       WHEN 'P' THEN 'TABLE THAT WAS IMPLICITLY CREATED FOR XML'
       WHEN 'T' THEN 'TABLE                                    '
       WHEN 'V' THEN 'VIEW                                     '
       WHEN 'X' THEN 'AUXILIARY TABLE                          '
       ELSE          'UNKNOWN                                  '
       END AS TABLE_TYPE
     , CASE AUDITING
       WHEN ' ' THEN '            '
       WHEN 'A' THEN 'AUDIT ALL   '
       WHEN 'C' THEN 'AUDIT CHANGE'
       ELSE          'UNKNOWN     '
       END AS AUDIT_LEVEL
     , TABLESTATUS
     , CASE SECURITY_LABEL
       WHEN ' ' THEN '       '
       WHEN 'R' THEN 'MLS    '
       ELSE          'UNKNOWN'
       END AS SECURITY_LABEL
     , CASE CONTROL
       WHEN ' ' THEN 'NO ACCESS CONTROL ENFORCEMENT'
       WHEN 'B' THEN 'ROW AND COLUMN ACCESS CONTROL'
       WHEN 'C' THEN 'COLUMN ACCESS CONTROL        '
       WHEN 'R' THEN 'ROW ACCESS CONTROL           '
       ELSE          'UNKNOWN                      '
       END AS SECURITY_LABEL
     , CREATEDBY
FROM SYSIBM.SYSTABLES
ORDER BY 1 , 2
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT
       DBNAME
     , NAME
     , CREATOR
     , CASE CREATORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS CREATORTYPE
     , CASE TYPE
       WHEN ' ' THEN 'NORMAL '
       WHEN 'G' THEN 'PBG    '
       WHEN 'L' THEN 'LARGE  '
       WHEN 'O' THEN 'LOB    '
       WHEN 'P' THEN 'XML PBG'
       WHEN 'R' THEN 'PBR    '
       ELSE          'UNKNOWN'
       END AS SPACE_TYPE     , CASE STATUS
       WHEN 'A' THEN 'OK                    '
       WHEN 'C' THEN 'PI MISSING            '
       WHEN 'P' THEN 'CHECKP STATUS         '
       WHEN 'S' THEN 'CHECKP STATS ON A PART'
       WHEN 'T' THEN 'NO TABLE DEFINED      '
       ELSE          'UNKNOWN               '
       END AS STATUS
     , CREATEDBY
FROM SYSIBM.SYSTABLESPACE
ORDER BY 1 , 2
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT SCHEMA AS CREATOR
     , NAME
     , OWNER
     , CASE OWNERTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS OWNERTYPE
     , SECURE
     , CASE TRIGTIME
       WHEN 'A' THEN 'AFTER  '
       WHEN 'B' THEN 'BEFORE '
       WHEN 'I' THEN 'INSTEAD'
       ELSE          'UNKNOWN'
       END AS TRIGGER_TIME
     , CREATEDBY
FROM SYSIBM.SYSTRIGGERS
ORDER BY 1 , 2
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT CREATOR
     , NAME
     , OWNER
     , CASE OWNERTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS OWNERTYPE
     , CASE TYPE
       WHEN 'F' THEN 'UDF OR CAST FUNCTION    '
       WHEN 'M' THEN 'MATERIALIZED QUERY TABLE'
       WHEN 'V' THEN 'VIEW                    '
       ELSE          'UNKNOWN                 '
       END        AS TABLE_TYPE
FROM SYSIBM.SYSVIEWS
ORDER BY 1 , 2
FETCH FIRST 50 ROWS ONLY
WITH UR
;

Once more: Add your own WHERE predicates here please!

 

Lost in translation

Finally, and the last SQL for this newsletter, is for the Inbound and Outbound AUTHID translation table:

SELECT AUTHID
     , CASE TYPE
       WHEN 'I' THEN 'INBOUND AND COME-FROM CHECKING               '
       WHEN 'O' THEN 'OUTBOUND TRANSLATION                         '
       WHEN 'S' THEN 'OUTBOUND SYSTEM AUTHID FOR TRUSTED CONNECTION'
       ELSE          'UNKNOWN                                      '
       END        AS NAME_TYPE
     , NEWAUTHID
FROM SYSIBM.USERNAMES
ORDER BY 1
FETCH FIRST 50 ROWS ONLY
WITH UR
;

We have now gone through all the Role based, and some more, DB2 Catalog tables. What about seeing what is happening on your machine? Have you anything in place that can give you 100% coverage of audit issues? With Software Engineering’s SQL WorkloadExpert for DB2 z/OS you can audit everything that is running in your enterprise. For example here is a view of the Audit pop-up window:
DB2 z/OS newsletter 2015-11: DB2 Quick Security Audit -Part 2

 

In the bottom half you can see the Authorization failures radio button. This shows all -551 SQL Codes and also the +562 “ping” of a double GRANT. Why this? Well, to prove that the Audit is actually alive and well you should do a “dummy” GRANT every day like, for example,

GRANT SELECT ON SYSIBM.SYDUMMY1 TO PUBLIC ;

that is already there and therefore gets a +562 which is also externalized and available in this selection. This way auditors can see that the Audit trace was running and so any -551 would also be there.

You also get GRANTs and REVOKEs and DDL that is running – optionally the software can even generate the DDL so you can follow the lifecycle of changes over time. All very handy stuff and available real-time!

 

Death by Default?

Now onto the last part of these newsletters: Default settings which can harm security.

Here’s a little list of any security ZPARM or BSDS settings that should never ever be left “as default”.

What Default  Where
 Catalog Alias DSNCAT CATALOG Zparm
 Group Name DSNCAT GRPNAME Zparm
 Member Name DSN1 MEMBNAME Zparm
 SSID DSN1 DSNHDECP module
 Command prefix –DSN1 n/a
 SYSADM 1 SYSADM SYSADM Zparm
 SYSADM 2 SYSADM SYSADM2 Zparm
 SYSOPER 1 SYSOPER SYSOPER Zparm
SYSOPER 2SYSOPERSYSOPER2 Zparm
Security Admin 1SECADMSECADM1 Zparm
Security Admin 2SECADMSECADM2 Zparm
Unknown UseridIBMUSERDEFLTID Zparm
If using DDF:
DB2 Location NameLOC1BSDS
DB2 LU NameLU1BSDS
DRDA Port446BSDS
SECURE Port448BSDS

 

If you have any of the above values in your shop – Time to plan some changes!

I hope you enjoyed this last part of a Quick Security Audit. Thanks again for reaching the end.

As always, any questions or comments would be most welcome!

 

TTFN,

Roy Boxwell

BIF HealthCheck Licensed Freeware for DB2 11

Detect static and dynamic SQL and match to the relevant collection, packages,…

BIF HealthCheck overview (Built-in Function Checker for DB2 z/OS)

BIF HealthCheck reports the following BIF incompatibilities in DB2 11

  • Execution of the DB2 9 for z/OS version of SYSIBM.CHAR(DECIMAL-EXPR)
  • Execution of the DB2 9 for z/OS version of SYSIBM.VARCHAR(DECIMAL-EXPR), CAST (DECIMAL AS VARCHAR), OR CAST (DECIMAL AS CHAR)

  • Use of an unsupported character string representation of a TIMESTAMP
  • Use of the DB2 10 for z/OS default SQL path instead of the V11 path, which has more implicit Schemas

  • Execution of a non-Java client that called a Stored Procedure (SP) that is on the DB2 for z/OS Data Server, while subsystem parameter DDF_COMPATIBILITY was set to SP_PARMS_NJV (the Data Server returned output argument values whose data types matched the data types of the call statement arguments).
  • Execution of an insert statement that inserts into an XML column without the XMLDOCUMENT function, which generates SQLCODE -20345 on a DB2 release prior to V11, but does not generate an error starting in V11

  • V10 XPATH evaluation behavior was in effect, which resulted in an error (e.g. a data type conversion error occurred for a predicate that would otherwise be evaluated to false.). Starting in V11, such errors might be suppressed

  • Execution of a SQL statement by a client non-Java, or Java application that included an unsupported conversion from a string type to a numeric type, or from a numeric type to a string type while the DB2 z/OS Data Server environment was one of the following (the Data Server issues SQLCODE -301)

• The Data Server was in version 11 New-Function Mode (NFM)
• APPLICATION COMPATIBILITY was set to V10R1
• Implicit casting was disabled because subsystem parameter DDF_COMPATIBILITY was set to SP_PARMS_NJV, or DISABLE_IMPCAST_NJV

BIF incompatibilities in DB2 10

 

More about BIF

BIF-Usage

Presentation

BIF CompatibilityDB2 10 compatibility mode
Changes to the STRING formating of decimal data within the CHAR and VARCHAR built-in function and to the CAST specification with CHAR and VARCHAR result types as well as  UNSUPPORTED TIMESTAMP STRINGs.
White PaperFinding BIFsAnd How to Lead a Problem-Free Life With Them in the Future
Navigating the Challenges of moving to a new DB2 Release
Newsletter2015-01 – BIFCIDS – Where’s the BIF?How will you deal with loop-hole usage in production code?
VideoBIF Usage(11min.) Trap  and correct the BIFs that will cause belly-ache one day soon
“Give and Take”
Program” page
 Give and Take
Program
We have “GIVEn” various free-of-charge Use Cases from SQL Workload Expert for DB2 z/OS like
1  Index Maintenance Costs
2  EXPLAIN Suppression
3  BIF Usage
4  BIF Healthcheck (Freeware) – This last one is still available
We TAKE the anonymized results for research
and will communicate with the local User Groups for discussions
 User StatementsBIF Usage:

“Give and Take
Program 3”

 Customer CommentsRead the Customer Comments across the Industry

  • Health Care
  • Insurance
  • Banking
  • Car Manufacturing

BIF HealthCheck licensed Freeware for DB2 10

Detect static and dynamic SQL and match to the relevant collection, packages,…

BIF HealthCheck overvew (Built-in Function Checker for DB2 z/OS)

BIF HealthCheck reports the following BIF incompatibilities in DB2 10

  • Execution of the DB2 9 for z/OS version of SYSIBM.CHAR(DECIMAL-EXPR)
  • Execution of the DB2 9 for z/OS version of SYSIBM.VARCHAR(DECIMAL-EXPR), CAST (DECIMAL AS VARCHAR), OR CAST (DECIMAL AS CHAR)

  • Use of an unsupported character string representation of a TIMESTAMP
  • Use of a USER-DEFINED FUNCTION (UDF) that has the unqualified name ARRAY_EXISTS
  • Use of a USER-DEFINED FUNCTION (UDF) that has the unqualified name CUBE
  • Use of a USER-DEFINED FUNCTION (UDF) that has the unqualified name ROLLUP

  • Execution of a non-Java client that called a Stored Procedure (SP) that is on the DB2 for z/OS Data Server, while subsystem parameter DDF_COMPATIBILITY was set to SP_PARMS_NJV (the Data Server returned output argument values whose data types matched the data types of the call statement arguments).

  • Execution of a SQL statement by a client non-Java application that included an unsupported conversion from a string type to a numeric type, while the DB2 z/OS Data Server environment was one of the following (the Data Server issues SQLCODE -301)
    • In version 10 Conversion Mode (CM)
    • In version 10 New-Function Mode (NFM) and implicit casting was disabled because subsystem parameter DDF_COMPATIBILITY was set to SP_PARMS_NJV, or DISABLE_IMPCAST_NJ

 

BIF incompatibilities in DB2 11

 

More about BIF

BIF-Usage

Presentation

BIF CompatibilityDB2 10 compatibility mode
Changes to the STRING formating of decimal data within the CHAR and VARCHAR built-in function and to the CAST specification with CHAR and VARCHAR result types as well as  UNSUPPORTED TIMESTAMP STRINGs.
White PaperFinding BIFsAnd How to Lead a Problem-Free Life With Them in the Future
Navigating the Challenges of moving to a new DB2 Release
Newsletter2015-01 – BIFCIDS – Where’s the BIF?How will you deal with loop-hole usage in production code?
VideoBIF Usage(11min.) Trap  and correct the BIFs that will cause belly-ache one day soon
“Give and Take”
Program” page
 Give and Take
Program
We have “GIVEn” various free-of-charge Use Cases from SQL Workload Expert for DB2 z/OS like
1  Index Maintenance Costs
2  EXPLAIN Suppression
3  BIF Usage 
BIF HealthCheck – This last one is still available
We TAKE the anonymized results for research
and will communicate with the local User Groups for discussions
 User StatementsBIF Usage:

“Give and Take
Program 3”

 Customer CommentsRead the Customer Comments across the Industry

  • Health Care
  • Insurance
  • Banking
  • Car Manufacturing

2015-10 DB2 Quick Security Audit – part 1

Is your DB2 Catalog opened with a PUBLIC grant?

Do you know how your DB2 z/OS System is looking on the security side ?

Today, I’d like to offer up some help around Audit and Security – always an issue. Please bear with me, as this is a really long newsletter. In fact, I had to make it into two parts. In this first part I wish to share a bunch of SQLs with you that will give a quick appraisal of how your DB2 system is looking – on the Security side of things. In the second part, we will then delve down more into Roles and conducting a deep analysis of your DB2 Catalog as well as quick review of any defaults that can cause security risks.

To get the ball rolling, let’s review any and all GRANTs on the DB2 Directory and Catalog tables. I know lots of shops where the whole Catalog is simply open with a PUBLIC grant, or two. Perhaps you should reconsider that these days? Remember that in the RUNSTATS data there are indeed data values stored in the Catalog.

Part 2 is dedicated to a deep Analysis of your DB2 Catalog (Newsletter 2015-11)

 

Let’s start the System appraisal with some SQLs… by applying the following laws:

0.Catalog and Directory Special Cases

1.With GRANT OPTION is a bad idea

2.Know your SYSADM userids

3.Is anything PUBLIC?

4.“Trusted” Trusted Contexts?

 

 

Catalog and Directory Special Cases

The first SQL is for Packages and Plans that access the Catalog:

SELECT A.GRANTOR
     , CASE A.GRANTORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
END AS GRANTORTYPE
     , A.GRANTEE
     , CASE A.GRANTEETYPE
       WHEN 'L' THEN 'ROLE        '
       WHEN 'P' THEN 'PLAN/PACKAGE'
       WHEN ' ' THEN 'AUTH ID     '
       ELSE          'UNKNOWN     '
END AS GRANTEETYPE
     , A.DBNAME
     , A.TCREATOR AS CREATOR
     , A.TTNAME   AS NAME
     , CASE A.AUTHHOWGOT
       WHEN ' ' THEN 'N/A         '
       WHEN 'B' THEN 'SYSTEM DBADM'
       WHEN 'C' THEN 'DBCTRL      '
       WHEN 'E' THEN 'SECADM      '
       WHEN 'G' THEN 'ACCESSCTRL  '
       WHEN 'K' THEN 'SQLADM      '
       WHEN 'L' THEN 'SYSCTRL     '
       WHEN 'M' THEN 'DBMAINT     '
       WHEN 'S' THEN 'SYSADM      '
       WHEN 'T' THEN 'DATAACCESS  '
       ELSE          'UNKNOWN     '
       END AS AUTHHOWGOT
     , A.ALTERAUTH
     , A.DELETEAUTH
     , A.INDEXAUTH
     , A.INSERTAUTH
     , A.SELECTAUTH
     , A.UPDATEAUTH
     , A.REFERENCESAUTH
     , A.TRIGGERAUTH
     , A.UPDATECOLS
     , A.REFCOLS
     , A.COLLID
     , HEX(A.CONTOKEN) AS CONTOKEN
FROM SYSIBM.SYSTABAUTH A
     , SYSIBM.SYSTABLES  B
WHERE NOT A.GRANTOR = A.GRANTEE
 AND A.GRANTEETYPE  = 'P'
 AND B.DBNAME IN ('DSNDB01', 'DSNDB06', 'DSNXSR' )
 AND B.TYPE    = 'T'
 AND B.CREATOR = A.TCREATOR
 AND B.NAME    = A.TTNAME
ORDER BY CREATOR, NAME, A.GRANTOR, A.GRANTEE
FETCH FIRST 50 ROWS ONLY
WITH UR
;

Note that this query is decoding various fields for you as well – especially the Role of the Grantor/Grantee – and you will see this all the way through the following queries. You will also see the “FETCH FIRST 50 ROWS ONLY”, as you might have vastly more info than can easily be reviewed. Feel free to add predicates for your shop!

Now we want to see all the non-plan/package GRANTs:

SELECT A.GRANTOR
     , CASE A.GRANTORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTORTYPE
     , A.GRANTEE
     , CASE A.GRANTEETYPE
       WHEN 'L' THEN 'ROLE        '
       WHEN 'P' THEN 'PLAN/PACKAGE'
       WHEN ' ' THEN 'AUTH ID     '
       ELSE          'UNKNOWN     '
       END AS GRANTEETYPE
     , A.DBNAME
     , A.TCREATOR AS CREATOR
     , A.TTNAME   AS NAME
     , CASE A.AUTHHOWGOT
       WHEN ' ' THEN 'N/A         '
       WHEN 'B' THEN 'SYSTEM DBADM'
       WHEN 'C' THEN 'DBCTRL      '
       WHEN 'E' THEN 'SECADM      '
       WHEN 'G' THEN 'ACCESSCTRL  '
       WHEN 'K' THEN 'SQLADM      '
       WHEN 'L' THEN 'SYSCTRL     '
       WHEN 'M' THEN 'DBMAINT     '
       WHEN 'S' THEN 'SYSADM      '
       WHEN 'T' THEN 'DATAACCESS  '
       ELSE          'UNKNOWN     '
       END AS AUTHHOWGOT
     , A.ALTERAUTH
     , A.DELETEAUTH
     , A.INDEXAUTH
     , A.INSERTAUTH
     , A.SELECTAUTH
     , A.UPDATEAUTH
     , A.REFERENCESAUTH
     , A.TRIGGERAUTH
     , A.UPDATECOLS
     , A.REFCOLS
     , A.COLLID
     , HEX(A.CONTOKEN) AS CONTOKEN
FROM SYSIBM.SYSTABAUTH A
   , SYSIBM.SYSTABLES  B
WHERE NOT A.GRANTOR = A.GRANTEE
 AND NOT A.GRANTEETYPE = 'P'
 AND B.DBNAME IN ('DSNDB01', 'DSNDB06', 'DSNXSR' )
 AND B.TYPE    = 'T'
 AND B.CREATOR = A.TCREATOR
 AND B.NAME    = A.TTNAME
ORDER BY CREATOR, NAME, A.GRANTOR, A.GRANTEE
FETCH FIRST 50 ROWS ONLY
WITH UR
;

Here it gets interesting when you have “G’s” in the xxxxAUTH columns of course! See later for the “First Law”.

Next, I would like to see whatever has been GRANTed to public:

SELECT A.GRANTOR
     , CASE A.GRANTORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTORTYPE
     , A.GRANTEE
     , CASE A.GRANTEETYPE
       WHEN 'L' THEN 'ROLE        '
       WHEN 'P' THEN 'PLAN/PACKAGE'
       WHEN ' ' THEN 'AUTH ID     '
       ELSE          'UNKNOWN     '
       END AS GRANTEETYPE
     , A.DBNAME
     , A.TCREATOR AS CREATOR
     , A.TTNAME   AS NAME
     , CASE A.AUTHHOWGOT
       WHEN ' ' THEN 'N/A         '
       WHEN 'B' THEN 'SYSTEM DBADM'
       WHEN 'C' THEN 'DBCTRL      '
       WHEN 'E' THEN 'SECADM      '
       WHEN 'G' THEN 'ACCESSCTRL  '
       WHEN 'K' THEN 'SQLADM      '
       WHEN 'L' THEN 'SYSCTRL     '
       WHEN 'M' THEN 'DBMAINT     '
       WHEN 'S' THEN 'SYSADM      '
       WHEN 'T' THEN 'DATAACCESS  '
       ELSE          'UNKNOWN     '
       END AS AUTHHOWGOT
     , A.ALTERAUTH
     , A.DELETEAUTH
     , A.INDEXAUTH
     , A.INSERTAUTH
     , A.SELECTAUTH
     , A.UPDATEAUTH
     , A.REFERENCESAUTH
     , A.TRIGGERAUTH
     , A.UPDATECOLS
     , A.REFCOLS
     , A.COLLID
     , HEX(A.CONTOKEN) AS CONTOKEN
FROM SYSIBM.SYSTABAUTH A
   , SYSIBM.SYSTABLES  B
WHERE NOT A.GRANTOR = A.GRANTEE
 AND B.DBNAME IN ('DSNDB01', 'DSNDB06', 'DSNXSR' )
 AND B.TYPE    = 'T'
 AND B.CREATOR = A.TCREATOR
 AND B.NAME    = A.TTNAME
 AND ( A.GRANTOR = 'PUBLIC'
    OR A.GRANTOR = 'PUBLIC*'
    OR A.GRANTEE = 'PUBLIC'
    OR A.GRANTEE = 'PUBLIC*' )
ORDER BY CREATOR, NAME, A.GRANTOR, A.GRANTEE
FETCH FIRST 50 ROWS ONLY
WITH UR
;

Ok that’s the “special” case of the Catalog and Directory. Now onto the “normal” Catalog tables, to check what is in them, and whether it matches up to modern ideas of security, or not.

First Law: WITH GRANT OPTION is a bad idea

SELECT GRANTOR
    , CASE GRANTORTYPE
      WHEN 'L' THEN 'ROLE   '
      WHEN ' ' THEN 'AUTH ID'
      ELSE         'UNKNOWN'
 END AS GRANTORTYPE
    , GRANTEE
    , CASE GRANTEETYPE
      WHEN 'L' THEN 'ROLE   '
      WHEN ' ' THEN 'AUTH ID'
      ELSE         'UNKNOWN'
      END AS GRANTEETYPE
    , NAME
    , CASE AUTHHOWGOT
      WHEN 'C' THEN 'DBCTRL   '
      WHEN 'D' THEN 'DBADM     '
      WHEN 'E' THEN 'SECADM   '
      WHEN 'G' THEN 'ACCESSCTRL'
      WHEN 'L' THEN 'SYSCTRL   '
      WHEN 'M' THEN 'DBMAINT   '
      WHEN 'S' THEN 'SYSADM   '
      WHEN ' ' THEN 'N/A       '
      ELSE         'UNKNOWN   '
 END AS AUTHHOWGOT
    , CREATETABAUTH
    , CREATETSAUTH
    , DBADMAUTH
    , DBCTRLAUTH
    , DBMAINTAUTH
    , DISPLAYDBAUTH
    , DROPAUTH
    , IMAGCOPYAUTH
    , LOADAUTH
    , REORGAUTH
    , RECOVERDBAUTH
    , REPAIRAUTH
    , STARTDBAUTH
    , STATSAUTH
    , STOPAUTH
 FROM SYSIBM.SYSDBAUTH
 WHERE NOT GRANTOR = GRANTEE
  AND ( CREATETABAUTH = 'G'
   OR CREATETSAUTH = 'G'
   OR DBADMAUTH     = 'G'
   OR DBCTRLAUTH   = 'G'
   OR DBMAINTAUTH   = 'G'
   OR DISPLAYDBAUTH = 'G'
   OR DROPAUTH     = 'G'
   OR IMAGCOPYAUTH = 'G'
   OR LOADAUTH     = 'G'
   OR REORGAUTH     = 'G'
   OR RECOVERDBAUTH = 'G'
   OR REPAIRAUTH   = 'G'
   OR STARTDBAUTH   = 'G'
   OR STATSAUTH     = 'G'
   OR STOPAUTH     = 'G' )
 ORDER BY NAME, GRANTOR, GRANTEE
 FETCH FIRST 50 ROWS ONLY
 WITH UR
 ;
SELECT GRANTOR
   , CASE GRANTORTYPE
     WHEN 'L' THEN 'ROLE   '
     WHEN ' ' THEN 'AUTH ID'
     ELSE         'UNKNOWN'
 END AS GRANTORTYPE
   , GRANTEE
   , CASE GRANTEETYPE
     WHEN 'L' THEN 'ROLE   '
     WHEN 'P' THEN 'PLAN   '
     WHEN ' ' THEN 'AUTH ID'
     ELSE         'UNKNOWN'
 END AS GRANTEETYPE
   , COLLID
   , NAME
   , CASE AUTHHOWGOT
     WHEN 'A' THEN 'PACKADM (COLLECTION *)   '
     WHEN 'C' THEN 'DBCTRL                  '
     WHEN 'D' THEN 'DBADM                     '
     WHEN 'E' THEN 'SECADM                   '
     WHEN 'G' THEN 'ACCESSCTRL               '
     WHEN 'L' THEN 'SYSCTRL                   '
     WHEN 'M' THEN 'DBMAINT                  '
     WHEN 'P' THEN 'PACKADM (NOT COLLECTION *)'
     WHEN 'S' THEN 'SYSADM                   '
     WHEN 'T' THEN 'DATAACCESS               '
     WHEN ' ' THEN 'N/A                       '
     ELSE         'UNKNOWN                   '
     END AS AUTHHOWGOT
   , BINDAUTH
   , COPYAUTH
   , EXECUTEAUTH
 FROM SYSIBM.SYSPACKAUTH
 WHERE NOT GRANTOR = GRANTEE
  AND ( BINDAUTH   = 'G'
   OR COPYAUTH   = 'G'
   OR EXECUTEAUTH = 'G' )
 ORDER BY NAME, GRANTOR, GRANTEE
 FETCH FIRST 50 ROWS ONLY
 WITH UR
 ;
SELECT GRANTOR
     , CASE GRANTORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE         'UNKNOWN'
       END AS GRANTORTYPE
     , GRANTEE
     , CASE GRANTEETYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE         'UNKNOWN'
       END AS GRANTEETYPE
     , NAME
     , CASE AUTHHOWGOT
       WHEN 'C' THEN 'DBCTRL   '
       WHEN 'D' THEN 'DBADM     '
       WHEN 'E' THEN 'SECADM   '
       WHEN 'G' THEN 'ACCESSCTRL'
       WHEN 'L' THEN 'SYSCTRL   '
       WHEN 'M' THEN 'DBMAINT   '
       WHEN 'S' THEN 'SYSADM   '
       WHEN ' ' THEN 'N/A       '
       ELSE         'UNKNOWN   '
       END AS AUTHHOWGOT
     , BINDAUTH
     , EXECUTEAUTH
 FROM SYSIBM.SYSPLANAUTH
 WHERE NOT GRANTOR = GRANTEE
  AND ( BINDAUTH   = 'G'
    OR EXECUTEAUTH = 'G' )
 ORDER BY NAME, GRANTOR, GRANTEE
 FETCH FIRST 50 ROWS ONLY
 WITH UR
 ;
SELECT GRANTOR
     , CASE GRANTORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE         'UNKNOWN'
       END AS GRANTORTYPE
     , GRANTEE
     , CASE GRANTEETYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE         'UNKNOWN'
       END AS GRANTEETYPE
     , QUALIFIER
     , NAME
     , CASE AUTHHOWGOT
       WHEN 'A' THEN 'PACKADM (COLLECTION *)   '
       WHEN 'C' THEN 'DBCTRL                   '
       WHEN 'D' THEN 'DBADM                     '
       WHEN 'E' THEN 'SECADM                   '
       WHEN 'G' THEN 'ACCESSCTRL               '
       WHEN 'L' THEN 'SYSCTRL                   '
       WHEN 'M' THEN 'DBMAINT                   '
       WHEN 'P' THEN 'PACKADM (NOT COLLECTION *)'
       WHEN 'S' THEN 'SYSADM                   '
       WHEN 'T' THEN 'DATAACCESS               '
       WHEN ' ' THEN 'N/A                       '
       ELSE         'UNKNOWN                   '
       END AS AUTHHOWGOT
     , CASE OBTYPE
       WHEN 'B' THEN 'BUFFER POOL '
       WHEN 'C' THEN 'COLLECTION   '
       WHEN 'D' THEN 'DISTINCT TYPE'
       WHEN 'R' THEN 'TABLE SPACE '
       WHEN 'S' THEN 'STORAGE GROUP'
       WHEN 'J' THEN 'JAR FILE     '
       ELSE         'UNKNOWN     '
       END       AS OBJECT_TYPE
     , USEAUTH
 FROM SYSIBM.SYSRESAUTH
 WHERE NOT GRANTOR = GRANTEE
 AND USEAUTH     = 'G'
 ORDER BY QUALIFIER, NAME, GRANTOR, GRANTEE
 FETCH FIRST 50 ROWS ONLY
 WITH UR
 ;
SELECT GRANTOR
    , CASE GRANTORTYPE
      WHEN 'L' THEN 'ROLE   '
      WHEN ' ' THEN 'AUTH ID'
      ELSE         'UNKNOWN'
      END AS GRANTORTYPE
    , GRANTEE
    , CASE GRANTEETYPE
      WHEN 'L' THEN 'ROLE             '
      WHEN 'P' THEN 'PLAN/PACKAGE     '
      WHEN 'R' THEN 'INTERNAL USE ONLY'
      WHEN ' ' THEN 'AUTH ID         '
      ELSE         'UNKNOWN         '
      END AS GRANTEETYPE
    , SCHEMA      AS CREATOR
    , SPECIFICNAME AS NAME
    , CASE ROUTINETYPE
      WHEN 'F' THEN 'UDF OR CAST FUNCTION'
      WHEN 'P' THEN 'STORED PROCEDURE   '
      ELSE         'UNKNOWN             '
      END       AS ROUTINETYPE
    , CASE AUTHHOWGOT
      WHEN '1' THEN 'GRANTOR SCHEMA.* AT TIME'
      WHEN 'E' THEN 'SECADM                 '
      WHEN 'G' THEN 'ACCESSCTRL             '
      WHEN 'L' THEN 'SYSCTRL                 '
      WHEN 'S' THEN 'SYSADM                 '
      WHEN 'T' THEN 'DATAACCESS             '
      WHEN ' ' THEN 'N/A                     '
      ELSE         'UNKNOWN                 '
      END AS AUTHHOWGOT
    , EXECUTEAUTH
    , COLLID
    , HEX(CONTOKEN) AS CONTOKEN
 FROM SYSIBM.SYSROUTINEAUTH
 WHERE NOT GRANTOR = GRANTEE
 AND EXECUTEAUTH = 'G'
 ORDER BY CREATOR , NAME, GRANTOR, GRANTEE
 FETCH FIRST 50 ROWS ONLY
 WITH UR
 ;
SELECT GRANTOR
   , CASE GRANTORTYPE
     WHEN 'L' THEN 'ROLE   '
     WHEN ' ' THEN 'AUTH ID'
     ELSE         'UNKNOWN'
     END AS GRANTORTYPE
   , GRANTEE
   , CASE GRANTEETYPE
     WHEN 'L' THEN 'ROLE   '
     WHEN ' ' THEN 'AUTH ID'
     ELSE         'UNKNOWN'
     END AS GRANTEETYPE
   , SCHEMANAME
   , CASE AUTHHOWGOT
     WHEN '1' THEN 'GRANTOR SCHEMA.* AT TIME'
     WHEN 'E' THEN 'SECADM                 '
     WHEN 'G' THEN 'ACCESSCTRL             '
     WHEN 'L' THEN 'SYSCTRL                 '
     WHEN 'S' THEN 'SYSADM                 '
     ELSE         'UNKNOWN                 '
     END AS AUTHHOWGOT
   , CREATEINAUTH
   , ALTERINAUTH
   , DROPINAUTH
 FROM SYSIBM.SYSSCHEMAAUTH
 WHERE NOT GRANTOR = GRANTEE
  AND ( CREATEINAUTH = 'G'
   OR   ALTERINAUTH = 'G'
   OR   DROPINAUTH   = 'G' )
 ORDER BY SCHEMANAME, GRANTOR, GRANTEE
 FETCH FIRST 50 ROWS ONLY
 WITH UR
 ;
SELECT GRANTOR
    , CASE GRANTORTYPE
      WHEN 'L' THEN 'ROLE   '
      WHEN ' ' THEN 'AUTH ID'
      ELSE         'UNKNOWN'
      END AS GRANTORTYPE
    , GRANTEE
    , CASE GRANTEETYPE
      WHEN 'L' THEN 'ROLE            '
      WHEN 'P' THEN 'PLAN/PACKAGE     '
      WHEN 'R' THEN 'INTERNAL USE ONLY'
      WHEN ' ' THEN 'AUTH ID         '
      ELSE         'UNKNOWN         '
 END AS GRANTEETYPE
    , SCHEMA AS CREATOR
    , NAME
    , CASE AUTHHOWGOT
      WHEN ' ' THEN 'N/A       '
      WHEN 'E' THEN 'SECADM   '
      WHEN 'G' THEN 'ACCESSCTRL'
      WHEN 'L' THEN 'SYSCTRL   '
      WHEN 'S' THEN 'SYSADM   '
      WHEN 'T' THEN 'DATAACCESS'
      ELSE         'UNKNOWN   '
      END AS AUTHHOWGOT
    , ALTERAUTH
    , USEAUTH
    , COLLID
    , HEX(CONTOKEN) AS CONTOKEN
 FROM SYSIBM.SYSSEQUENCEAUTH
 WHERE NOT GRANTOR = GRANTEE
  AND ( ALTERAUTH = 'G'
   OR   USEAUTH   = 'G' )
 ORDER BY CREATOR, NAME, GRANTOR, GRANTEE
 FETCH FIRST 50 ROWS ONLY
 WITH UR
 ;
SELECT GRANTOR
    , CASE GRANTORTYPE
      WHEN 'L' THEN 'ROLE   '
      WHEN ' ' THEN 'AUTH ID'
      ELSE         'UNKNOWN'
      END AS GRANTORTYPE
    , GRANTEE
    , CASE GRANTEETYPE
      WHEN 'L' THEN 'ROLE       '
      WHEN 'P' THEN 'PLAN/PACKAGE'
      WHEN ' ' THEN 'AUTH ID     '
      ELSE         'UNKNOWN     '
      END AS GRANTEETYPE
    , DBNAME
    , TCREATOR AS CREATOR
    , TTNAME   AS NAME
    , CASE AUTHHOWGOT
      WHEN ' ' THEN 'N/A         '
      WHEN 'B' THEN 'SYSTEM DBADM'
      WHEN 'C' THEN 'DBCTRL     '
      WHEN 'E' THEN 'SECADM     '
      WHEN 'G' THEN 'ACCESSCTRL '
      WHEN 'K' THEN 'SQLADM     '
      WHEN 'L' THEN 'SYSCTRL     '
      WHEN 'M' THEN 'DBMAINT     '
      WHEN 'S' THEN 'SYSADM     '
      WHEN 'T' THEN 'DATAACCESS '
      ELSE         'UNKNOWN     '
      END AS AUTHHOWGOT
    , ALTERAUTH
    , DELETEAUTH
    , INDEXAUTH
    , INSERTAUTH
    , SELECTAUTH
    , UPDATEAUTH
    , REFERENCESAUTH
    , TRIGGERAUTH
    , UPDATECOLS
    , REFCOLS
    , COLLID
    , HEX(CONTOKEN) AS CONTOKEN
 FROM SYSIBM.SYSTABAUTH
 WHERE NOT GRANTOR = GRANTEE
  AND ( ALTERAUTH     = 'G'
   OR   DELETEAUTH     = 'G'
   OR   INDEXAUTH     = 'G'
   OR   INSERTAUTH     = 'G'
   OR   SELECTAUTH     = 'G'
   OR   UPDATEAUTH     = 'G'
   OR   REFERENCESAUTH = 'G'
   OR   TRIGGERAUTH   = 'G' )
 ORDER BY CREATOR, NAME, GRANTOR, GRANTEE
 FETCH FIRST 50 ROWS ONLY
 WITH UR
 ;
SELECT GRANTOR
    , CASE GRANTORTYPE
      WHEN 'L' THEN 'ROLE   '
      WHEN ' ' THEN 'AUTH ID'
      ELSE         'UNKNOWN'
 END AS GRANTORTYPE
   , GRANTEE
   , CASE GRANTEETYPE
     WHEN 'L' THEN 'ROLE       '
     WHEN 'P' THEN 'PLAN/PACKAGE'
     WHEN ' ' THEN 'AUTH ID     '
     ELSE        'UNKNOWN     '
     END AS GRANTEETYPE
   , CASE AUTHHOWGOT
     WHEN ' ' THEN 'N/A       '
     WHEN 'C' THEN 'DBCTRL   '
     WHEN 'E' THEN 'SECADM   '
     WHEN 'G' THEN 'ACCESSCTRL'
     WHEN 'K' THEN 'SQLADM   '
     WHEN 'L' THEN 'SYSCTRL   '
     WHEN 'M' THEN 'DBMAINT   '
     WHEN 'O' THEN 'SYSOPR   '
     WHEN 'S' THEN 'SYSADM   '
     ELSE         'UNKNOWN   '
     END AS AUTHHOWGOT
   , BINDADDAUTH
   , BSDSAUTH
   , CREATEDBAAUTH
   , CREATEDBCAUTH
   , CREATESGAUTH
   , DISPLAYAUTH
   , RECOVERAUTH
   , STOPALLAUTH
   , STOSPACEAUTH
   , SYSADMAUTH
   , SYSOPRAUTH
   , TRACEAUTH
   , MON1AUTH
   , MON2AUTH
   , CREATEALIASAUTH
   , SYSCTRLAUTH
   , BINDAGENTAUTH
   , ARCHIVEAUTH
   , CREATETMTABAUTH
   , DEBUGSESSIONAUTH
   , EXPLAINAUTH
   , SQLADMAUTH
   , SDBADMAUTH
   , DATAACCESSAUTH
   , ACCESSCTRLAUTH
   , CREATESECUREAUTH
 FROM SYSIBM.SYSUSERAUTH
 WHERE NOT GRANTOR = GRANTEE
  AND ( BINDADDAUTH     = 'G'
   OR   BSDSAUTH         = 'G'
   OR   CREATEDBAAUTH   = 'G'
   OR   CREATEDBCAUTH   = 'G'
   OR   CREATESGAUTH     = 'G'
   OR   DISPLAYAUTH     = 'G'
   OR   RECOVERAUTH     = 'G'
   OR   STOPALLAUTH     = 'G'
   OR   STOSPACEAUTH     = 'G'
   OR   SYSADMAUTH       = 'G'
   OR   SYSOPRAUTH       = 'G'
   OR   TRACEAUTH       = 'G'
   OR   MON1AUTH         = 'G'
   OR   MON2AUTH         = 'G'
   OR   CREATEALIASAUTH = 'G'
   OR   SYSCTRLAUTH     = 'G'
   OR   BINDAGENTAUTH   = 'G'
   OR   ARCHIVEAUTH     = 'G'
   OR   CREATETMTABAUTH = 'G'
   OR   DEBUGSESSIONAUTH = 'G'
   OR   EXPLAINAUTH     = 'G'
   OR   SQLADMAUTH       = 'G'
   OR   SDBADMAUTH       = 'G'
   OR   DATAACCESSAUTH   = 'G'
   OR   ACCESSCTRLAUTH   = 'G'
   OR   CREATESECUREAUTH = 'G' )
 ORDER BY GRANTOR, GRANTEE
 FETCH FIRST 50 ROWS ONLY
 WITH UR
 ;

Now you must review all of the output, and try to decide which, (if any!) of these should be allowed. I think they should all be not allowed, as you very quickly lose the ability to see who GRANTed what to whom!

Second Law: Know your SYSADM userids

If you do not know who is SYSADM that is a very bad place to be!

Here’s an SQL to help you find out:

SELECT GRANTOR
     , CASE GRANTORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTORTYPE
     , GRANTEE
     , CASE GRANTEETYPE
       WHEN 'L' THEN 'ROLE        '
       WHEN 'P' THEN 'PLAN/PACKAGE'
       WHEN ' ' THEN 'AUTH ID     '
       ELSE          'UNKNOWN     '
       END AS GRANTEETYPE
     , CASE AUTHHOWGOT
       WHEN ' ' THEN 'N/A       '
       WHEN 'C' THEN 'DBCTRL    '
       WHEN 'E' THEN 'SECADM    '
       WHEN 'G' THEN 'ACCESSCTRL'
       WHEN 'K' THEN 'SQLADM    '
       WHEN 'L' THEN 'SYSCTRL   '
       WHEN 'M' THEN 'DBMAINT   '
       WHEN 'O' THEN 'SYSOPR    '
       WHEN 'S' THEN 'SYSADM    '
       ELSE          'UNKNOWN   '
       END AS AUTHHOWGOT
     , SYSADMAUTH
FROM SYSIBM.SYSUSERAUTH
WHERE NOT GRANTOR    = GRANTEE
  AND NOT SYSADMAUTH = ' '
ORDER BY GRANTOR, GRANTEE
FETCH FIRST 50 ROWS ONLY
WITH UR
;

Again, review the output *very* carefully and make very sure that all of the User Ids are well protected! One point to mention here is that lots of people use a surrogate User Id for Job scheduling (TWS, UC4, ESP, Control-M etc.) and normally these User Ids are very powerful, but they do *not* need to be SYSADM, and, if they are SYSADM, at least make them unavailable to TSO and remote Logon!

Third Law: Is anything PUBLIC?

There was a time, when nearly everything was PUBLIC, or even PUBLIC AT ALL LOCATIONS. These days this should never really be used, apart from exceptional circumstances. For example, the four SYSIBM.SYSDUMMYx tables can all safely get a

GRANT SELECT ON TABLE SYSIBM.SYSDUMMY1
                    , SYSIBM.SYSDUMMYE
                    , SYSIBM.SYSDUMMYA
                    , SYSIBM.SYSDUMMYU
TO PUBLIC ;

but you must weigh up the pros and cons of any other table being opened up like this.

SELECT GRANTOR
     , CASE GRANTORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTORTYPE
     , GRANTEE
     , CASE GRANTEETYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN 'P' THEN 'PLAN   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTEETYPE
     , CREATOR
     , TNAME    AS NAME
     , COLNAME  AS COLUMN
     , CASE PRIVILEGE
       WHEN 'R' THEN 'REFERENCES'
       WHEN ' ' THEN 'UPDATE    '
       ELSE          'UNKNOWN   '
       END AS AUTHHOWGOT
     , COLLID
     , HEX(CONTOKEN) AS CONTOKEN
FROM SYSIBM.SYSCOLAUTH
WHERE NOT GRANTOR = GRANTEE
 AND ( GRANTOR = 'PUBLIC'
    OR GRANTEE = 'PUBLIC' )
ORDER BY NAME, GRANTOR, GRANTEE
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT GRANTOR
, CASE GRANTORTYPE
WHEN 'L' THEN 'ROLE   '
WHEN ' ' THEN 'AUTH ID'
ELSE          'UNKNOWN'
END AS GRANTORTYPE
, GRANTEE
, CASE GRANTEETYPE
WHEN 'L' THEN 'ROLE   '
WHEN 'P' THEN 'PLAN   '
WHEN ' ' THEN 'AUTH ID'
ELSE          'UNKNOWN'
END AS GRANTEETYPE
, NAME
, CASE AUTHHOWGOT
WHEN 'C' THEN 'DBCTRL    '
WHEN 'D' THEN 'DBADM     '
WHEN 'E' THEN 'SECADM    '
WHEN 'G' THEN 'ACCESSCTRL'
WHEN 'L' THEN 'SYSCTRL   '
WHEN 'M' THEN 'DBMAINT   '
WHEN 'S' THEN 'SYSADM    '
WHEN ' ' THEN 'N/A       '
ELSE          'UNKNOWN   '
END AS AUTHHOWGOT
, CREATETABAUTH
, CREATETSAUTH
, DBADMAUTH
, DBCTRLAUTH
, DBMAINTAUTH
, DISPLAYDBAUTH
, DROPAUTH
, IMAGCOPYAUTH
, LOADAUTH
, REORGAUTH
, RECOVERDBAUTH
, REPAIRAUTH
, STARTDBAUTH
, STATSAUTH
, STOPAUTH
FROM SYSIBM.SYSDBAUTH
WHERE NOT GRANTOR = GRANTEE
AND ( GRANTOR = 'PUBLIC'
OR GRANTEE = 'PUBLIC' )
ORDER BY NAME, GRANTOR, GRANTEE
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT GRANTOR
     , CASE GRANTORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTORTYPE
     , GRANTEE
     , CASE GRANTEETYPE
       WHEN 'L' THEN 'ROLE   '
      WHEN 'P' THEN 'PLAN   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTEETYPE
     , COLLID
     , NAME
     , CASE AUTHHOWGOT
       WHEN 'A' THEN 'PACKADM (COLLECTION *)    '
       WHEN 'C' THEN 'DBCTRL                    '
       WHEN 'D' THEN 'DBADM                     '
       WHEN 'E' THEN 'SECADM                    '
       WHEN 'G' THEN 'ACCESSCTRL                '
       WHEN 'L' THEN 'SYSCTRL                   '
       WHEN 'M' THEN 'DBMAINT                   '
       WHEN 'P' THEN 'PACKADM (NOT COLLECTION *)'
       WHEN 'S' THEN 'SYSADM                    '
       WHEN 'T' THEN 'DATAACCESS                '
       WHEN ' ' THEN 'N/A                       '
       ELSE          'UNKNOWN                   '
       END AS AUTHHOWGOT
     , BINDAUTH
     , COPYAUTH
     , EXECUTEAUTH
FROM SYSIBM.SYSPACKAUTH
WHERE NOT GRANTOR = GRANTEE
 AND ( GRANTOR = 'PUBLIC'
    OR GRANTOR = 'PUBLIC*'
    OR GRANTEE = 'PUBLIC'
    OR GRANTEE = 'PUBLIC*' )
ORDER BY NAME, GRANTOR, GRANTEE
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT GRANTOR
     , CASE GRANTORTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
      END AS GRANTORTYPE
    , GRANTEE
    , CASE GRANTEETYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END AS GRANTEETYPE
     , NAME
     , CASE AUTHHOWGOT
       WHEN 'C' THEN 'DBCTRL    '
       WHEN 'D' THEN 'DBADM     '
       WHEN 'E' THEN 'SECADM    '
       WHEN 'G' THEN 'ACCESSCTRL'
       WHEN 'L' THEN 'SYSCTRL   '
       WHEN 'M' THEN 'DBMAINT   '
       WHEN 'S' THEN 'SYSADM    '
       WHEN ' ' THEN 'N/A       '
       ELSE          'UNKNOWN   '
       END AS AUTHHOWGOT
     , BINDAUTH
     , EXECUTEAUTH
FROM SYSIBM.SYSPLANAUTH
WHERE NOT GRANTOR = GRANTEE
 AND  GRANTEE = 'PUBLIC'
ORDER BY NAME, GRANTOR, GRANTEE
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT GRANTOR
    , CASE GRANTORTYPE
      WHEN 'L' THEN 'ROLE   '
      WHEN ' ' THEN 'AUTH ID'
      ELSE          'UNKNOWN'
 END AS GRANTORTYPE
   , GRANTEE
   , CASE GRANTEETYPE
     WHEN 'L' THEN 'ROLE   '
     WHEN ' ' THEN 'AUTH ID'
     ELSE          'UNKNOWN'
     END AS GRANTEETYPE
   , QUALIFIER
   , NAME
   , CASE AUTHHOWGOT
     WHEN 'A' THEN 'PACKADM (COLLECTION *)    '
     WHEN 'C' THEN 'DBCTRL                    '
     WHEN 'D' THEN 'DBADM                     '
     WHEN 'E' THEN 'SECADM                    '
     WHEN 'G' THEN 'ACCESSCTRL                '
     WHEN 'L' THEN 'SYSCTRL                   '
     WHEN 'M' THEN 'DBMAINT                   '
     WHEN 'P' THEN 'PACKADM (NOT COLLECTION *)'
     WHEN 'S' THEN 'SYSADM                    '
     WHEN 'T' THEN 'DATAACCESS                '
     WHEN ' ' THEN 'N/A                       '
     ELSE          'UNKNOWN                   '
     END AS AUTHHOWGOT
   , CASE OBTYPE
     WHEN 'B' THEN 'BUFFER POOL  '
     WHEN 'C' THEN 'COLLECTION   '
     WHEN 'D' THEN 'DISTINCT TYPE'
     WHEN 'R' THEN 'TABLE SPACE  '
     WHEN 'S' THEN 'STORAGE GROUP'
     WHEN 'J' THEN 'JAR FILE     '
     ELSE          'UNKNOWN      '
     END        AS OBJECT_TYPE
   , USEAUTH
 FROM SYSIBM.SYSRESAUTH
 WHERE NOT GRANTOR = GRANTEE
   AND  GRANTEE = 'PUBLIC'
 ORDER BY QUALIFIER, NAME, GRANTOR, GRANTEE
 FETCH FIRST 50 ROWS ONLY
 WITH UR
;
SELECT GRANTOR
, CASE GRANTORTYPE
WHEN 'L' THEN 'ROLE   '
WHEN ' ' THEN 'AUTH ID'
ELSE          'UNKNOWN'
END AS GRANTORTYPE
, GRANTEE
, CASE GRANTEETYPE
WHEN 'L' THEN 'ROLE             '
WHEN 'P' THEN 'PLAN/PACKAGE     '
WHEN 'R' THEN 'INTERNAL USE ONLY'
WHEN ' ' THEN 'AUTH ID          '
ELSE          'UNKNOWN          '
END AS GRANTEETYPE
, SCHEMA       AS CREATOR
, SPECIFICNAME AS NAME
, CASE ROUTINETYPE
WHEN 'F' THEN 'UDF OR CAST FUNCTION'
WHEN 'P' THEN 'STORED PROCEDURE    '
ELSE          'UNKNOWN             '
END        AS ROUTINETYPE
, CASE AUTHHOWGOT
WHEN '1' THEN 'GRANTOR SCHEMA.* AT TIME'
WHEN 'E' THEN 'SECADM                  '
WHEN 'G' THEN 'ACCESSCTRL              '
WHEN 'L' THEN 'SYSCTRL                 '
WHEN 'S' THEN 'SYSADM                  '
WHEN 'T' THEN 'DATAACCESS              '
WHEN ' ' THEN 'N/A                     '
ELSE          'UNKNOWN                 '
END AS AUTHHOWGOT
, EXECUTEAUTH
, COLLID
, HEX(CONTOKEN) AS CONTOKEN
FROM SYSIBM.SYSROUTINEAUTH
WHERE NOT GRANTOR = GRANTEE
AND  GRANTEE = 'PUBLIC'
ORDER BY CREATOR , NAME, GRANTOR, GRANTEE
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT GRANTOR
   , CASE GRANTORTYPE
     WHEN 'L' THEN 'ROLE   '
     WHEN ' ' THEN 'AUTH ID'
     ELSE          'UNKNOWN'
     END AS GRANTORTYPE
   , GRANTEE
   , CASE GRANTEETYPE
     WHEN 'L' THEN 'ROLE   '
     WHEN ' ' THEN 'AUTH ID'
     ELSE          'UNKNOWN'
     END AS GRANTEETYPE
   , SCHEMANAME
   , CASE AUTHHOWGOT
     WHEN '1' THEN 'GRANTOR SCHEMA.* AT TIME'
     WHEN 'E' THEN 'SECADM                  '
     WHEN 'G' THEN 'ACCESSCTRL              '
     WHEN 'L' THEN 'SYSCTRL                 '
     WHEN 'S' THEN 'SYSADM                  '
     ELSE          'UNKNOWN                 '
     END AS AUTHHOWGOT
   , CREATEINAUTH
   , ALTERINAUTH
   , DROPINAUTH
FROM SYSIBM.SYSSCHEMAAUTH
WHERE NOT GRANTOR = GRANTEE
 AND  GRANTEE = 'PUBLIC'
ORDER BY SCHEMANAME, GRANTOR, GRANTEE
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT GRANTOR
   , CASE GRANTORTYPE
     WHEN 'L' THEN 'ROLE   '
     WHEN ' ' THEN 'AUTH ID'
     ELSE          'UNKNOWN'
     END AS GRANTORTYPE
   , GRANTEE
   , CASE GRANTEETYPE
     WHEN 'L' THEN 'ROLE             '
     WHEN 'P' THEN 'PLAN/PACKAGE     '
     WHEN 'R' THEN 'INTERNAL USE ONLY'
     WHEN ' ' THEN 'AUTH ID          '
     ELSE          'UNKNOWN          '
     END AS GRANTEETYPE
   , SCHEMA AS CREATOR
   , NAME
   , CASE AUTHHOWGOT
     WHEN ' ' THEN 'N/A       '
     WHEN 'E' THEN 'SECADM    '
     WHEN 'G' THEN 'ACCESSCTRL'
     WHEN 'L' THEN 'SYSCTRL   '
     WHEN 'S' THEN 'SYSADM    '
     WHEN 'T' THEN 'DATAACCESS'
     ELSE          'UNKNOWN   '
     END AS AUTHHOWGOT
   , ALTERAUTH
   , USEAUTH
   , COLLID
   , HEX(CONTOKEN) AS CONTOKEN
FROM SYSIBM.SYSSEQUENCEAUTH
WHERE NOT GRANTOR = GRANTEE
AND  GRANTEE = 'PUBLIC'
ORDER BY CREATOR, NAME, GRANTOR, GRANTEE
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT GRANTOR
   , CASE GRANTORTYPE
     WHEN 'L' THEN 'ROLE   '
     WHEN ' ' THEN 'AUTH ID'
     ELSE          'UNKNOWN'
     END AS GRANTORTYPE
   , GRANTEE
   , CASE GRANTEETYPE
     WHEN 'L' THEN 'ROLE        '
     WHEN 'P' THEN 'PLAN/PACKAGE'
     WHEN ' ' THEN 'AUTH ID     '
     ELSE          'UNKNOWN     '
END AS GRANTEETYPE
   , DBNAME
   , TCREATOR AS CREATOR
   , TTNAME   AS NAME
   , CASE AUTHHOWGOT
     WHEN ' ' THEN 'N/A         '
     WHEN 'B' THEN 'SYSTEM DBADM'
     WHEN 'C' THEN 'DBCTRL      '
     WHEN 'E' THEN 'SECADM      '
     WHEN 'G' THEN 'ACCESSCTRL  '
     WHEN 'K' THEN 'SQLADM      '
     WHEN 'L' THEN 'SYSCTRL     '
     WHEN 'M' THEN 'DBMAINT     '
     WHEN 'S' THEN 'SYSADM      '
     WHEN 'T' THEN 'DATAACCESS  '
     ELSE          'UNKNOWN     '
     END AS AUTHHOWGOT
   , ALTERAUTH
   , DELETEAUTH
   , INDEXAUTH
   , INSERTAUTH
   , SELECTAUTH
   , UPDATEAUTH
   , REFERENCESAUTH
   , TRIGGERAUTH
   , UPDATECOLS
   , REFCOLS
   , COLLID
   , HEX(CONTOKEN) AS CONTOKEN
FROM SYSIBM.SYSTABAUTH
WHERE NOT GRANTOR = GRANTEE
 AND ( GRANTOR = 'PUBLIC'
  OR GRANTOR = 'PUBLIC*'
  OR GRANTEE = 'PUBLIC'
  OR GRANTEE = 'PUBLIC*' )
ORDER BY CREATOR, NAME, GRANTOR, GRANTEE
FETCH FIRST 50 ROWS ONLY
WITH UR
;
SELECT GRANTOR
   , CASE GRANTORTYPE
     WHEN 'L' THEN 'ROLE   '
     WHEN ' ' THEN 'AUTH ID'
     ELSE          'UNKNOWN'
     END AS GRANTORTYPE
   , GRANTEE
   , CASE GRANTEETYPE
     WHEN 'L' THEN 'ROLE        '
     WHEN 'P' THEN 'PLAN/PACKAGE'
     WHEN ' ' THEN 'AUTH ID     '
     ELSE          'UNKNOWN     '
     END AS GRANTEETYPE
   , CASE AUTHHOWGOT
     WHEN ' ' THEN 'N/A       '
     WHEN 'C' THEN 'DBCTRL    '
     WHEN 'E' THEN 'SECADM    '
     WHEN 'G' THEN 'ACCESSCTRL'
     WHEN 'K' THEN 'SQLADM    '
     WHEN 'L' THEN 'SYSCTRL   '
     WHEN 'M' THEN 'DBMAINT   '
     WHEN 'O' THEN 'SYSOPR    '
     WHEN 'S' THEN 'SYSADM    '
     ELSE          'UNKNOWN   '
END AS AUTHHOWGOT
   , BINDADDAUTH
   , BSDSAUTH
   , CREATEDBAAUTH
   , CREATEDBCAUTH
   , CREATESGAUTH
   , DISPLAYAUTH
   , RECOVERAUTH
   , STOPALLAUTH
   , STOSPACEAUTH
   , SYSADMAUTH
   , SYSOPRAUTH
   , TRACEAUTH
   , MON1AUTH
   , MON2AUTH
   , CREATEALIASAUTH
   , SYSCTRLAUTH
   , BINDAGENTAUTH
   , ARCHIVEAUTH
   , CREATETMTABAUTH
   , DEBUGSESSIONAUTH
   , EXPLAINAUTH
   , SQLADMAUTH
   , SDBADMAUTH
   , DATAACCESSAUTH
   , ACCESSCTRLAUTH
   , CREATESECUREAUTH
FROM SYSIBM.SYSUSERAUTH
WHERE NOT GRANTOR = GRANTEE
AND  GRANTEE = 'PUBLIC'
ORDER BY GRANTOR, GRANTEE
FETCH FIRST 50 ROWS ONLY
WITH UR
;

Once again, go through the output and make informed decisions! The Hacker loves PUBLIC.

Fourth Law: “Trusted” Trusted Contexts?

Trusted Contexts are great, but have you got some that are a bit too open? Have you – by accident – left the back door open? Run this to find out:

SELECT ENABLED
     , NAME
     , CONTEXTID
     , DEFINER
     , CASE DEFINERTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS DEFINERTYPE
     , DEFAULTROLE
     , CASE OBJECTOWNERTYPE
       WHEN 'L' THEN 'ROLE   '
       WHEN ' ' THEN 'AUTH ID'
       ELSE          'UNKNOWN'
       END        AS OBJECTOWNERTYPE
     , ALLOWPUBLIC
     , AUTHENTICATEPUBLIC
     , DEFAULTSECURITYLABEL
FROM SYSIBM.SYSCONTEXT
WHERE ALLOWPUBLIC        = 'Y'
  AND AUTHENTICATEPUBLIC = 'N'
ORDER BY 3
FETCH FIRST 50 ROWS ONLY
WITH UR
;

 

Allowing public access, but without authentication, is not a good idea.

Now all we have done is validate the DB2 Catalog. What about seeing what is happening on your machine? Have you anything in place that can give you 100% coverage of audit issues? With SOFTWARE ENGINEERING’s  SQL WorkloadExpert for DB2 z/OS you can audit everything that is running in your enterprise. For example here is a view of the Audit pop-up window:

 

DB2 z/OS newsletter 2015-10: DB2 Quick Security Audit -Part 1

 

One of the options here, is to see exactly how many Authorization Ids are running at your shop, or even what the SYSADMs of the world have been doing. All handy stuff and available real-time!

I hope you enjoyed this first part and thanks for getting this far. Next up is knowing your Roles and Authorization Ids.

As always, any questions or comments would be most welcome!

TTFN,

Roy Boxwell

GIVE and TAKE Program

1,2,3


Give and Take 2020

Information on the Give and Take Programs 4,5,6,7


Previous Give & Take

We have “GIVEn” various free-of-charge Use Cases from our SQL WorkloadExpert for Db2 z/OS like:

1 Index Maintenance Costs

2 EXPLAIN Suppression

3 BIF Usage

Limited free-of-Charge Db2 Application

This Program started in Europe, during our 30th anniversary was such a success, that it is now being Extended for the benefit of North American Db2 z/OS sites.

<a href="http://www.seg.de/produkte/db2-zos-produkte/sql-workloadexpert-for-db2-zos/" target="


Index Maintenance Costs, EXPLAIN Suppression, BIF

Limited free-of-Charge Db2 Application

This Program started in Europe, during our 30th anniversary was such a success, that it is now being Extended for the benefit of North American Db2 z/OS sites.

SQL WorkloadExpert for Db2 z/OS (WLX) contains several “Use Cases”. We provided three of them, free of charge, for one month to different sites. In return, we received their results. We’d like to share this with you now.

We have “GIVEn” various free-of-charge Use Cases from SQL Workload Expert for Db2 z/OS like
1  Index Maintenance Costs
2  EXPLAIN Suppression
3  BIF Usage 
BIX HealthCheck – This last one is still available
We TAKE the anonymized results for research
and will communicate with the local User Groups for discussions

Inspiring experiences

Customer Statements

3BIF USAGE
News
Read the Customer Comments across the Industry 

 

  • Health Care
  • Insurance
  • Banking
  • Car Manufacturing

First results from Db2 z/OS sites

1Index Mantenance CostsNearly all the data we got back showed a positive result for created Indexes…
2EXPLAIN SuppressionAbout 10% of SQLs are actually “left over”…
3 BIF Usage When migrating to a new Db2 version, the BIFs are not always compatible and an extreme amount of data is produced.

 

The difficulty of near-time analysis to track down BIFs within dynamic SQL have been solved with the BIF Usage Use Case…

 [Results from Db2 z/OS sites]

Program 3 – BIF Usage –  has now started

BIF-Usage

 

Presentation

BIF CompatibilityDb2 10 compatibility mode
Changes to the STRING formating of decimal data within the CHAR and VARCHAR built-in function and to the CAST specification with CHAR and VARCHAR result types as well as  UNSUPPORTED TIMESTAMP STRINGs.
White PaperFinding BIFsAnd How to Lead a Problem-Free Life With Them in the Future
Navigating the Challenges of moving to a new Db2 Release
Newsletter2015-01 – BIFCIDS – Where’s the BIF?How will you deal with loop-hole usage in production code?
VideoBIF Usage(11min.) Trap  and correct the BIFs that will cause belly-ache one day soon

BIF Usage video


2015-09 A real CLUSTER Buster

Are you using the “default” clustering INDEX or are you defining the correct INDEX with the CLUSTER Attribute?

This newsletter is dedicated to all DDL designers who do their best but then omit that last tiny bit. No-one really notices, or even cares, for years and years until…

Imagine a huge table up in the billions of rows. Imagine now that you have SQL that accesses this table and it must, as always, run fast. So what do you do? You create an index, RUNSTATS it and Hey Presto! Everything is sweet and dandy! Now imagine this happening again and again over time… What you finally end up with is a huge table with billions of rows now with ten indexes! Not too brilliant for insert and update but that is not the point of this newsletter.

 

An SQL, that had worked perfectly well, suddenly went pear shaped…

So now stop imagining, as this had already really happened at a customer site. We come to the crux: An SQL, that had worked perfectly well, suddenly went pear shaped (belly-up for the non-British English readers!) and started using a two column index with one matching column instead of a six column index with six matching columns! This change in access path caused death by random-IO to occur and it all went horribly wrong.

 

Now the question is why? What on earth happened for the DB2 Optimizer to make such a terrible decision?

1- RUNSTATS review

First idea was, of course, my favourite – Incomplete or not Full RUNSTATS data. In fact there were “bogus stats” from 2003 in the SYSCOLDIST, but even after all the bogus stats were deleted and a complete RUNSTATS with HISTOGRAM and FREQVAL performed, the access path remained stuck on the “bad” index.

 

2- DDL review

I then reviewed the DDL that created all of the objects and noticed that none of the indexes was defined with the CLUSTER attribute. The table itself was “as old as the hills,” but all of the indexes had been created and/or altered many times over the last ten years or so.

 

3- Redefine the “bad” Index as CLUSTER

 The dummy CLUSTER

Now, as we all know, if no index is defined as CLUSTER DB2 picks one to be a dummy CLUSTER when it does a REORG. So you can end up with 100% clustering non-clustered indexes. In this case that was exactly what was happening. The “bad” index was, purely by fluke after many years of index maintenance, the “default” clustering index, however it was a *terrible* choice for a clustering index. Worse still: because of the fact it was non-unique with two columns and therefore small (well small in this case was still 40,000 pages!) it looked positively “good” to the DB2 Optimizer—hence the decision to abandon a six column matching index in favour of a single column one…

“Cleansing” with ALTER, REORG and the DB2 10 INCLUDE syntax

A quick ALTER of the original “first” index to get the CLUSTER attribute, a REORG scheduled for the weekend to get the data into *proper* CLUSTERing sequence and – Bob’s your uncle! Access path swapped back to the “good” index.

Now there’s still work to be done here as ten indexes is about seven too many, if you ask me.With DB2 10 it is possible to use the INCLUDE syntax to weed out some of the extra indexes and thus speed up all usage of this mega-table. But, for the right here and now, the job is done!

So now I am at the end of this sad story of how a little design “error” of just forgetting one little attribute on an index create statement caused major mayhem many years down the line… remember to check *all* of your tables and see if you have any beauties like this in your shop (surely not!)

 

Here’s a little SQL that will do the job for you:

--                                                                     
-- QUERY TO LIST OUT ALL TABLES WITH TWO OR MORE INDEXES WHERE NO INDEX
-- IS DEFINED AS CLUSTER                                               
--                                                                     
SELECT A.CREATOR                                                       
      ,A.NAME                                                          
FROM SYSIBM.SYSTABLES  A                                               
WHERE NOT A.CREATOR = 'SYSIBM'                                         
  AND NOT EXISTS                                                       
          (SELECT 1                                                    
           FROM SYSIBM.SYSINDEXES B                                    
           WHERE A.NAME       = B.TBNAME                               
             AND A.CREATOR    = B.TBCREATOR                            
             AND B.CLUSTERING = 'Y')                                   
  AND 1 < (SELECT COALESCE(COUNT(*) , 0)                               
           FROM SYSIBM.SYSINDEXES B                                    
           WHERE A.NAME    = B.TBNAME                                  
             AND A.CREATOR = B.TBCREATOR)                              
ORDER BY 1 , 2                                                         
;

Note that this query excludes the SYSIBM indexes as IBM also forgot to CLUSTER them!

 

As usual, any comments or questions please mail me!

 

TTFN

Roy Boxwell

2015-08 Overloaded Logs

 

Have all your SQL members an “equivalent” elapsed time?

 

Hey, just a quick newsletter this month to highlight an interesting observation I had recently…

 

The high-water mark for elapsed time for some SQL was inexplicably high…

At a customer site, the Lead DBA and I were analysing SQL performance—using our  tool—and we saw in the data-sharing aggregated view of the executed SQLs that the high-water mark for elapsed time for some SQL was inexplicably high.

We then viewed the data at the Member level for these SQLs and what we saw practically jumped right out of the data at us. The same SQL on one Member was taking up to 45% longer to execute when compared against another member of the Data-sharing Group. Time to see what was going on…

 

High elapsed times and lots of Wait times on one member

On the member in question there were very high elapsed times and lots of Wait times—all well in excess of the other members. Viewing the SQLs that ran on the “problem” Member, it was quickly apparent that data change SQLs, (Insert, Delete, Update and Merge), were happening orders of magnitude more often than on any other member in the group. This started giving the Lead DBA a good idea about where the Problem could lie.

 

The problem was Logging

On this member, the OUTBUFF was increased in size, both the Active and Archive Logs were increased in size, and some traffic was switched to another Member in the group.

Tra la! The problem was fixed! All members now have an “equivalent” elapsed time for the same SQL.

 

When was the last time that you took a look to see how your workload for SQL Updates is “balanced” across your machine? Just saying.

 

As usual, any comments or questions are welcome!

TTFN

Roy Boxwell

2015-07 Bad Data Day

A Good time to check your DB2 Catalog Statistics !

One of my favorite topics is STATISTICS and RUNSTATS.

This month I have a short newsletter involving both of them!

 

Something jumped right out…

Some time ago we were helping one of our customers to perform an Early Precheck (Going from DB2 9 to 10). To do so, we requested a copy of their entire DB2 production statistics so the optimizer could work here at our labs in Dusseldorf – just like at the customer site.

 

…as we loaded up DB2 production statistics of a customer

We loaded up the data and I noticed something that just jumped right out…

SELECT TYPE 
      ,FREQUENCYF 
      ,NUMCOLUMNS 
      ,SUBSTR(COLVALUE , 1 , 11) AS COLVALUE 
      ,COLGROUPCOLNO 
       FROM SYSIBM.SYSCOLDIST 
       WHERE TBOWNER = 'aaaaaaa' 
         AND TBNAME  = 'bbbbbb' 
         AND NAME    = 'cccccc' 
ORDER BY 1 , 3 , 2 
; 
---------+---------+---------+---------+---------+---------+---------
TYPE             FREQUENCYF   NUMCOLUMNS   COLVALUE      COLGROUPCOLNO
---------+---------+---------+---------+---------+---------+---------
F    +0.6066539624818615E-02            1 . xxxxxxxxxx .. 
F    +0.6066539624818615E-02            1 . xxxxxxxxxx 
F    +0.6287988717751475E-02            1 . xxxxxxxxxx .. 
F    +0.6287988717751475E-02            1 . xxxxxxxxxx 
F    +0.8554928116458912E-02            1 . xxxxxxxxxx .. 
F    +0.8554928116458912E-02            1 . xxxxxxxxxx 
F    +0.8578238547293950E-02            1 . xxxxxxxxxx .. 
F    +0.8578238547293950E-02            1 . xxxxxxxxxx 
F    +0.8852136109605646E-02            1 . xxxxxxxxxx 
F    +0.8852136109605646E-02            1 . xxxxxxxxxx .. 
F    +0.1229042465777374E-01            1 . xxxxxxxxxx 
F    +0.1229042465777374E-01            1 . xxxxxxxxxx .. 
F    +0.1331608361451540E-01            1 . xxxxxxxxxx .. 
F    +0.1331608361451540E-01            1 . xxxxxxxxxx 
F    +0.1342098055327308E-01            1 . xxxxxxxxxx .. 
F    +0.1342098055327308E-01            1 . xxxxxxxxxx 
F    +0.1633478440765281E-01            1 . xxxxxxxxxx 
F    +0.1633478440765281E-01            1 . xxxxxxxxxx .. 
F    +0.8439891140288000E+00            1 . xxxxxxxxxx .. 
F    +0.8439891140288000E+00            1 . xxxxxxxxxx 
DSNE610I NUMBER OF ROWS DISPLAYED IS 20 
DSNE616I STATEMENT EXECUTION WAS SUCCESSFUL, SQLCODE IS 100 

 

There were “duplicates”!

This is just one of many examples. Also above, you can see the problem – Notice the data in COLGROUPCOLNO? Sometimes there is a hex value and sometimes not!

Now, believe this or not, all of this goes back to a bug in RUNSTATS in DB2 V8 which got this APAR:

PK33517:

COLGROUPCOLNO ASSOCIATED WITH SINGLE COLUMN CONTAINS A NUMERIC VALUE INSTEAD OF ZERO LENGTH FIELD ACCORDING TO SQL REF

What’s interesting here, is this APAR is marked as FIN so the “bug” disappeared in DB2 9!

The bug was fixed in DB2 9, but the “bad” data was not automatically cleaned up

As you can see, the bug caused an erroneous value in the COLGROUPCOLNO to be set for single column frequency rows.

The bug was then fixed in DB2 9, but the “bad” data that had been inserted was not automatically cleaned up and, as I hope you all know, the SYSCOLDIST data is never automatically deleted – it is only ever updated. So when the bug was fixed, the low-value or hexadecimal column number in that field was no longer EQUAL to a zero length field, and so an insert was done. Since then these rows have just stayed there…

 

Query to count this bad rows in the SYSCOLDIST

I wrote a little query just to show the count of how many of these bad rows existed in the SYSCOLDIST:

SELECT COUNT(*) AS BAD_GUYS 
FROM SYSIBM.SYSCOLDIST 
WHERE NUMCOLUMNS                = 1 
  AND TYPE                      = 'F' 
  AND NOT LENGTH(COLGROUPCOLNO) = 0 
; 
---------+---------+---------+---------+------
    BAD_GUYS 
---------+---------+---------+---------+------
       8680 
DSNE610I NUMBER OF ROWS DISPLAYED IS 1


All of these entries should be deleted from SYSCOLDIST to help the optimizer pick the right access paths!

Check your stats !

I first noticed this problem during a test of our Statistics HealthCheck product, which flagged over 1,200 critical problems in the DB2 catalog and, thinking I had broken something, I checked all of the checks and found the above bad data. Now is as good a time as any to check your stats *and* download our Statistics Healthcheck Freeware!!

 

As usual any questions or  comments are welcome,

TTFN Roy Boxwell

Senior Software Architect