, Restreindre le menu ATTN

Dans un précédent poste, nous avons expliqué comment changer les options le menu ATTN , https://www.gaia.fr/menu-attn/

Nous allons voir maintenant comment faire, si vous voulez interdire le menu ATTN ou restreindre l’usage du menu sys request

il faut savoir que c’est un panel de groupe QSYS/QGMNSYSR qui est lancé

La méthode radicale c’est d’interdire ce menu

==>GRTOBJAUT OBJ(QSYS/QGMNSYSR) OBJTYPE(PNLGRP) USER(PUBLIC) AUT(*EXCLUDE)

A ce moment la seul, les utilisateurs *ALLOBJ auront accès à ce menu.

Si vous voulez ajouter des utilisateurs , vous pouvez par exemple ajouter une liste d’autorisations sur le panel de groupe.
il vous suffira alors d’ajouter les utilisateurs dans la liste pour qu’il accède à ce menu, vous pouvez utiliser un groupe

Vous avez une deuxième solution à base de programme d’exit

C’est le point d’exit QIBM_QWT_SYSREQPGMS, vous pourrez ajouter votre programme par ==>WRKREGINF

Ce programme reçoit 2 paramètres et renvoi la valeur 0 dans une paramètre intégrer pour interdire l’accès au menu

Voici

Voici 2 squelettes

1 en CLLE

pgm (&sysreqdsp &sysusrdta)
dcl &sysreqdsp *int
dcl &sysusrdta char(128)
dcl &user 
rtvjoba user(&user) 
/* Votre algo de contrôle */ 
if ...
/* si ko */
do
chgvar &sysreqdsp 0 
enddo
else do
/* si ok */
chgvar &sysreqdsp 1
enddo 
ENDPGM

2 en RPGLE

Dcl-Pi *N;                                          
  p_reqdsp             int ;
  p_usrdta             char(128);   
End-Pi;   
// votre algo  
if ... ;
  SysReqDsp = 0; // KO
else ;
  SysReqDsp = 1; // OK
endif ;
*Inlr = *On;   

Dans les 2 programmes vous devrez implémenter votre algorithme de contrôle.

Conclusion :

A vous de choisir la méthode qui vous convient , la deuxième peut vous permettre d’avoir plus de finesse par exemple un rôle dans un ERP , mais vous devrez développer du code

La première est souvent suffisante dans beaucoup de cas, attention au changement de version ce paramétrage sera perdu pas de développement gestion par ==>EDTAUTL

Il est déconseillé d’utiliser les 2 en même temps

Voila simple et efficace , à vous de jouer

Utilisation de PGP sur L’IBMi

Vous avez une notion de PGP dans la mise en place des droits, je vais essayer de vous expliquer en quoi ca consiste.

PGP veut dire groupe principal privé, à ne pas confondre avec le protocole de cryptage, que vous pouvez utiliser sur votre IBMi dans la partie open source pour crypter et décrypter des fichiers reçus de l’extérieur par exemple , pour info ce protocole est souvent utilisé pour le cryptage des mails.

Vous pouvez ajouter un PGP ou le changer s’il y en a déjà un par la commande CHGPGP par CHGOBJPGP

Exemple :

CHGPGP OBJ(‘/qsys.lib/gdata.lib/testpfxx.file’)
NEWPGP(PLB8)
DTAAUT(RWX) OBJAUT(OBJALTER)
RVKOLDAUT(*NO)

EDTOBJAUT gdata/testpfxx *file

On obtient

Utilisat Groupe sur objet
*PUBLIC *CHANGE
QSECOFR *ALL
PLB8 USER DEF < nouveau droit ici

Si vous sauvegardez cet objet

SAVOBJ OBJ(TESTPFXX)
LIB(GDATA)
DEV(*SAVF)
SAVF(GDATA/TESTPFXX1)

et que vous le restaurez

RSTOBJ OBJ(TESTPFXX)
SAVLIB(GDATA)
DEV(*SAVF)
SAVF(GDATA/TESTPFXX1)
RSTLIB(GAIA)

les droits sont conservés
Conclusion, les droits sont stockés sur l’objet et non pas dans le profil comme les droits privés traditionnels que vous ajouter par GRTOBJAUT par exemple.

