Object security on IBM i

Log in to save

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 — violations are recorded in the audit journal before you even raise the level, if auditing is on. 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.

*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 does not automatically propagate to called programs unless you ask for it with USEADPAUT(*YES).

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:

  1. Turn auditing on and let it gather data for a few weeks. You need to know who really accesses what, rather than guessing.
  2. Start with a single application, the least critical one. Set *PUBLIC *EXCLUDE on its files and USRPRF(*OWNER) on its programs.
  3. 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.
  4. Repeat, one application at a time.
  5. Remove *ALLOBJ only 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 DATE - 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 modelQSECURITY 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, DSPUSRPRF and CHGDLTPRF 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 exactly like the view. 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.

Sources

← Back to blog

Comments

No comments yet. Be the first to comment!

You need an account to comment. Log in · Sign up