How To
Summary
Determining a user's true access to IBM i objects can be challenging due to the many security mechanisms involved in authority evaluation. A user's effective authority may be derived from multiple sources, including private authorities, authorization lists, group profiles, adopted authority, and inherited permissions within the Integrated File System (IFS). Understanding the final authority that IBM i applies at runtime requires evaluating these sources in the same sequence used by the operating system.
This document presents a comprehensive, SQL-based methodology for determining a user's effective authority to both traditional library-based objects and Integrated File System (IFS) objects. It provides a step-by-step process for collecting, resolving, and consolidating authority information using IBM i Services and SQL queries, enabling administrators to accurately assess a user's access across two key IBM i object spaces:
Objects contained within a specified library
Objects located under a specified IFS directory path
The authority determination process follows the same evaluation order used by IBM i security at runtime, ensuring that the resulting authority calculations closely reflect actual system behavior. Throughout the document, each authority source is examined individually and then incorporated into the overall resolution process to produce an accurate representation of a user's effective permissions.
Upon completion, the process populates two output tables containing a complete authority inventory for the target user profile—one for library objects and one for IFS objects. These inventories can be used for security reviews, access validation, compliance audits, migration planning, troubleshooting authorization issues, and identifying excessive or unintended user privileges.
By leveraging SQL and IBM i Services, organizations can automate authority analysis, reduce reliance on manual security investigations, and gain a consistent, repeatable method for evaluating user access across the IBM i environment.
Environment
Operating System: IBM i
IBM i Version: 7.3 and above (V7R3M0+)
Steps
IBM i · Security · Object Authority Management This document provides a step-by-step SQL-based process for building a complete authority inventory for a target user profile on IBM i. It covers two distinct object spaces: The authority resolution follows the exact order IBM i uses at runtime when checking a user's authority to an object. At the conclusion of this process you will have two populated output tables: Output Table Contents Each row identifies the object, the effective authority level, and the source of that authority (e.g., Overview
SECAUDIT.LIB_AUTH_INVENTORYLibrary object authority inventory SECAUDIT.IFS_AUTH_INVENTORYIFS object authority inventory *ALLOBJ special authority, Private authority, Authorization list, Group *ALLOBJ, Group private authority, Group authorization list, *PUBLIC authority).
ℹ️ Important:
|
Prerequisites
- The executing user must have
*SECADMor*ALLOBJspecial authority, OR specific*READauthority toQSYS2catalog views and the objects being inventoried. - The
SECAUDITschema (library) must exist or be created in Step 1. - For IFS queries,
QSYS2.IFS_OBJECT_STATISTICSandQSYS2.IFS_OBJECT_PRIVILEGESare used — these are available from V7R3M0.
Parameters
Before running any SQL below, replace these placeholder values with your actual targets:
Placeholder | Description | Example |
|---|---|---|
'MYLIB' | The library to inventory | 'PRODLIB' |
'HUGO' | The user profile to check authority for | 'JDOE' |
'/home/mydir' | The IFS directory path to inventory | '/home/jdoe' |
Step 1 — Create the Output Schema and Tables
Run this DDL once to create the schema and both output tables. If they already exist, the CREATE OR REPLACE clause will rebuild them.
⚠️ Important:
|
-- ============================================================
-- category: IBM i Services - Security
-- description: Step 1 - Create output schema and inventory tables
-- minvrm: v7r3m0
-- ============================================================
-- Create the schema if it does not already exist
CREATE SCHEMA IF NOT EXISTS SECAUDIT;
-- --------------------------------------------------------
-- Output table for LIBRARY objects
-- --------------------------------------------------------
CREATE OR REPLACE TABLE SECAUDIT.LIB_AUTH_INVENTORY (
INVENTORY_TS TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
TARGET_USER VARCHAR(10) NOT NULL,
OBJECT_LIBRARY VARCHAR(10) NOT NULL,
OBJECT_NAME VARCHAR(10) NOT NULL,
OBJECT_TYPE VARCHAR(10) NOT NULL,
OBJECT_OWNER VARCHAR(10),
AUTL_NAME VARCHAR(10), -- Authorization list securing the object
AUTH_SOURCE VARCHAR(50) NOT NULL, -- Where authority came from
AUTH_SOURCE_DETAIL VARCHAR(100), -- e.g. group name that provided access
EFFECTIVE_AUTHORITY VARCHAR(50) NOT NULL, -- e.g. *ALL, *CHANGE, *USE, *EXCLUDE
OBJ_OPERATIONAL CHAR(3),
OBJ_MANAGEMENT CHAR(3),
OBJ_EXISTENCE CHAR(3),
OBJ_ALTER CHAR(3),
OBJ_REFERENCE CHAR(3),
DATA_READ CHAR(3),
DATA_ADD CHAR(3),
DATA_UPDATE CHAR(3),
DATA_DELETE CHAR(3),
DATA_EXECUTE CHAR(3),
CONSTRAINT LIB_AUTH_INV_PK
PRIMARY KEY (TARGET_USER, OBJECT_LIBRARY, OBJECT_NAME, OBJECT_TYPE)
);
LABEL ON TABLE SECAUDIT.LIB_AUTH_INVENTORY
IS 'Library Object Authority Inventory';
LABEL ON COLUMN SECAUDIT.LIB_AUTH_INVENTORY (
INVENTORY_TS IS 'Inventory Run Timestamp',
TARGET_USER IS 'User Profile Checked',
OBJECT_LIBRARY IS 'Object Library',
OBJECT_NAME IS 'Object Name',
OBJECT_TYPE IS 'Object Type',
OBJECT_OWNER IS 'Object Owner',
AUTL_NAME IS 'Authorization List',
AUTH_SOURCE IS 'Authority Source (Priority 1-7)',
AUTH_SOURCE_DETAIL IS 'Source Detail (e.g., Group Name)',
EFFECTIVE_AUTHORITY IS 'Effective Authority Level'
);
-- --------------------------------------------------------
-- Output table for IFS objects
-- --------------------------------------------------------
CREATE OR REPLACE TABLE SECAUDIT.IFS_AUTH_INVENTORY (
INVENTORY_TS TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
TARGET_USER VARCHAR(10) NOT NULL,
IFS_PATH_NAME VARCHAR(1024) NOT NULL,
OBJECT_TYPE VARCHAR(20) NOT NULL,
OBJECT_OWNER VARCHAR(10),
AUTL_NAME VARCHAR(10), -- Authorization list securing the object
AUTH_SOURCE VARCHAR(50) NOT NULL,
AUTH_SOURCE_DETAIL VARCHAR(100),
EFFECTIVE_AUTHORITY VARCHAR(50) NOT NULL,
DATA_READ CHAR(3),
DATA_ADD CHAR(3),
DATA_UPDATE CHAR(3),
DATA_DELETE CHAR(3),
DATA_EXECUTE CHAR(3),
CONSTRAINT IFS_AUTH_INV_PK
PRIMARY KEY (TARGET_USER, IFS_PATH_NAME)
);
LABEL ON TABLE SECAUDIT.IFS_AUTH_INVENTORY
IS 'IFS Object Authority Inventory';
LABEL ON COLUMN SECAUDIT.IFS_AUTH_INVENTORY (
INVENTORY_TS IS 'Inventory Run Timestamp',
TARGET_USER IS 'User Profile Checked',
IFS_PATH_NAME IS 'Full IFS Path',
OBJECT_TYPE IS 'IFS Object Type',
OBJECT_OWNER IS 'Object Owner',
AUTL_NAME IS 'Authorization List',
AUTH_SOURCE IS 'Authority Source (Priority 1-7)',
AUTH_SOURCE_DETAIL IS 'Source Detail (e.g., Group Name)',
EFFECTIVE_AUTHORITY IS 'Effective Authority Level'
);
NOTES:
- The SQL statements in this document assume that the SECAUDIT library exists on the system and is available to store the generated output tables. If the library does not already exist, create it before executing the SQL statements by running: CRTLIB LIB(SECAUDIT)
ℹ️ Expected Result:
|
Step 2 — Populate the Library Object Inventory
This query resolves authority for every object in 'MYLIB' for the user 'HUGO', applying the 7-priority cascade. Replace both placeholders before running.
⚠️ Before running::
|
-- ============================================================
-- category: IBM i Services - Security
-- description: Step 2 - Library object authority inventory
-- Resolves authority in IBM i priority order (1-7).
-- Replace 'MYLIB' and 'HUGO' before running.
-- minvrm: v7r3m0
-- ============================================================
-- Remove any previous inventory rows for this user + library
DELETE FROM SECAUDIT.LIB_AUTH_INVENTORY
WHERE TARGET_USER = 'HUGO'
AND OBJECT_LIBRARY = 'MYLIB';
INSERT INTO SECAUDIT.LIB_AUTH_INVENTORY (
INVENTORY_TS, TARGET_USER, OBJECT_LIBRARY, OBJECT_NAME, OBJECT_TYPE,
OBJECT_OWNER, AUTL_NAME, AUTH_SOURCE, AUTH_SOURCE_DETAIL,
EFFECTIVE_AUTHORITY, OBJ_OPERATIONAL, OBJ_MANAGEMENT, OBJ_EXISTENCE,
OBJ_ALTER, OBJ_REFERENCE, DATA_READ, DATA_ADD, DATA_UPDATE, DATA_DELETE, DATA_EXECUTE
)
WITH
-- User profile attributes
user_attrs AS (
SELECT AUTHORIZATION_NAME, SPECIAL_AUTHORITIES,
GROUP_PROFILE_NAME, SUPPLEMENTAL_GROUP_LIST
FROM QSYS2.USER_INFO
WHERE AUTHORIZATION_NAME = 'HUGO'
),
-- Expand all group profiles into individual rows
user_groups AS (
SELECT GROUP_PROFILE_NAME AS GROUP_NAME
FROM user_attrs
WHERE GROUP_PROFILE_NAME IS NOT NULL
AND TRIM(GROUP_PROFILE_NAME) NOT IN ('', '*NONE')
UNION ALL
-- Supplemental groups - tokenize the space-delimited list with XMLTABLE
SELECT TRIM(x.GROUP_TOKEN) AS GROUP_NAME
FROM user_attrs,
XMLTABLE(
'for $t in tokenize($s, " ") return <g>{string($t)}</g>'
PASSING SUPPLEMENTAL_GROUP_LIST AS "s"
COLUMNS GROUP_TOKEN VARCHAR(10) PATH '.'
) AS x
WHERE SUPPLEMENTAL_GROUP_LIST IS NOT NULL
AND TRIM(SUPPLEMENTAL_GROUP_LIST) NOT IN ('', '*NONE')
AND TRIM(x.GROUP_TOKEN) NOT IN ('', '*NONE')
),
-- All objects in the target library + detect *AUTL linkage
obj_list AS (
SELECT os.OBJLIB, os.OBJNAME, os.OBJTYPE, os.OBJOWNER,
NULLIF(TRIM(ap.AUTHORIZATION_LIST), '') AS AUTL_NAME
FROM TABLE(QSYS2.OBJECT_STATISTICS('MYLIB', '*ALL')) AS os
LEFT JOIN QSYS2.OBJECT_PRIVILEGES AS ap
ON ap.SYSTEM_OBJECT_SCHEMA = os.OBJLIB
AND ap.OBJECT_NAME = os.OBJNAME
AND ap.OBJECT_TYPE = os.OBJTYPE
AND ap.USER_NAME = '*PUBLIC'
AND ap.OBJECT_AUTHORITY = '*AUTL'
),
-- Priority 2: User private authority
user_priv AS (
SELECT op.SYSTEM_OBJECT_SCHEMA AS OBJLIB, op.OBJECT_NAME AS OBJNAME,
op.OBJECT_TYPE AS OBJTYPE, op.OBJECT_AUTHORITY AS EFFECTIVE_AUTHORITY,
op.OBJECT_OPERATIONAL, op.OBJECT_MANAGEMENT, op.OBJECT_EXISTENCE,
op.OBJECT_ALTER, op.OBJECT_REFERENCE,
op.DATA_READ, op.DATA_ADD, op.DATA_UPDATE, op.DATA_DELETE, op.DATA_EXECUTE
FROM QSYS2.OBJECT_PRIVILEGES AS op
WHERE op.SYSTEM_OBJECT_SCHEMA = 'MYLIB'
AND op.USER_NAME = 'HUGO'
AND op.OBJECT_TYPE <> '*AUTL'
AND op.USER_NAME <> '*PUBLIC'
),
-- Priority 3: User private entry in the authorization list
user_autl_priv AS (
SELECT ol.OBJLIB, ol.OBJNAME, ol.OBJTYPE,
al.OBJECT_AUTHORITY AS EFFECTIVE_AUTHORITY,
al.OBJECT_OPERATIONAL, al.OBJECT_MANAGEMENT, al.OBJECT_EXISTENCE,
al.OBJECT_ALTER, al.OBJECT_REFERENCE,
al.DATA_READ, al.DATA_ADD, al.DATA_UPDATE, al.DATA_DELETE, al.DATA_EXECUTE
FROM obj_list AS ol
JOIN QSYS2.OBJECT_PRIVILEGES AS al
ON al.SYSTEM_OBJECT_SCHEMA = 'QSYS'
AND al.OBJECT_NAME = ol.AUTL_NAME
AND al.OBJECT_TYPE = '*AUTL'
AND al.USER_NAME = 'HUGO'
WHERE ol.AUTL_NAME IS NOT NULL
),
-- Priority 4: Any group profile that has *ALLOBJ
grp_allobj AS (
SELECT ug.GROUP_NAME
FROM user_groups AS ug
JOIN QSYS2.USER_INFO AS gui
ON gui.AUTHORIZATION_NAME = ug.GROUP_NAME
WHERE gui.SPECIAL_AUTHORITIES LIKE '%*ALLOBJ%'
FETCH FIRST 1 ROW ONLY
),
-- Priority 5: Best group private authority on each object
grp_priv AS (
SELECT op.SYSTEM_OBJECT_SCHEMA AS OBJLIB, op.OBJECT_NAME AS OBJNAME,
op.OBJECT_TYPE AS OBJTYPE, op.USER_NAME AS GROUP_NAME,
op.OBJECT_AUTHORITY AS EFFECTIVE_AUTHORITY,
op.OBJECT_OPERATIONAL, op.OBJECT_MANAGEMENT, op.OBJECT_EXISTENCE,
op.OBJECT_ALTER, op.OBJECT_REFERENCE,
op.DATA_READ, op.DATA_ADD, op.DATA_UPDATE, op.DATA_DELETE, op.DATA_EXECUTE,
ROW_NUMBER() OVER (
PARTITION BY op.SYSTEM_OBJECT_SCHEMA, op.OBJECT_NAME, op.OBJECT_TYPE
ORDER BY CASE op.OBJECT_AUTHORITY
WHEN '*ALL' THEN 1 WHEN '*CHANGE' THEN 2
WHEN '*USE' THEN 3 WHEN '*EXCLUDE' THEN 4 ELSE 5
END
) AS RNK
FROM QSYS2.OBJECT_PRIVILEGES AS op
JOIN user_groups AS ug ON op.USER_NAME = ug.GROUP_NAME
WHERE op.SYSTEM_OBJECT_SCHEMA = 'MYLIB'
AND op.USER_NAME <> '*PUBLIC'
),
-- Priority 6: Best group entry in the authorization list
grp_autl_priv AS (
SELECT ol.OBJLIB, ol.OBJNAME, ol.OBJTYPE, al.USER_NAME AS GROUP_NAME,
al.OBJECT_AUTHORITY AS EFFECTIVE_AUTHORITY,
al.OBJECT_OPERATIONAL, al.OBJECT_MANAGEMENT, al.OBJECT_EXISTENCE,
al.OBJECT_ALTER, al.OBJECT_REFERENCE,
al.DATA_READ, al.DATA_ADD, al.DATA_UPDATE, al.DATA_DELETE, al.DATA_EXECUTE,
ROW_NUMBER() OVER (
PARTITION BY ol.OBJLIB, ol.OBJNAME, ol.OBJTYPE
ORDER BY CASE al.OBJECT_AUTHORITY
WHEN '*ALL' THEN 1 WHEN '*CHANGE' THEN 2
WHEN '*USE' THEN 3 WHEN '*EXCLUDE' THEN 4 ELSE 5
END
) AS RNK
FROM obj_list AS ol
JOIN QSYS2.OBJECT_PRIVILEGES AS al
ON al.SYSTEM_OBJECT_SCHEMA = 'QSYS'
AND al.OBJECT_NAME = ol.AUTL_NAME
AND al.OBJECT_TYPE = '*AUTL'
AND al.USER_NAME <> '*PUBLIC'
JOIN user_groups AS ug ON al.USER_NAME = ug.GROUP_NAME
WHERE ol.AUTL_NAME IS NOT NULL
),
-- Priority 7: *PUBLIC authority
pub_auth AS (
-- Branch A: direct *PUBLIC (not secured by *AUTL)
SELECT op.SYSTEM_OBJECT_SCHEMA AS OBJLIB, op.OBJECT_NAME AS OBJNAME,
op.OBJECT_TYPE AS OBJTYPE, op.OBJECT_AUTHORITY AS EFFECTIVE_AUTHORITY,
op.OBJECT_OPERATIONAL, op.OBJECT_MANAGEMENT, op.OBJECT_EXISTENCE,
op.OBJECT_ALTER, op.OBJECT_REFERENCE,
op.DATA_READ, op.DATA_ADD, op.DATA_UPDATE, op.DATA_DELETE, op.DATA_EXECUTE
FROM QSYS2.OBJECT_PRIVILEGES AS op
WHERE op.SYSTEM_OBJECT_SCHEMA = 'MYLIB'
AND op.USER_NAME = '*PUBLIC'
AND op.OBJECT_AUTHORITY <> '*AUTL'
UNION ALL
-- Branch B: object secured by *AUTL - get *PUBLIC from inside the auth list
SELECT ol.OBJLIB, ol.OBJNAME, ol.OBJTYPE,
al.OBJECT_AUTHORITY, al.OBJECT_OPERATIONAL, al.OBJECT_MANAGEMENT,
al.OBJECT_EXISTENCE, al.OBJECT_ALTER, al.OBJECT_REFERENCE,
al.DATA_READ, al.DATA_ADD, al.DATA_UPDATE, al.DATA_DELETE, al.DATA_EXECUTE
FROM obj_list AS ol
JOIN QSYS2.OBJECT_PRIVILEGES AS al
ON al.SYSTEM_OBJECT_SCHEMA = 'QSYS'
AND al.OBJECT_NAME = ol.AUTL_NAME
AND al.OBJECT_TYPE = '*AUTL'
AND al.USER_NAME = '*PUBLIC'
WHERE ol.AUTL_NAME IS NOT NULL
),
-- Authority resolution - 7-priority CASE chain
resolved AS (
SELECT 'HUGO' AS TARGET_USER,
ol.OBJLIB, ol.OBJNAME, ol.OBJTYPE, ol.OBJOWNER, ol.AUTL_NAME,
CASE
WHEN (SELECT SPECIAL_AUTHORITIES FROM user_attrs) LIKE '%*ALLOBJ%'
THEN 'Priority 1 - User *ALLOBJ special authority'
WHEN up.OBJNAME IS NOT NULL THEN 'Priority 2 - User private authority'
WHEN uap.OBJNAME IS NOT NULL THEN 'Priority 3 - User authority via authorization list'
WHEN (SELECT COUNT(*) FROM grp_allobj) > 0
THEN 'Priority 4 - Group *ALLOBJ special authority'
WHEN gp.OBJNAME IS NOT NULL THEN 'Priority 5 - Group private authority'
WHEN gap.OBJNAME IS NOT NULL THEN 'Priority 6 - Group authority via authorization list'
ELSE 'Priority 7 - *PUBLIC authority'
END AS AUTH_SOURCE,
CASE
WHEN (SELECT SPECIAL_AUTHORITIES FROM user_attrs) LIKE '%*ALLOBJ%'
THEN 'User profile: HUGO'
WHEN up.OBJNAME IS NOT NULL THEN 'User profile: HUGO'
WHEN uap.OBJNAME IS NOT NULL THEN 'Authorization list: ' || COALESCE(ol.AUTL_NAME, '')
WHEN (SELECT COUNT(*) FROM grp_allobj) > 0
THEN 'Group profile: ' || (SELECT GROUP_NAME FROM grp_allobj)
WHEN gp.OBJNAME IS NOT NULL THEN 'Group profile: ' || gp.GROUP_NAME
WHEN gap.OBJNAME IS NOT NULL THEN 'Group profile: ' || gap.GROUP_NAME
|| ' via authorization list: ' || COALESCE(ol.AUTL_NAME, '')
ELSE '*PUBLIC'
END AS AUTH_SOURCE_DETAIL,
CASE
WHEN (SELECT SPECIAL_AUTHORITIES FROM user_attrs) LIKE '%*ALLOBJ%'
THEN '*ALL (via *ALLOBJ)'
WHEN up.OBJNAME IS NOT NULL THEN up.EFFECTIVE_AUTHORITY
WHEN uap.OBJNAME IS NOT NULL THEN uap.EFFECTIVE_AUTHORITY
WHEN (SELECT COUNT(*) FROM grp_allobj) > 0 THEN '*ALL (via *ALLOBJ)'
WHEN gp.OBJNAME IS NOT NULL THEN gp.EFFECTIVE_AUTHORITY
WHEN gap.OBJNAME IS NOT NULL THEN gap.EFFECTIVE_AUTHORITY
ELSE COALESCE(pa.EFFECTIVE_AUTHORITY, '*EXCLUDE (no *PUBLIC entry)')
END AS EFFECTIVE_AUTHORITY,
CASE WHEN (SELECT SPECIAL_AUTHORITIES FROM user_attrs) LIKE '%*ALLOBJ%' THEN 'YES'
WHEN up.OBJNAME IS NOT NULL THEN up.OBJ_OPERATIONAL
WHEN uap.OBJNAME IS NOT NULL THEN uap.OBJ_OPERATIONAL
WHEN (SELECT COUNT(*) FROM grp_allobj) > 0 THEN 'YES'
WHEN gp.OBJNAME IS NOT NULL THEN gp.OBJ_OPERATIONAL
WHEN gap.OBJNAME IS NOT NULL THEN gap.OBJ_OPERATIONAL
ELSE pa.OBJ_OPERATIONAL END AS OBJ_OPERATIONAL,
CASE WHEN up.OBJNAME IS NOT NULL THEN up.OBJ_MANAGEMENT
WHEN uap.OBJNAME IS NOT NULL THEN uap.OBJ_MANAGEMENT
WHEN (SELECT SPECIAL_AUTHORITIES FROM user_attrs) LIKE '%*ALLOBJ%' THEN 'YES'
WHEN gp.OBJNAME IS NOT NULL THEN gp.OBJ_MANAGEMENT
WHEN gap.OBJNAME IS NOT NULL THEN gap.OBJ_MANAGEMENT
ELSE pa.OBJ_MANAGEMENT END AS OBJ_MANAGEMENT,
CASE WHEN up.OBJNAME IS NOT NULL THEN up.OBJ_EXISTENCE
WHEN uap.OBJNAME IS NOT NULL THEN uap.OBJ_EXISTENCE
WHEN (SELECT SPECIAL_AUTHORITIES FROM user_attrs) LIKE '%*ALLOBJ%' THEN 'YES'
WHEN gp.OBJNAME IS NOT NULL THEN gp.OBJ_EXISTENCE
WHEN gap.OBJNAME IS NOT NULL THEN gap.OBJ_EXISTENCE
ELSE pa.OBJ_EXISTENCE END AS OBJ_EXISTENCE,
CASE WHEN up.OBJNAME IS NOT NULL THEN up.OBJ_ALTER
WHEN uap.OBJNAME IS NOT NULL THEN uap.OBJ_ALTER
WHEN (SELECT SPECIAL_AUTHORITIES FROM user_attrs) LIKE '%*ALLOBJ%' THEN 'YES'
WHEN gp.OBJNAME IS NOT NULL THEN gp.OBJ_ALTER
WHEN gap.OBJNAME IS NOT NULL THEN gap.OBJ_ALTER
ELSE pa.OBJ_ALTER END AS OBJ_ALTER,
CASE WHEN up.OBJNAME IS NOT NULL THEN up.OBJ_REFERENCE
WHEN uap.OBJNAME IS NOT NULL THEN uap.OBJ_REFERENCE
WHEN (SELECT SPECIAL_AUTHORITIES FROM user_attrs) LIKE '%*ALLOBJ%' THEN 'YES'
WHEN gp.OBJNAME IS NOT NULL THEN gp.OBJ_REFERENCE
WHEN gap.OBJNAME IS NOT NULL THEN gap.OBJ_REFERENCE
ELSE pa.OBJ_REFERENCE END AS OBJ_REFERENCE,
CASE WHEN up.OBJNAME IS NOT NULL THEN up.DATA_READ
WHEN uap.OBJNAME IS NOT NULL THEN uap.DATA_READ
WHEN (SELECT SPECIAL_AUTHORITIES FROM user_attrs) LIKE '%*ALLOBJ%' THEN 'YES'
WHEN gp.OBJNAME IS NOT NULL THEN gp.DATA_READ
WHEN gap.OBJNAME IS NOT NULL THEN gap.DATA_READ
ELSE pa.DATA_READ END AS DATA_READ,
CASE WHEN up.OBJNAME IS NOT NULL THEN up.DATA_ADD
WHEN uap.OBJNAME IS NOT NULL THEN uap.DATA_ADD
WHEN (SELECT SPECIAL_AUTHORITIES FROM user_attrs) LIKE '%*ALLOBJ%' THEN 'YES'
WHEN gp.OBJNAME IS NOT NULL THEN gp.DATA_ADD
WHEN gap.OBJNAME IS NOT NULL THEN gap.DATA_ADD
ELSE pa.DATA_ADD END AS DATA_ADD,
CASE WHEN up.OBJNAME IS NOT NULL THEN up.DATA_UPDATE
WHEN uap.OBJNAME IS NOT NULL THEN uap.DATA_UPDATE
WHEN (SELECT SPECIAL_AUTHORITIES FROM user_attrs) LIKE '%*ALLOBJ%' THEN 'YES'
WHEN gp.OBJNAME IS NOT NULL THEN gp.DATA_UPDATE
WHEN gap.OBJNAME IS NOT NULL THEN gap.DATA_UPDATE
ELSE pa.DATA_UPDATE END AS DATA_UPDATE,
CASE WHEN up.OBJNAME IS NOT NULL THEN up.DATA_DELETE
WHEN uap.OBJNAME IS NOT NULL THEN uap.DATA_DELETE
WHEN (SELECT SPECIAL_AUTHORITIES FROM user_attrs) LIKE '%*ALLOBJ%' THEN 'YES'
WHEN gp.OBJNAME IS NOT NULL THEN gp.DATA_DELETE
WHEN gap.OBJNAME IS NOT NULL THEN gap.DATA_DELETE
ELSE pa.DATA_DELETE END AS DATA_DELETE,
CASE WHEN up.OBJNAME IS NOT NULL THEN up.DATA_EXECUTE
WHEN uap.OBJNAME IS NOT NULL THEN uap.DATA_EXECUTE
WHEN (SELECT SPECIAL_AUTHORITIES FROM user_attrs) LIKE '%*ALLOBJ%' THEN 'YES'
WHEN gp.OBJNAME IS NOT NULL THEN gp.DATA_EXECUTE
WHEN gap.OBJNAME IS NOT NULL THEN gap.DATA_EXECUTE
ELSE pa.DATA_EXECUTE END AS DATA_EXECUTE
FROM obj_list AS ol
LEFT JOIN user_priv AS up ON up.OBJLIB = ol.OBJLIB AND up.OBJNAME = ol.OBJNAME AND up.OBJTYPE = ol.OBJTYPE
LEFT JOIN user_autl_priv AS uap ON uap.OBJLIB = ol.OBJLIB AND uap.OBJNAME = ol.OBJNAME AND uap.OBJTYPE = ol.OBJTYPE
LEFT JOIN (SELECT * FROM grp_priv WHERE RNK = 1) AS gp ON gp.OBJLIB = ol.OBJLIB AND gp.OBJNAME = ol.OBJNAME AND gp.OBJTYPE = ol.OBJTYPE
LEFT JOIN (SELECT * FROM grp_autl_priv WHERE RNK = 1) AS gap ON gap.OBJLIB = ol.OBJLIB AND gap.OBJNAME = ol.OBJNAME AND gap.OBJTYPE = ol.OBJTYPE
LEFT JOIN pub_auth AS pa ON pa.OBJLIB = ol.OBJLIB AND pa.OBJNAME = ol.OBJNAME AND pa.OBJTYPE = ol.OBJTYPE
)
SELECT CURRENT_TIMESTAMP, TARGET_USER, OBJLIB, OBJNAME, OBJTYPE, OBJOWNER, AUTL_NAME,
AUTH_SOURCE, AUTH_SOURCE_DETAIL, EFFECTIVE_AUTHORITY,
OBJ_OPERATIONAL, OBJ_MANAGEMENT, OBJ_EXISTENCE, OBJ_ALTER, OBJ_REFERENCE,
DATA_READ, DATA_ADD, DATA_UPDATE, DATA_DELETE, DATA_EXECUTE
FROM resolved
ORDER BY OBJLIB, OBJNAME, OBJTYPE;ℹ️ Expected Result:
|
Sample Output — Library Inventory
| TARGET_USER | OBJECT_LIBRARY | OBJECT_NAME | OBJECT_TYPE | EFFECTIVE_AUTHORITY | AUTH_SOURCE |
|---|---|---|---|---|---|
| HUGO | V6CASTIL | A | *QRYDFN | *EXCLUDE | Priority 7 - *PUBLIC authority |
| HUGO | V6CASTIL | ADPAUT | *PGM | *CHANGE | Priority 2 - User private authority |
| HUGO | V6CASTIL | ADPAUT1 | *PGM | *CHANGE | Priority 7 - *PUBLIC authority |
| HUGO | V6CASTIL | ADPAUT2 | *PGM | *USE | Priority 2 - User private authority |
| HUGO | V6CASTIL | ASP_INFO | *FILE | *CHANGE | Priority 3 - User authority via authorization list |
Step 3 — Populate the IFS Object Inventory
This query resolves authority for every object under an IFS directory for the user 'HUGO'.
⚠️ Before running::
|
SQL — Step 3: IFS Object Inventory
-- ============================================================
-- category: IBM i Services - Security
-- description: Step 3 - IFS object authority inventory
-- Resolves authority in IBM i priority order (1-7).
-- Replace '/home/mydir' and 'HUGO' before running.
-- minvrm: v7r3m0
-- ============================================================
-- Remove any previous inventory rows for this user + path before re-inserting
DELETE FROM SECAUDIT.IFS_AUTH_INVENTORY
WHERE TARGET_USER = 'HUGO'
AND IFS_PATH_NAME LIKE '/home/mydir%';
INSERT INTO SECAUDIT.IFS_AUTH_INVENTORY (
INVENTORY_TS, TARGET_USER, IFS_PATH_NAME, OBJECT_TYPE, OBJECT_OWNER,
AUTL_NAME, AUTH_SOURCE, AUTH_SOURCE_DETAIL, EFFECTIVE_AUTHORITY,
DATA_READ, DATA_ADD, DATA_UPDATE, DATA_DELETE, DATA_EXECUTE
)
WITH
-- User profile attributes
ifs_user_attrs AS (
SELECT AUTHORIZATION_NAME, SPECIAL_AUTHORITIES,
GROUP_PROFILE_NAME, SUPPLEMENTAL_GROUP_LIST
FROM QSYS2.USER_INFO
WHERE AUTHORIZATION_NAME = 'HUGO'
),
-- All group profiles for the user
ifs_user_groups AS (
SELECT GROUP_PROFILE_NAME AS GROUP_NAME
FROM ifs_user_attrs
WHERE GROUP_PROFILE_NAME IS NOT NULL
AND TRIM(GROUP_PROFILE_NAME) NOT IN ('', '*NONE')
UNION ALL
SELECT TRIM(x.GROUP_TOKEN) AS GROUP_NAME
FROM ifs_user_attrs,
XMLTABLE(
'for $t in tokenize($s, " ") return <g>{string($t)}</g>'
PASSING SUPPLEMENTAL_GROUP_LIST AS "s"
COLUMNS GROUP_TOKEN VARCHAR(10) PATH '.'
) AS x
WHERE SUPPLEMENTAL_GROUP_LIST IS NOT NULL
AND TRIM(SUPPLEMENTAL_GROUP_LIST) NOT IN ('', '*NONE')
AND TRIM(x.GROUP_TOKEN) NOT IN ('', '*NONE')
),
-- All IFS objects under the target directory (recursive)
ifs_obj_list AS (
SELECT PATH_NAME, OBJECT_TYPE, OBJECT_OWNER,
AUTHORIZATION_LIST AS AUTL_NAME
FROM TABLE(QSYS2.IFS_OBJECT_STATISTICS(
START_PATH_NAME => '/home/mydir',
SUBTREE_DIRECTORIES => 'YES'))
),
-- Priority 2: User private authority on each IFS object
ifs_user_priv AS (
SELECT ip.PATH_NAME, ip.AUTHORIZATION_NAME,
ip.DATA_AUTHORITY AS EFFECTIVE_AUTHORITY,
ip.DATA_READ, ip.DATA_ADD, ip.DATA_UPDATE, ip.DATA_DELETE, ip.DATA_EXECUTE
FROM TABLE(QSYS2.IFS_OBJECT_PRIVILEGES(
PATH_NAME => '/home/mydir')) AS ip
WHERE ip.AUTHORIZATION_NAME = 'HUGO'
AND ip.AUTHORIZATION_NAME <> '*PUBLIC'
),
-- Priority 3: User private entry in the authorization list on IFS object
ifs_user_autl_priv AS (
SELECT ol.PATH_NAME,
al.OBJECT_AUTHORITY AS EFFECTIVE_AUTHORITY,
al.DATA_READ, al.DATA_ADD, al.DATA_UPDATE, al.DATA_DELETE, al.DATA_EXECUTE
FROM ifs_obj_list AS ol
JOIN QSYS2.OBJECT_PRIVILEGES AS al
ON al.SYSTEM_OBJECT_SCHEMA = 'QSYS'
AND al.OBJECT_NAME = ol.AUTL_NAME
AND al.OBJECT_TYPE = '*AUTL'
AND al.USER_NAME = 'HUGO'
WHERE ol.AUTL_NAME IS NOT NULL
),
-- Priority 4: Any group that has *ALLOBJ
ifs_grp_allobj AS (
SELECT ug.GROUP_NAME
FROM ifs_user_groups AS ug
JOIN QSYS2.USER_INFO AS gui
ON gui.AUTHORIZATION_NAME = ug.GROUP_NAME
WHERE gui.SPECIAL_AUTHORITIES LIKE '%*ALLOBJ%'
FETCH FIRST 1 ROW ONLY
),
-- Priority 5: Best group private authority on each IFS object
ifs_grp_priv AS (
SELECT ip.PATH_NAME, ip.AUTHORIZATION_NAME AS GROUP_NAME,
ip.DATA_AUTHORITY AS EFFECTIVE_AUTHORITY,
ip.DATA_READ, ip.DATA_ADD, ip.DATA_UPDATE, ip.DATA_DELETE, ip.DATA_EXECUTE,
ROW_NUMBER() OVER (
PARTITION BY ip.PATH_NAME
ORDER BY CASE ip.DATA_AUTHORITY
WHEN '*ALL' THEN 1 WHEN '*CHANGE' THEN 2
WHEN '*USE' THEN 3 WHEN '*EXCLUDE' THEN 4 ELSE 5
END
) AS RNK
FROM TABLE(QSYS2.IFS_OBJECT_PRIVILEGES(
PATH_NAME => '/home/mydir')) AS ip
JOIN ifs_user_groups AS ug ON ip.AUTHORIZATION_NAME = ug.GROUP_NAME
WHERE ip.AUTHORIZATION_NAME <> '*PUBLIC'
),
-- Priority 6: Best group authority via authorization list on IFS object
ifs_grp_autl_priv AS (
SELECT ol.PATH_NAME, al.USER_NAME AS GROUP_NAME,
al.OBJECT_AUTHORITY AS EFFECTIVE_AUTHORITY,
al.DATA_READ, al.DATA_ADD, al.DATA_UPDATE, al.DATA_DELETE, al.DATA_EXECUTE,
ROW_NUMBER() OVER (
PARTITION BY ol.PATH_NAME
ORDER BY CASE al.OBJECT_AUTHORITY
WHEN '*ALL' THEN 1 WHEN '*CHANGE' THEN 2
WHEN '*USE' THEN 3 WHEN '*EXCLUDE' THEN 4 ELSE 5
END
) AS RNK
FROM ifs_obj_list AS ol
JOIN QSYS2.OBJECT_PRIVILEGES AS al
ON al.SYSTEM_OBJECT_SCHEMA = 'QSYS'
AND al.OBJECT_NAME = ol.AUTL_NAME
AND al.OBJECT_TYPE = '*AUTL'
AND al.USER_NAME <> '*PUBLIC'
JOIN ifs_user_groups AS ug ON al.USER_NAME = ug.GROUP_NAME
WHERE ol.AUTL_NAME IS NOT NULL
),
-- Priority 7: *PUBLIC authority on IFS objects
ifs_pub_auth AS (
-- Branch A: object NOT secured by auth list
SELECT ip.PATH_NAME, ip.DATA_AUTHORITY AS EFFECTIVE_AUTHORITY,
ip.DATA_READ, ip.DATA_ADD, ip.DATA_UPDATE, ip.DATA_DELETE, ip.DATA_EXECUTE
FROM TABLE(QSYS2.IFS_OBJECT_PRIVILEGES(
PATH_NAME => '/home/mydir')) AS ip
JOIN ifs_obj_list AS ol ON ol.PATH_NAME = ip.PATH_NAME AND ol.AUTL_NAME IS NULL
WHERE ip.AUTHORIZATION_NAME = '*PUBLIC'
AND ip.DATA_AUTHORITY <> '*AUTL'
UNION ALL
-- Branch B: object IS secured by auth list - get *PUBLIC from inside the list
SELECT ol.PATH_NAME, al.OBJECT_AUTHORITY,
al.DATA_READ, al.DATA_ADD, al.DATA_UPDATE, al.DATA_DELETE, al.DATA_EXECUTE
FROM ifs_obj_list AS ol
JOIN QSYS2.OBJECT_PRIVILEGES AS al
ON al.SYSTEM_OBJECT_SCHEMA = 'QSYS'
AND al.OBJECT_NAME = ol.AUTL_NAME
AND al.OBJECT_TYPE = '*AUTL'
AND al.USER_NAME = '*PUBLIC'
WHERE ol.AUTL_NAME IS NOT NULL
),
-- Authority resolution - 7-priority CASE chain
ifs_resolved AS (
SELECT 'HUGO' AS TARGET_USER,
ol.PATH_NAME, ol.OBJECT_TYPE, ol.OBJECT_OWNER, ol.AUTL_NAME,
CASE
WHEN (SELECT SPECIAL_AUTHORITIES FROM ifs_user_attrs) LIKE '%*ALLOBJ%'
THEN 'Priority 1 - User *ALLOBJ special authority'
WHEN up.PATH_NAME IS NOT NULL THEN 'Priority 2 - User private authority'
WHEN uap.PATH_NAME IS NOT NULL THEN 'Priority 3 - User authority via authorization list'
WHEN (SELECT COUNT(*) FROM ifs_grp_allobj) > 0
THEN 'Priority 4 - Group *ALLOBJ special authority'
WHEN gp.PATH_NAME IS NOT NULL THEN 'Priority 5 - Group private authority'
WHEN gap.PATH_NAME IS NOT NULL THEN 'Priority 6 - Group authority via authorization list'
ELSE 'Priority 7 - *PUBLIC authority'
END AS AUTH_SOURCE,
CASE
WHEN (SELECT SPECIAL_AUTHORITIES FROM ifs_user_attrs) LIKE '%*ALLOBJ%'
THEN 'User profile: HUGO'
WHEN up.PATH_NAME IS NOT NULL THEN 'User profile: HUGO'
WHEN uap.PATH_NAME IS NOT NULL THEN 'Authorization list: ' || COALESCE(ol.AUTL_NAME, '')
WHEN (SELECT COUNT(*) FROM ifs_grp_allobj) > 0
THEN 'Group profile: ' || (SELECT GROUP_NAME FROM ifs_grp_allobj)
WHEN gp.PATH_NAME IS NOT NULL THEN 'Group profile: ' || gp.GROUP_NAME
WHEN gap.PATH_NAME IS NOT NULL THEN 'Group profile: ' || gap.GROUP_NAME
|| ' via authorization list: ' || COALESCE(ol.AUTL_NAME, '')
ELSE '*PUBLIC'
END AS AUTH_SOURCE_DETAIL,
CASE
WHEN (SELECT SPECIAL_AUTHORITIES FROM ifs_user_attrs) LIKE '%*ALLOBJ%'
THEN '*ALL (via *ALLOBJ)'
WHEN up.PATH_NAME IS NOT NULL THEN up.EFFECTIVE_AUTHORITY
WHEN uap.PATH_NAME IS NOT NULL THEN uap.EFFECTIVE_AUTHORITY
WHEN (SELECT COUNT(*) FROM ifs_grp_allobj) > 0 THEN '*ALL (via *ALLOBJ)'
WHEN gp.PATH_NAME IS NOT NULL THEN gp.EFFECTIVE_AUTHORITY
WHEN gap.PATH_NAME IS NOT NULL THEN gap.EFFECTIVE_AUTHORITY
ELSE COALESCE(pa.EFFECTIVE_AUTHORITY, '*EXCLUDE (no *PUBLIC entry)')
END AS EFFECTIVE_AUTHORITY,
CASE WHEN up.PATH_NAME IS NOT NULL THEN up.DATA_READ
WHEN uap.PATH_NAME IS NOT NULL THEN uap.DATA_READ
WHEN (SELECT SPECIAL_AUTHORITIES FROM ifs_user_attrs) LIKE '%*ALLOBJ%' THEN 'YES'
WHEN gp.PATH_NAME IS NOT NULL THEN gp.DATA_READ
WHEN gap.PATH_NAME IS NOT NULL THEN gap.DATA_READ
ELSE pa.DATA_READ END AS DATA_READ,
CASE WHEN up.PATH_NAME IS NOT NULL THEN up.DATA_ADD
WHEN uap.PATH_NAME IS NOT NULL THEN uap.DATA_ADD
WHEN (SELECT SPECIAL_AUTHORITIES FROM ifs_user_attrs) LIKE '%*ALLOBJ%' THEN 'YES'
WHEN gp.PATH_NAME IS NOT NULL THEN gp.DATA_ADD
WHEN gap.PATH_NAME IS NOT NULL THEN gap.DATA_ADD
ELSE pa.DATA_ADD END AS DATA_ADD,
CASE WHEN up.PATH_NAME IS NOT NULL THEN up.DATA_UPDATE
WHEN uap.PATH_NAME IS NOT NULL THEN uap.DATA_UPDATE
WHEN (SELECT SPECIAL_AUTHORITIES FROM ifs_user_attrs) LIKE '%*ALLOBJ%' THEN 'YES'
WHEN gp.PATH_NAME IS NOT NULL THEN gp.DATA_UPDATE
WHEN gap.PATH_NAME IS NOT NULL THEN gap.DATA_UPDATE
ELSE pa.DATA_UPDATE END AS DATA_UPDATE,
CASE WHEN up.PATH_NAME IS NOT NULL THEN up.DATA_DELETE
WHEN uap.PATH_NAME IS NOT NULL THEN uap.DATA_DELETE
WHEN (SELECT SPECIAL_AUTHORITIES FROM ifs_user_attrs) LIKE '%*ALLOBJ%' THEN 'YES'
WHEN gp.PATH_NAME IS NOT NULL THEN gp.DATA_DELETE
WHEN gap.PATH_NAME IS NOT NULL THEN gap.DATA_DELETE
ELSE pa.DATA_DELETE END AS DATA_DELETE,
CASE WHEN up.PATH_NAME IS NOT NULL THEN up.DATA_EXECUTE
WHEN uap.PATH_NAME IS NOT NULL THEN uap.DATA_EXECUTE
WHEN (SELECT SPECIAL_AUTHORITIES FROM ifs_user_attrs) LIKE '%*ALLOBJ%' THEN 'YES'
WHEN gp.PATH_NAME IS NOT NULL THEN gp.DATA_EXECUTE
WHEN gap.PATH_NAME IS NOT NULL THEN gap.DATA_EXECUTE
ELSE pa.DATA_EXECUTE END AS DATA_EXECUTE
FROM ifs_obj_list AS ol
LEFT JOIN ifs_user_priv AS up ON up.PATH_NAME = ol.PATH_NAME
LEFT JOIN ifs_user_autl_priv AS uap ON uap.PATH_NAME = ol.PATH_NAME
LEFT JOIN (SELECT * FROM ifs_grp_priv WHERE RNK = 1) AS gp ON gp.PATH_NAME = ol.PATH_NAME
LEFT JOIN (SELECT * FROM ifs_grp_autl_priv WHERE RNK = 1) AS gap ON gap.PATH_NAME = ol.PATH_NAME
LEFT JOIN ifs_pub_auth AS pa ON pa.PATH_NAME = ol.PATH_NAME
)
SELECT CURRENT_TIMESTAMP, TARGET_USER, PATH_NAME, OBJECT_TYPE, OBJECT_OWNER,
AUTL_NAME, AUTH_SOURCE, AUTH_SOURCE_DETAIL, EFFECTIVE_AUTHORITY,
DATA_READ, DATA_ADD, DATA_UPDATE, DATA_DELETE, DATA_EXECUTE
FROM ifs_resolved
ORDER BY PATH_NAME;ℹ️ Expected Result:
|
Sample Output — IFS Inventory
| TARGET_USER | IFS_PATH_NAME | OBJECT_TYPE | EFFECTIVE_AUTHORITY | AUTH_SOURCE |
|---|---|---|---|---|
| HUGO | /home/v6castil | *DIR | *CHANGE | Priority 3 - User authority via authorization list |
| HUGO | /home/v6castil/.sh_history | *STMF | *EXCLUDE | Priority 7 - *PUBLIC authority |
| HUGO | /home/v6castil/AJSWeb.jar | *STMF | *CHANGE | Priority 3 - User authority via authorization list |
| HUGO | /home/v6castil/aut.txt | *STMF | *CHANGE | Priority 3 - User authority via authorization list |
| HUGO | /home/v6castil/aut2.txt | *STMF | *EXCLUDE | Priority 7 - *PUBLIC authority |
Step 4 — Review the Results
4a — Library Object Authority Summary (by source)
A high-level count of how many objects each authority source controls, grouped by library.
-- ============================================================
-- category: IBM i Services - Security
-- description: Step 4a - Library authority summary by source
-- minvrm: v7r3m0
-- ============================================================
SELECT
TARGET_USER,
OBJECT_LIBRARY,
AUTH_SOURCE,
COUNT(*) AS OBJECT_COUNT,
LISTAGG(DISTINCT EFFECTIVE_AUTHORITY, ', ')
WITHIN GROUP (ORDER BY EFFECTIVE_AUTHORITY) AS AUTHORITY_LEVELS
FROM SECAUDIT.LIB_AUTH_INVENTORY
GROUP BY
TARGET_USER,
OBJECT_LIBRARY,
AUTH_SOURCE
ORDER BY
TARGET_USER,
OBJECT_LIBRARY,
AUTH_SOURCE;4b — Library Object Authority Detail
Full detail of every object in the library inventory including all authority bits.
-- ============================================================
-- category: IBM i Services - Security
-- description: Step 4b - Full library authority detail
-- minvrm: v7r3m0
-- ============================================================
SELECT
TARGET_USER,
OBJECT_LIBRARY,
OBJECT_NAME,
OBJECT_TYPE,
OBJECT_OWNER,
AUTL_NAME,
AUTH_SOURCE,
AUTH_SOURCE_DETAIL,
EFFECTIVE_AUTHORITY,
DATA_READ,
DATA_ADD,
DATA_UPDATE,
DATA_DELETE,
DATA_EXECUTE,
OBJ_OPERATIONAL,
OBJ_MANAGEMENT,
OBJ_EXISTENCE,
OBJ_ALTER,
OBJ_REFERENCE
FROM SECAUDIT.LIB_AUTH_INVENTORY
ORDER BY
TARGET_USER,
OBJECT_LIBRARY,
OBJECT_TYPE,
OBJECT_NAME;4c — IFS Object Authority Summary (by source)
A high-level count of how many IFS objects each authority source controls.
-- ============================================================
-- category: IBM i Services - Security
-- description: Step 4c - IFS authority summary by source
-- minvrm: v7r3m0
-- ============================================================
SELECT
TARGET_USER,
AUTH_SOURCE,
COUNT(*) AS OBJECT_COUNT,
LISTAGG(DISTINCT EFFECTIVE_AUTHORITY, ', ')
WITHIN GROUP (ORDER BY EFFECTIVE_AUTHORITY) AS AUTHORITY_LEVELS
FROM SECAUDIT.IFS_AUTH_INVENTORY
GROUP BY
TARGET_USER,
AUTH_SOURCE
ORDER BY
TARGET_USER,
AUTH_SOURCE;4d — IFS Object Authority Detail
Full detail of every IFS object in the inventory.
-- ============================================================
-- category: IBM i Services - Security
-- description: Step 4d - Full IFS authority detail
-- minvrm: v7r3m0
-- ============================================================
SELECT
TARGET_USER,
IFS_PATH_NAME,
OBJECT_TYPE,
OBJECT_OWNER,
AUTL_NAME,
AUTH_SOURCE,
AUTH_SOURCE_DETAIL,
EFFECTIVE_AUTHORITY,
DATA_READ,
DATA_ADD,
DATA_UPDATE,
DATA_DELETE,
DATA_EXECUTE
FROM SECAUDIT.IFS_AUTH_INVENTORY
ORDER BY
TARGET_USER,
IFS_PATH_NAME;4e — Objects where the user has *EXCLUDE or no authority
A focused query highlighting where the user is denied access — useful for confirming the inventory captured *EXCLUDE entries correctly.
ℹ️
|
-- ============================================================
-- category: IBM i Services - Security
-- description: Step 4e - Denied/excluded objects (both spaces)
-- minvrm: v7r3m0
-- ============================================================
SELECT 'LIBRARY' AS OBJECT_SPACE,
TARGET_USER,
OBJECT_LIBRARY AS LOCATION,
OBJECT_NAME,
OBJECT_TYPE,
EFFECTIVE_AUTHORITY,
AUTH_SOURCE,
AUTH_SOURCE_DETAIL
FROM SECAUDIT.LIB_AUTH_INVENTORY
WHERE EFFECTIVE_AUTHORITY LIKE '%*EXCLUDE%'
OR EFFECTIVE_AUTHORITY LIKE '%no *PUBLIC%'
UNION ALL
SELECT 'IFS',
TARGET_USER,
LEFT(IFS_PATH_NAME, 80),
IFS_PATH_NAME,
OBJECT_TYPE,
EFFECTIVE_AUTHORITY,
AUTH_SOURCE,
AUTH_SOURCE_DETAIL
FROM SECAUDIT.IFS_AUTH_INVENTORY
WHERE EFFECTIVE_AUTHORITY LIKE '%*EXCLUDE%'
OR EFFECTIVE_AUTHORITY LIKE '%no *PUBLIC%'
ORDER BY OBJECT_SPACE, TARGET_USER, LOCATION;Step 5 — Optional: Clean Up Before Re-running
If you need to re-run the inventory for the same user (e.g., after authority changes), delete the existing rows first to avoid primary key constraint violations:
-- ============================================================
-- category: IBM i Services - Security
-- description: Step 5 - Remove prior inventory rows before re-run
-- minvrm: v7r3m0
-- ============================================================
DELETE FROM SECAUDIT.LIB_AUTH_INVENTORY
WHERE TARGET_USER = 'HUGO';
DELETE FROM SECAUDIT.IFS_AUTH_INVENTORY
WHERE TARGET_USER = 'HUGO';Key IBM i Services Used
| Service | Type | Description |
|---|---|---|
QSYS2.OBJECT_STATISTICS() | Table Function | Enumerates all objects in a library with ownership and AUTL info |
QSYS2.OBJECT_PRIVILEGES | View | Object-level authority entries (private + *PUBLIC) for library objects and authorization lists |
QSYS2.IFS_OBJECT_STATISTICS() | Table Function | Enumerates IFS objects under a directory path |
QSYS2.IFS_OBJECT_PRIVILEGES | View | IFS object-level authority entries |
QSYS2.USER_INFO | View | User profile attributes including SPECIAL_AUTHORITIES, GROUP_PROFILE_NAME, SUPPLEMENTAL_GROUP_LIST |
XMLTABLE / tokenize() | XQuery | Splits the supplemental group list string into individual rows — PTF-level independent, works on all V7R3+ |
Authority Source Values in the Output Tables
The AUTH_SOURCE column in both output tables will contain one of these exact values:
AUTH_SOURCE value | Meaning |
|---|---|
Priority 1 - User *ALLOBJ special authority | User profile has *ALLOBJ; all objects are fully accessible |
Priority 2 - User private authority | Explicit private authority entry granted directly to the user |
Priority 3 - User authority via authorization list | User has a private entry in the *AUTL securing this object |
Priority 4 - Group *ALLOBJ special authority | A group the user belongs to has *ALLOBJ |
Priority 5 - Group private authority | A group the user belongs to has a private authority entry on the object |
Priority 6 - Group authority via authorization list | A group the user belongs to has a private entry in the *AUTL securing this object |
Priority 7 - *PUBLIC authority | No specific authority found; effective authority comes from *PUBLIC |
Execution Order Summary
Run the steps in this order against your IBM i system using IBM Access Client Solutions (ACS) Run SQL Scripts:
- Run Step 1 — Create
SECAUDITschema and both output tables (DDL, run once) - Run Step 2 — Library object inventory
INSERT(replaceMYLIB/HUGO) - Run Step 3 — IFS object inventory
INSERT(replace/home/mydir/HUGO) - Run Step 4 — Review results (queries 4a–4e as needed)
- Run Step 5 — Optional cleanup before re-run
Notes and Limitations
- Supplemental groups are stored in
QSYS2.USER_INFO.SUPPLEMENTAL_GROUP_LISTas a space-delimited string.XMLTABLEwith the XQuerytokenize()function splits the list into individual rows — this approach is PTF-level independent and works on all V7R3+ systems. If your list uses a comma delimiter instead of a space, change the" "intokenize($s, " ")to",". - Authorization list detection:
QSYS2.OBJECT_STATISTICSdoes not expose the authorization list name directly. Theobj_listCTE identifies the*AUTLby LEFT JOINingQSYS2.OBJECT_PRIVILEGESfor the row whereUSER_NAME = '*PUBLIC'andOBJECT_AUTHORITY = '*AUTL'— when such a row exists,AUTHORIZATION_LISTholds the authorization list name securing the object. - Group authority tie-breaking (Priorities 5 & 6): When multiple group profiles have authority, the
ROW_NUMBER()window function selects the most permissive group authority (*ALL>*CHANGE>*USE>*EXCLUDE). This mirrors IBM i runtime behavior, which grants access if any group provides sufficient authority. - IFS
SUBTREE_DIRECTORIES => 'YES': This setting causesIFS_OBJECT_STATISTICSto recurse into subdirectories. Set to'NO'if you want a flat (single-level) scan only. - Performance: For large libraries or deep IFS trees, consider adding
WITH URto SELECT portions inside the CTEs where read-isolation is acceptable. Filtering by object type (e.g.,*FILE,*PGM) can significantly reduce runtime. - Re-running: Always run Step 5 (DELETE) before Step 2/3 to avoid primary key constraint violations.
- The SQL scripts must be executed using IBM Access Client Solutions (ACS) – Run SQL Scripts. Running the script from other SQL interfaces or tools may result in unexpected behavior, syntax errors, or incomplete execution. Before running the script, ensure you are connected to the correct IBM i system and that all required substitutions (such as library names and user profiles) have been made throughout the entire script.
References
- IBM Documentation
QSYS2.OBJECT_STATISTICS()Table Function - IBM Documentation
QSYS2.OBJECT_PRIVILEGESView - IBM Documentation
QSYS2.IFS_OBJECT_STATISTICS()Table Function - IBM Documentation
QSYS2.IFS_OBJECT_PRIVILEGESTable Function - IBM Documentation
QSYS2.USER_INFOView - IBM Documentation IBM i Object Authority Concepts
- IBM Documentation Authorization Lists
Document Location
Worldwide
Was this topic helpful?
Document Information
Modified date:
13 July 2026
UID
ibm17279605