EDTOBJAUT gaia/testpfxx *file

Utilisat Groupe sur objet
*PUBLIC *CHANGE
QSECOFR *ALL
PLB8 USER DEF << le droit est toujours la

Vous avez des commandes spécifiques
==>go cmdpgp

par exemple , pour voir les objets par PGP

WRKOBJPGP PGP(PLB8)

Conclusion :


C’est un moyen d’avoir un troisième droit sur un objet en plus du public et du propriétaire inclus dans l’objet.
selon les documentations peu nombreuses , ca améliore les performances
Il faut comprendre comment ca fonctionne, si vous en avez sur vos ibmi , mais ce n’est pas stratégique.


Il est conseillé à chaque déploiement de réappliquer les droits sur les objets, ce qui permet de garder une cohérence globale.

il est conseillé de mettre comme propriétaire votre groupe ce qui simplifiera la gestion le pgp et le groupe seront fusionné sur l’objet créé


rappel, si le propriétaire n’existe pas sur le système ou vous restaurez l’objet il sera attribué à QDFTOWN.

, , Gérer les magasins de datas

Une des nouveautés de la dernière TR est de pouvoir analyser et exporter les analyses de journaux d’audit à partir d’un interface graphique dans navigator for i.

le menu

Vous avez la nouvelle option, gérer les magasins d’audit

vous devez commencer par en créer un

Attention la bibliothèque doit existée

Une fois les données agrégées vous avez une liste de vos magasins

vous avez un menu qui vous permet de voir le détail du contenu du magasin

Vous avez le détail de votre magasin que vous pouvez consulter ou exporter par exemple

le menu action

Conclusion

Ca facilite grandement l’utilisation et la restitution des informations d’audit

, Liste complète des droits sur un objet

Il peut être intéressant de voir les droits qui existent sur un objet, pour comprendre et administrer la sécurité.

Les droits sur un objet sont visibles par la commande DSPOBJAUT, mais également par DSPAUTL si votre objet est protégé par une liste.

Prérequis, vous devez avoir au moins le droit *USE sur la bibliothèque qui contient l’objet.

Cette requête résume l’ensemble de ces droits présents

--
-- Voir les droits sur un objet
-- sur l'objet et sur la liste s'il y en a une
-- indiquez votre objet et votre lib 
--
SELECT '2) LISTE' as nature,
'QSYS' as Library ,
AUTHORIZATION_LIST,
'*AUTL' as TYPE,
AUTHORIZATION_NAME ,
OBJECT_OPERATIONAL,
OBJECT_MANAGEMENT,
OBJECT_EXISTENCE,
OBJECT_ALTER,
OBJECT_REFERENCE,
DATA_READ,
DATA_ADD,
DATA_UPDATE,
DATA_DELETE,
DATA_EXECUTE
FROM QSYS2.AUTHORIZATION_LIST_USER_INFO
WHERE AUTHORIZATION_LIST = (SELECT AUTHORIZATION_LIST
FROM QSYS2.OBJECT_PRIVILEGES
WHERE object_schema = 'VOTRE_BIB'
AND object_name = 'VOTRE_OBJ'
FETCH FIRST ROW ONLY)
UNION
SELECT '1) OBJECT' as NATURE,
OBJECT_SCHEMA as library,
OBJECT_NAME as OBJECT,
OBJECT_TYPE as TYPE,
AUTHORIZATION_NAME,
OBJECT_OPERATIONAL,
OBJECT_MANAGEMENT,
OBJECT_EXISTENCE,
OBJECT_ALTER,
OBJECT_REFERENCE,
DATA_READ,
DATA_ADD,
DATA_UPDATE,
DATA_DELETE,
DATA_EXECUTE
FROM QSYS2.OBJECT_PRIVILEGES
WHERE object_schema = 'VOTRE_BIB'
AND object_name = 'VOTRE_OBJ'
ORDER BY 1;

Rappel :

Ces droits ne sont vérifiés que si votre profil et votre profil de groupe ne sont pas *ALLOBJ

Les droits qui sont systématiquement présents sur les objets, sont les droits *PUBLIC et le propriétaire

, Connaitre le droit d’un profil sur un objet

Vous voulez savoir quel est le droit d’un utilisateur sur un objet, et comprendre comment il a obtenu ce droit. Voici une commande qui va vous l’afficher.

