Security on IBM i is well designed: it is the operating system itself that controls access to objects, not the application. The trouble is that many installations work around it, and for an understandable reason: a program did not work, somebody gave the user *ALLOBJ, it worked, and nobody ever went back.
Where to start: QSECURITY
DSPSYSVAL SYSVAL(QSECURITY)
The values you meet:
- 20 — anyone who signs on effectively has access to everything. Treat it as "no security".
- 30 — object authority is enforced. This is the reasonable minimum.
- 40 — as 30, plus integrity protection: programs cannot bypass system interfaces. This is the value IBM recommends and the one most healthy installations run on.
- 50 — 40 with additional checks, for environments with particularly strict requirements.
The move from 30 to 40 needs preparation: some old programs use techniques no longer allowed at level 40. The system tells you in advance, though: turn on auditing with at least *AUTFAIL and *PGMFAIL in QAUDLVL, run the applications at level 30 and look for AF entries in the journal. You raise the level after watching that log for a few weeks, not before.
Who holds the keys to everything
This query answers the most important question:
SELECT AUTHORIZATION_NAME, STATUS, SPECIAL_AUTHORITIES
FROM QSYS2.USER_INFO
WHERE SPECIAL_AUTHORITIES LIKE '%*ALLOBJ%'
ORDER BY AUTHORIZATION_NAME;
The list that comes back is almost always longer than expected, and typically contains three groups: service accounts created years ago, users who were given *ALLOBJ to solve a momentary problem, and group profiles that propagate it to all their members. The query sees the authorities written in the profile, not those that come from a group: a user in a group with *ALLOBJ uses it all the same. Group membership is in GROUP_PROFILE_NAME and SUPPLEMENTAL_GROUP_LIST.
*ALLOBJ is not the only special authority that matters: *SECADM allows managing user profiles, *JOBCTL allows acting on other people's jobs, *SPLCTL allows seeing every spooled file — including the payroll.
*PUBLIC: the setting that decides everything
Every object has a public authority, the one that applies to anyone without specific rights. The default comes from the library the object is created in, and on many installations it is *CHANGE: anybody can modify the data.
DSPOBJAUT OBJ(MYLIB/CUSTOMERS) OBJTYPE(*FILE)
The recommended model is the opposite: *PUBLIC *EXCLUDE on data, with access granted not to users directly but to programs.
Adopted authority: the key to the model
This is the mechanism that lets you take rights away from users without breaking the applications. A program compiled like this:
CRTBNDRPG PGM(MYLIB/UPDCUST)
USRPRF(*OWNER)
runs with the rights of the program's owner, not of whoever launches it. If the owner is a profile that can write to the customer file, the program can write even though the user, on their own, could not.
The result is the right one: the user can change the data only by going through the intended programs. If they try to open the same file with a download or a query, they have no rights. That is exactly the distinction *ALLOBJ erases.
Two cautions: the program itself has to be controlled, because whoever can change it can do anything the owner can do; and adopted authority stays active while the program is in the call stack: the programs it calls use it too, except those created with USEADPAUT(*NO). A program owned by a profile with *ALLOBJ that leads to a command line gives *ALLOBJ to whoever reaches it.
Authorization lists, to stay sane
Granting rights object by object becomes unmanageable as soon as you have a few dozen files. An authorization list is a container of permissions that objects are attached to:
CRTAUTL AUTL(PAYROLLDTA) TEXT('Access to personnel data')
GRTOBJAUT OBJ(MYLIB/PAY*) OBJTYPE(*FILE) AUTL(PAYROLLDTA)
From then on permissions are managed in one place, and adding a person does not require remembering every file involved.
A realistic route back
Taking *ALLOBJ away from everyone overnight stops the company. A route that works:
- Turn auditing on and let it gather data for a few weeks. You need to know who really accesses what, rather than guessing.
- Start with a single application, the least critical one. Set
*PUBLIC *EXCLUDEon its files andUSRPRF(*OWNER)on its programs. - Test with a real user who does not have
*ALLOBJ. This is where the unexpected access paths surface: reports, extractions, Excel macros reading the files directly. - Repeat, one application at a time.
- Remove
*ALLOBJonly at the end, and one user at a time.
Step 3 is what reveals the system's real architecture, which almost never matches the one people believe they have.
The check worth repeating every year
SELECT AUTHORIZATION_NAME, STATUS, PREVIOUS_SIGNON,
SPECIAL_AUTHORITIES
FROM QSYS2.USER_INFO
WHERE STATUS = '*ENABLED'
AND (PREVIOUS_SIGNON < CURRENT TIMESTAMP - 6 MONTHS
OR PREVIOUS_SIGNON IS NULL)
ORDER BY PREVIOUS_SIGNON;
Enabled profiles that have not signed on for six months. They are almost always people who no longer work there, or service accounts for retired applications: the most convenient way in that exists, because nobody would notice them being used.
Which versions this works on
The security model — QSECURITY levels, object authority, *PUBLIC, authorization lists, adopted authority with USRPRF(*OWNER) — has been stable for a great many releases and behaves the same on 7.3, 7.4, 7.5 and 7.6. The commands EDTOBJAUT, GRTOBJAUT, RVKOBJAUT, CRTAUTL and DSPUSRPRF are all long-standing.
QSYS2.USER_INFO — the SQL view over user profiles is an IBM i Service, so its availability depends on the release and the database PTF level. It is also extended over time: the multi-factor authentication columns, for example, are recent additions. If a column mentioned here does not exist on your machine, it arrived later.
Before this view existed, the same listing was obtained like this:
DSPUSRPRF USRPRF(*ALL) TYPE(*BASIC)
OUTPUT(*OUTFILE) OUTFILE(QTEMP/PROFILES)
The resulting file is queried in SQL like any table, with column names of its own. It is the method that works on any release, and it stays useful today when you want a snapshot to archive.
Special authorities (*ALLOBJ, *SECADM, *JOBCTL, *SPLCTL) and the QAUDJRN audit journal with the QAUDCTL and QAUDLVL system values have been around a long time; the individual QAUDLVL values have been extended across releases.
Comments
No comments yet. Be the first to comment!
You need an account to comment. Log in · Sign up