On ne traitera ici que le mécanisme historique de l’IBMi, pas les droits complétifs obtenus par les groupes additionnels, on considère également que vous avez droit sur la bibliothèque qui contient l’objet.

Rappel le schéma de recherche d’obtention des droits

Le principe est : au premier trouvé il s’arrête !

Notre outil s’appelle DSPUSRAUT2, il existait déjà sur Git une version sans écran DSPUSRAUT

La commande

Le résultat

Dans notre exemple le droit est *ALL et il est obtenu grâce au profil de groupe mentionné dans la liste d’autorisation.

Les sources de l’outil DSPUSRAUT2 se trouvent ici :

https://github.com/Plberthoin/PLB/tree/master/GTOOLS/

Vous avez 4 sources à compiler dans cet ordre, un DSPF, un PNLGRP, un CLLE (en adoption de droit par rapport à un profil qui a *ALLOBJ) et un CMD.

Voila, simple et efficace.

Ça peut vous permettre de comprendre rapidement des accès ou des refus et maintenant grâce aux services SQL, vous pouvez administrer une grande partie des autorisations.

Vous pouvez aussi utiliser les collectes de droits pour retrouver des informations intéressantes qui sont plus complètes mais plus compliquées à utiliser …

Conseil :

Si vous voulez mettre en place une politique de sécurité intéressante vous devez viser le niveau 5 ou 6

Comment faire afficher un écran à un traitement batch ?

Les traitements 5250 sont faits pour tourner en interactif, mais pour différentes raisons vous pouvez vouloir les faire tourner en batch :

Pas de login
sécurisation pas de attn request
etc …

Voici un exemple, dans une société ou j’ai travaillé, les unités de productions pouvaient demander un mot de passe à l’astreinte, par exemple la nuit.

La solution la plus simple qu’on avait trouvée était de lui afficher un programme de changement sur son unité écran.

On lui demandait donc son profil utilisateur et son unité écran et on lançait le programme sur celle ci, il pouvait changer son mot de passe directement.

C’est cet exemple que j’ai simplifié qui est ci dessous

le DSPF source

                                                                 
     A                                      DSPSIZ(24 80 *DS3)             
     A                                      CA03(03)                       
     A                                      INDARA                         
     A          R FMT01                                                    
     A*%%TS  SD  20240527  074541  PLB         REL-V7R4M0  5770-WDS        
     A                                  4 20'Réinitialiser un mot de passe'
     A                                  7  2'Utilisateur         :'        
     A                                  8  2'Nouveau mot de passe  :'        
     A                                 22  1'F3=Exit'                      
     A            USER          10A  O  7 26                               
     A            PWD           32A  B  8 26CHECK(LC)                      
     A            DEV           10A  O  4 54                               
     A            TEXTE         30   O 14  3                               

Le CLP source

pgm  (&dev &user)                                                
/*----------------------------------------------------------*/   
/* Ce programme permet de faire afficher un écran en batch  */   
/* vous devez acquérir l'unité écran                         */   
/* pour réinitialiser un mot de passe                        */   
/* sbmjob cmd(call initpwdr (&dev &user) job(QPADEV0001)    */   
/*----------------------------------------------------------*/   
dcl &dev  *char 10                                               
dcl &user *char 10                                               
/* Contrôles existence                      */                   
             CHKOBJ     OBJ(&DEV) OBJTYPE(*DEVD)                 
             MONMSG     MSGID(CPF9801) EXEC(DO)                  
             SNDPGMMSG  MSGID(CPF9898) MSGF(QCPFMSG) +           
                          MSGDTA('L''unité écran doit exister') +
                          MSGTYPE(*ESCAPE)                       
             enddo 
            ALCOBJ     OBJ((&DEV *DEVD *EXCLRD)) WAIT(0)       
            monmsg CPF1002  exec(do)                           
            SNDPGMMSG  MSGID(CPF9898) MSGF(QCPFMSG) +          
                         MSGDTA('Impossible d''allouer l''unité +
                         écran doit exister') MSGTYPE(*ESCAPE) 
            enddo                                                                                            
             CHKOBJ     OBJ(&user) OBJTYPE(*usrprf)              
             MONMSG     MSGID(CPF9801) EXEC(DO)                  
             SNDPGMMSG  MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Le +
                          profil utilisateur doit exister') +         
                          MSGTYPE(*ESCAPE)                            
             enddo                                                    
 /* Lancement du programme sur l'écran remote  */                      
             SBMJOB     CMD(CALL PGM(INITPWDR) PARM((&DEV) (&USER))) +
                          JOB(&DEV) JOBQ(QSYSNOMAX)  
             SNDPGMMSG  MSGID(CPF9898) MSGF(QCPFMSG) +          
                          MSGDTA('Travail, ' *bcat &dev *bcat + 
                          'démarré') MSGTYPE(*comp)                              
endpgm                                                                

Le CLP cible

pgm  (&dev &user)                                                
/*----------------------------------------------------------*/   
/* Ce programme réinitiliase  un mot  de passe              */   
/* Peut être envoyé sur un écran remote qui est sur la      */   
/* Mire                                                     */   
/*----------------------------------------------------------*/   
dcl &dev *char 10                                                
dclf initpwdr                                                    
monmsg cpf0000 exec(goto erreur)                                 
/* controles fait dans le programme appelant */                  
             OVRDSPF    FILE(INITPWDR) DEV(&DEV) OVRSCOPE(*JOB)  
          chgvar &pwd     'ici mot de passe'                     
             dountil &in03                                       
             SNDRCVF    RCDFMT(FMT01)                            
             if cond(*not &in03) then(do)                        
             if (&pwd *ne 'ici mot de passe') then(do)           
             CHGUSRPRF  USRPRF(&USER) PASSWORD(&PWD) PWDEXP(*YES)
             Chgvar &texte ('Mot de passe réinitialisé')         
             enddo                                               
             enddo                                                   
             enddo                                                   
/* fin traitement */                                                 
             DLTOVR     FILE(INITPWD) LVL(*JOB)                      
             MONMSG     MSGID(CPF0000)                               
return                                                               
erreur:                                                              
             SNDUSRMSG  MSG('Réinitialisation de mot de passe pour' +
                          *BCAT &USER *BCAT ', actuellement +        
                          impossible') MSGTYPE(*INFO)                
             MONMSG     MSGID(CPF0000)                               
endpgm                                                               

La seule spécificité est de choisir l’unité écran d’affichage, pour qu’elle soit éligible elle doit être à la mire de connexion.

La commande pour habiller

             CMD        PROMPT('Réinitialisation de PWD')           
             PARM       KWD(UNITE) TYPE(*NAME) LEN(10) MIN(1) +     
                          PROMPT('Unité écran')                     
             PARM       KWD(PROFIL) TYPE(*NAME) LEN(10) MIN(1) +    
                          PROMPT('Profil utilisateur')              

le lancement job source:

La saisie sur le job cible :

Sur un changement de mot de passe, il peut être important d’avoir un suivi ?

Bien sur, vous pouvez ajouter des contrôles …

Le job cible qui tourne en batch !

Donc pas de possibilité d’ATTN Request , et messages d’erreurs dans QSYSOPR

Remarques :

Vous pouvez choisir l’utilisateur de lancement, mais QSECOFR est interdit dans un SBMJOB
Simple mais efficace, mais difficilement généralisable, on doit avoir un OVRDBF par DSPF

Intéressant pour des demandes ponctuelles

Dans les CLP vous pouvez indiquer directement l’unité sur la commande SNDRCVF

, , Gestion du suivi des tâches soumises

Une petite amélioration sur le clear avec la TR4

Je vous rappelle le principe de cette fonction qui existe depuis la TR1

C’est un job à démarrage automatique qui tourne dans QUSRWRK qui va superviser

QSYSWRK QSYS SBS 0,0 DEQW
QMRDBJNFY QSECOFR ASJ 0,0 PGM-QMRDBJNFY DEQW

Pour le lancer

QSYS/CALL QSYS/QMRDBJNFY PARM(0)

Ajouter une jobq à surveiller

CALL QSYS2.ADD_TRACKED_JOB_QUEUE(IASP_NAME => ‘*SYSBAS’,
JOB_QUEUE_LIBRARY => ‘majobq’,
JOB_QUEUE => ‘malib’);

Supprimer une jobq à surveiller

CALL QSYS2.REMOVE_TRAcked_job_QUEUE(IASP_NAME => ‘*SYSBAS’,
JOB_QUEUE_LIBRARY => ‘majobq’,
JOB_QUEUE => ‘malib’)


pour voir les jobq contrôlées

SELECT * FROM QSYS2.TRACKED_JOB_QUEUES

c’est le fichier QSYS/QAMRDJQL il peut être copié d’une machine à une autre !

Soumission d’un travail dans la file

SBMJOB CMD(DSPLIB LIB(QGPL)) JOB(DSPQGPL) JOBQ(GG/GGTEST)

voir le résultat

SELECT * FROM TABLE(QSYS2.TRACKED_JOB_INFO(JOB_QUEUE_LIBRARY_FILTER => ‘GG’,
JOB_QUEUE_FILTER => ‘GGTEST’))
ORDER BY INTERNAL_JOB_IDENTIFIER, ROUTING_STEP;

sortie

NODE_NAME QUALI00001 JOB_NAME JOB_USER JOB_NUMBER COMMA00001
NEPTUNE 740023/PLB/DSPQGPL DSPQGPL PLB 740023 DSPLIB LIB(QGPL)

pour clearer les logs
CALL QSYS2.CLEAR_TRACKED_JOB_INFO(IASP_NAME => ‘*SYSBAS’);

Vous pouvez avoir plus d’informations dans le fichier

Avec la TR4 vous avez des filtres supplémentaires par exemple jobq et bibliothèque

Pour clearer une jobq spécifique !

CALL QSYS2.CLEAR_TRACKED_JOB_INFO(IASP_NAME => ‘*SYSBAS’,
JOB_QUEUE_LIBRARY_FILTER => ‘GG’,
JOB_QUEUE_FILTER => ‘GGTEST’);

des liens à connaitre

https://www.ibm.com/docs/en/i/7.4?topic=environment-managing-submitted-job-tracker

https://www.ibm.com/support/pages/submitted-job-tracker-job-qmrdbjnfy

Remarque :

il definit des programmes d’exit que vous pouvez utiliser
Change Job (QIBM_QWT_CHGJOB)
Job Notification (QIBM_QWT_JOBNOTIFY)
Submit Job (QIBM_QWT_SBMJOB)

Rien dans Navigator for i Mais gros liens avec DB2MIRROR et son interface !

, , Manager les informations d’audit avec la TR4

Vous pouvez demander un tas d’informations d’audit pour tracer les violations de sécurité par exemple

Vous devez avoir le droit *AUDIT sur votre profil pour la mettre en place, c’est valeurs système qui permettent de le paramétrer les informations souhaitées

QAUDCTL, QAUDLVL, QAUDLVL2

Pour chaque information demandée, vous allez avoir un poste qui est créé dans le journal d’audit QAUDJRN.

Pour consolider ces informations, vous devez les copiez dans des fichiers il existait jusqu’à présent 2 méthodes

1) Les fichiers modèles utilisables dans des commandes IBMi

ils sont dans QSYS et commencent par QASY

DSPJRN QAUDJRN OUTPUT(*OUTFILE)
OUTFILE(MABIB/QASYPWJ5)
JRNCODE(‘T’) ENTTYP(‘PW’)

exemple pour les types PW, c’est le fichier QASYPWJ5 que vous devez dupliquer dans votre bibliothèque
DSPJRN JRN(QAUDJRN) ENTTYP(‘PW’)
OUTPUT(OUTFILE) OUTFILFMT(TYPE5) OUTFILE(MABIB/WASYPWJ5)

La stratégie est la suivante , la première fois vous demandez la création du fichier de sortie par un crtdupobj
et après vous ajoutez à ce fichier tous les soirs à 23 h 59 les postes PW

2) Les Technology Refresh nous apportent régulièrement des services

Ces services permettent de lire directement ces informations par SQL.
c’est les fonctions tables qui se trouve dans SYSTOOLS et qui s’écrivent SYSTOOLS.AUDIT_JOURNAL_XX()
XX étant le type
exemple pour les types PW
SYSTOOLS.AUDIT_JOURNAL_PW()

voici un exemple

select A.VIOLATION_TYPE_DETAIL, A.AUDIT_USER_NAME , A.REMOTE_ADDRESS, A.ENTRY_TIMESTAMP
from table (SYSTOOLS.AUDIT_JOURNAL_PW(STARTING_TIMESTAMP => current timestamp – 1 days)) A
order by A.ENTRY_TIMESTAMP desc

La stratégie est la suivante , la première fois vous demandez la création du fichier de sortie par un create table as()
et après vous ajoutez à ce fichier tous les soirs à 23 h 59 les postes PW par un insert

3) Avec la TR (4 pour V7R5 et 10 pour V7R4)

elle vous apporte une solution intégrée pour créer votre DATAMART
https://www.ibm.com/support/pages/ibm-i-75-tr4-enhancements
Vous avez 2 services

QSYS2.MANAGE_AUDIT_JOURNAL_DATA_MART procedure
QSYS2.AUDIT_JOURNAL_DATA_MART_INFO view

https://www.ibm.com/support/pages/node/7148888

ces 2 services vont faire ce que vous faisiez par SQL ou commande ibmi 2

Création du datamart le fichier résultat s’appelera AUDIT_JOURNAL_XX dans la bibliothèque que vous aurez choisi

Création de la table

CALL QSYS2.MANAGE_AUDIT_JOURNAL_DATA_MART(JOURNAL_ENTRY_TYPE => ‘PW’,
DATA_MART_LIBRARY => ‘MALIB’,
STARTING_TIMESTAMP => CURRENT DATE – 1 MONTH,
ENDING_TIMESTAMP => CURRENT TIMESTAMP);

Alimentation quotidienne de la table

CALL QSYS2.MANAGE_AUDIT_JOURNAL_DATA_MART(JOURNAL_ENTRY_TYPE => ‘PW’,
DATA_MART_LIBRARY => ‘MALIB’,
STARTING_TIMESTAMP => ‘*CONTINUE’,
ENDING_TIMESTAMP => CURRENT TIMESTAMP,
DATA_MART_ACTION => ‘ADD’
);

Vous avez une vue qui vous permet de suivre vos mises à jour de datamart

SELECT DATA_MART_LIBRARY, DATA_MART_TABLE, JOURNAL_ENTRY_TYPE, BUILD_END, FAILURE_DETAIL
FROM QSYS2.AUDIT_JOURNAL_DATA_MART_INFO
WHERE JOURNAL_ENTRY_TYPE = ‘PW’ AND DATA_MART_LIBRARY = ‘MALIB’ ;

Vous pourrez également manager par Navigator for i

Remarque :

Bien sur vous avez toujours aussi un onglet dans Navigator for i qui vous permet de voir sous forme de graphique les résultats , mais attention uniquement sur les postes en cours .
Si vous avez déjà une solution, c’est compliqué de revenir dessus, mais si vous n’avez rien ca vous simplifier considérablement les taches.
Attention dans tous les cas c’est à vous d’épurer les récepteurs quand vous les avez traité

, , , Convertir un SAVF en PF

il faut savoir qu’un fichier SAVF est un fichier PF de 528 de long.

Vous pouvez avoir besoin pour différentes raisons de convertir SAVF en PF pour manipuler plus simplement par SQL, pour contourner des restrictions d’utilisations etc ..

Vous trouverez ici 2 commandes qui vont vous permettent de réaliser cette opération : https://github.com/Plberthoin/PLB/tree/master/CPYSAVF

Copier un SAVF dans un PF

Voir le PF

Copier un PF dans un SAVF

Voir le Résultat

Pour voir ce résultat taper la commande DSPSAVF , Voir WRKSAVF si vous avez installez notre outil

Remarque :

Outil simple mais efficace qui peut rendre des services à des administrateurs

, , Tracer l’usage d’une commande

Vous voulez savoir si une commande est utilisée, il y a plusieurs solutions en voici une basée sur les
programme d’exit qui est assez simple

Il existe un programme d’exit QIBM_QCA_CHG_COMMAND

Pour ajouter votre programme vous avez une commande ADDEXITPGM

ADDEXITPGM EXITPNT(QIBM_QCA_CHG_COMMAND)   +
           FORMAT(CHGC0100)                +
           PGMNBR(1)                       +
           PGM(VOTREBIB/HSTCMD)           +
           TEXT('Tracer une commande') +
           PGMDTA('RSTLIB    QSYS')

Vous devrez lui indiquer dans la paramètre PGMDTA la commande qualifiée à tracer
exemple :
‘STRDBG QSYS’

Les données reçues sont sur le format CHGC0100 qui vous donne le découpage du buffer reçu par votre programme

Vous pouvez faire un programme générique qui va loguer l’utilisation d’une commande, vous pouvez en mettre plusieurs et la prise en compte est immédiate

Voici le source en clle du programme HSTCMD

 PGM    PARM(&ExitInfo  &NewString   &Newlength)                 
       DCL  &Class       *CHAR   10                                                                                 
       DCL  &OffsetDec   *DEC  (7 0)
       DCL  &CmdLenDec   *DEC  (7 0)
       DCL  &ExitInfo    *CHAR 2000   /* CHGC0100 interface data      */
/* Input parameters                                                   */
       DCL  &ExitPoint   *CHAR   20   /* Exit Point name              */ 
       DCL  &ExitFormat  *CHAR    8   /* Exit Point Format            */ 
       DCL  &CmdName     *CHAR   10   /* Command name being executed  */ 
       DCL  &CmdLib      *CHAR   10   /* Command Library              */ 
       DCL  &Change      *CHAR    1   /* Change allowed? 1=yes 0=no   */ 
       DCL  &Prompt      *CHAR    1   /* Prompt requested? 1=yes 0=no */ 
       DCL  &Filler      *CHAR    2   /* Reserved by IBM              */ 
       DCL  &Offset      *CHAR    4   /* Offset to command string     */ 
       DCL  &CmdLength   *CHAR    4   /* Command string length        */ 
       DCL  &CmdString   *CHAR 2000   /* Command String               */          
/* Output Parameters                                                  */
       DCL  &NewString   *CHAR 2000   /* Replace with this command    */
       DCL  &NewLength   *CHAR    4   /* Length of new command        */
                                      /* 0 = no new command           */ 
DCL &JOB *CHAR 10
DCL &USR *CHAR 10
DCL &NBR *CHAR  6
       MONMSG   CPF0000    EXEC(GOTO ERROR)
/* découpage du paramètre reçu                                   */
       CHGVAR  &ExitPoint  %SST(&ExitInfo   1  20)             
       CHGVAR  &ExitFormat %SST(&ExitInfo  21   8)              
       CHGVAR  &CmdName    %SST(&ExitInfo  29  10)             
       CHGVAR  &CmdLib     %SST(&ExitInfo  39  10)              
       CHGVAR  &Change     %SST(&ExitInfo  49   1)              
       CHGVAR  &Prompt     %SST(&ExitInfo  50   1)              
       CHGVAR  &Filler     %SST(&ExitInfo  51   2)              
       CHGVAR  &Offset     %SST(&ExitInfo  53   4)              
       CHGVAR  &CmdLength  %SST(&ExitInfo  57   4)               
       CHGVAR  &CmdLenDec  %BIN(&Cmdlength)                   
       CHGVAR  &OffsetDec  (%BIN(&Offset) + 1)          /* Set offset */
       CHGVAR  &CmdString  %SST(&ExitInfo &OffsetDec &CmdLenDec)
/* Extraction du travail */
                    RTVJOBA    JOB(&JOB) USER(&USR) NBR(&NBR)          
/* envoi message à qsysopr */ 
             SNDUSRMSG  MSG(&job *tcat '/' *tcat &usr *tcat +   
                          '/' *tcat &nbr *bcat %sst(&CmdString 1 + 
                          100) ) MSGTYPE(*INFO) TOUSR(*SYSOPR)
/* passage de la commande sans transformation */
chgvar &NewString &CmdString
chgvar &NewLength &CmdLength 
ERROR:
return
ENDPGM 

Remarque :

Vous n’avez pas besoin de mettre en place des audits et tout est dynamique

Vous pouvez transformer une commande ou la remplacer par une autre

Pour voir les commandes que vous tracez

==> WRKREGINF QIBM_QCA_CHG_COMMAND

Exemple :


Les commandes qui commencent par DLT, je remplace par un message suppression refusée pour certain utilisateurs

Rappel :

Un programme d’exit doit être simple et ne pas planter !