, , , Les traitements asynchrones sur IBMi


Une définition simple, ce sont des traitements qui se déclenchent pour traiter des entrées d’une pile et qui ne renvoient pas de résultats directs au proccess émetteur

Il existe des produits spécifiques pour faire ça, sur l’IBMi le plus connu est bien sur mqseries .
Mais il est maintenant possible d’installer des produits open source comme RabbitMQ , etc…

Il existe également des solutions natives de la plateforme.

Parmi ces solutions il y a 2 méthodes

  • Cyclique ( toutes les 30 secondes)
  • A l’événement qui ne se déclencheront qu’en cas de nécessité (exemple triggers)

On ne présentera ici que les secondes.

Les triggers

Ce sont des programmes qu’on va enregistrer au niveau de la base de données, ils vont se déclencher sur un update, insert ou delete avant ou après l’action.

On peut les déclarer par commande ADDPFTRG ou par l’instruction SQL CREATE TRIGGER, on peut être plus précis sur l’exécution en SQL (Niveau zone modifiée par exemple)

Les DTAQs

Ce sont des files d’attentes que l’on crée par CRTDTAQ , on peut écrire dedans par API (QSNDDTAQ, QRCVDTAQ) ou par SQL QSYS2.SEND_DATA_QUEUE() et QSYS2.RECEIVE_DATA_QUEUE()

Pour la réception, on peut indiquer un temps négatif souvent -1, et le traitement se déclenchera quand il y aura un entrée dans la file !

soit dans le programme de traitement
CALL PGM(QRCVDTAQ) PARM(&DTAQNOM &DTAQBIB &DTAQLEN
&DATA &WAIT)
/* &wait = -1 */

Les msgqs en wait

historiquement, souvent utilisé, par exemple pour superviser la msgq qsysopr

dans le programme de traitement qui boucle sur cette instruction
RCVMSG … WAIT(*MAX)

Les fichiers à fin retardée

Le principe est le suivant, votre programme attendra un enregistrement quand il aura fini de lire les enregistrements trouvés

Avant le programme RPGLE
OVRDBF FILE(VOTREFIC) EOFDLY(99999)

dans le programme RPGLE

dou %eof() ;
….
read VOTREFIC ;

endif ;

Les watchers


Permettent d’analyser en temps réels des messages qui arrive dans les joblog, les historiques de log voir une autre file de message (MSGQ) .
Pour démarrer un watcher, on utilise la commande STRWCH
STRWCH SSNID(ANAWCH) WCHPGM(votre bib/votre programme) +
CALLWCHPGM(WCHEVT) WCHMSG((ALL))
WCHMSGQ((Votre bib/votre msgq))

votre programme reçoit 4 paramètres
L’option, la session, l’erreur et la donnée du message

exemple

/* Paramètres reçus */

DCL VAR(&WCHOPTION) TYPE(CHAR) LEN(10)

DCL VAR(&SESSIONID) TYPE(CHAR) LEN(10)
DCL VAR(&ERROR) TYPE(CHAR) LEN(10)

DCL VAR(&EVTDATA) TYPE(CHAR) LEN(1024)

Les programmes d’exits

C’est des actions système enregistrées que vous pouvez voir par la commande WRKREGINF, et seules les actions définies dans cette liste sont utilisables.

Pour ajouter un programme c’est soit la commande addexitpgm ou l’option 8 dans wrkreginf.

Le principe , on reçoit un buffer avec les données en cours et on renvoie status pour dire ok ou ko, vous pouvez dire OK systématiquement et traiter ou faire un contrôle d’autorisation applicatif

Exemple sur FTP

PGM PARM (& APPID & OPID & USRPRF & REMOTEIP & REMOTELEN & OPINFO & OPLEN & OK)
DCL & APPID * CHAR 4 /* ID D’APPLICATION, NUM BINAIRE */
DCL & OPID * CHAR 4 /* ID D’OPERATION, NUMERO BINAIRE */
DCL & OPNUM * 4 /* OPERATION ID, UTILISABLE DANS CL */
DCL & USRPRF * CHAR 10 /* PROFIL UTILISATEUR UTILISANT FTP */
DCL & REMOTEIP * CHAR 251 /* ADRESSE IP */
DCL & REMOTELEN * CHAR 4 /* LONGUEUR DU PARAMETRE PRECEDENT */
DCL & OPINFO * CHAR 251 /* INFORMATIONS SPECIFIQUES OP */
DCL & OPLEN * CHAR 4 /* LONGUEUR DU PARAMETRE PRECEDENT */
DCL & OK * CHAR 4 /* SIGNAL DE CONFIRMATION / / seulement utilisateur FTPUSR */
if cond(&USRPRF *ne ‘FTPUSR’) then(do)
chgvar &ok (X’00000001′)
enddo
ENDPGM

pour l’ajouter

ADDEXITPGM EXITPNT(QIBM_QTMF_SVR_LOGON)
FORMAT(TCPL0100) PGMNBR(1) PGM(VOTRELIB/VOTREPGM)

Vous devez arrêter le service FTP pour que cela soit pris en compte
ENDTCPSVR *FTP puis STRTCPSVR

Conclusions

Vous avez plusieurs solutions dans certains cas , et certaines sont plus à jour

les 4 à utiliser aujourd’hui sont
Les triggers pour la base de données, si possible en SQL
Les watchers pour les événements de log systèmes
Les progammes d’exit pour les actions Système, par exemple pour les connexions ODBC
Les dtaq pour gérer des piles de données applicatives

Tous ces programmes sont appelés souvent, ils doivent être donc optimisés et ils ne doivent pas planter pour éviter de bloquer la file !

, 5 petites astuces pour améliorer votre base de données

1) Vous désirez mettre des noms longs .

Vous avez un fichier pf, et pour les gens qui font des requetes dessus vous voulez mettre des noms plus signicatif

exemple remplacer num234 par numero_de_client

Vous ne voulez pas ou vous pas migrer vers une base en SQL , voila comment faire

Cette opération ne peut pas être faite en SQL
En effet ALTER TABLE FICHIER1 ALTER COLUMN ne permet pas de changer le nom de la colonne

C’est le mot clé Alias qui permet ca

Fichier avant

A R FICHIER1F
A*
A NUMCLI 5 0 COLHDG(‘Numéro’ ‘Client’)
A NOMCLI 30 COLHDG(‘Nom ‘ ‘Client’)
A PRECLI 30 COLHDG(‘Prénom’ ‘Client’)

Vous pouvez mettre des noms longs

fichier après, on ajoute les alias

A R FICHIER1F
A*
A NUMCLI 5 0 COLHDG(‘Numéro’ ‘Client’)
A ALIAS(NUMERO_CLIENT)
A NOMCLI 30 COLHDG(‘Nom ‘ ‘Client’)
A ALIAS(NOM_CLIENT)
A PRECLI 30 COLHDG(‘Prénom’ ‘Client’)
A ALIAS(PRENOM_CLIENT)

Pour ne pas perdre vos données vous pouvez faire un change pf

CHGPF FILE(GDATA/FICHIER1) SRCFILE(GDATA/QDDSSRC) SRCMBR(FICHIER1)

Cette opération ne change pas le niveau de format , pas de recompile de votre application

vous devrez avoir le source sur votre machine de prod pour faire un CHGPF

Si vous n’avez pas le source mais que vous voulez préparer les données pour de la BI par exemple
vous pouvez faire des vues qui seront utilisées à la place de vos PF !

Exemple

CREATE VIEW fichier_client AS
SELECT nomcli as nom_client,
numcli as numero_client,
precli as prenom_client
FROM fichier1

2) Vous voulez ajouter une zone à notre pf

L’opération peut se faire cette fois directement par SQL, même sur un PF

Exemple, vous voulez ajouter une zone mail à votre fichier

ALTER TABLE FICHIER1 ADD COLUMN MAIL_CLIENT FOR COLUMN MAIL
CHARACTER ( 50) CCSID 1147 NOT NULL WITH DEFAULT

Vous ne perdez pas les données, ni les fichiers qui pointent dessus
Mais attention comme en DDS vous changer le niveau de format donc vos programmes doivent être recompilés ou vous devez indiquer lvlchk(*no) sur vos fichiers (analyse à faire)
Vous restez en format DDS, vous ne pourrez pas ajouter tous les types de données
Attention il faudra reporter la zone dans votre DDS pour être cohérent

3) Contrôlez les données de vos fichiers

Si vous avez des fichiers PF, vous pouvez avoir des données erronées, vous pouvez maintenant simplement contrôler la validité de vos données par une fonction table, systools.validate_data !

select *
from table (
systools.validate_data(
library_name => ‘votrebib’, file_name => ‘FICHIER1’,
member_name => ‘*LAST’) )

Ça vous permettra d’avoir la liste des enregistrements qui ont des erreurs de données, ça peut être intéressant de le faire de temps en temps sur les données sensibles de votre base.

4) Supprimer définitivement les enregistrements effacés

Quand vous supprimez vos données elles ne sont pas réellement supprimés elles sont juste flaguées
Pour les supprimer vous devez faire un RGZPFM de votre table qui supprimera réellement les enregistrements et qui reconstruira les indexes .
Commencer par le faire sur les tables qui ont le plus d’enregistrements supprimés

5) Contrôler qu’il ne vous manque pas d’index

Un des principaux axe pour améliorer les performances de votre base de données est souvent d’ajouter des index manquants.

Pour connaitre les index à analyser, vous avez une table qui s’appelle QSYS2.SYSIXADV qui vous propose des suggestions d’index

Vous pouvez ajouter les index qui sont souvent et régulièrement demandés.

Vous pouvez également voir ces suggestions sur ACS.

Comment faire un ping en boucle sur votre IBMi ?

Sans être un expert réseau on a parfois besoin de surveiller périodiquement des accès à notre partition
(suite à des migrations, des pb réseaux etc …)

Ce poste vous explique comment suivre ces problèmes.

1) Créer un fichier de log

CREATE TABLE VOTREBIB.PINGLOG (
PRESULT CHAR(10) CCSID 1147 NOT NULL DEFAULT  » ,
ADRESIP CHAR(20) CCSID 1147 NOT NULL DEFAULT  » ,
PDATE DATE NOT NULL DEFAULT CURRENT_DATE ,
PHEURE TIME NOT NULL DEFAULT CURRENT_TIME )

2) Créer un programme qui écrit dans ce fichier

/* +
Ping en boucle et capture le résultat dans le fichier LOG

p_IP : IP sur laquelle effectuer le ping
p_delai : délai en seconde entre chaque ping

*/

PGM PARM( &P_IP &P_DELAI)

/* Paramètres / DCL VAR(&P_IP) TYPE(CHAR) LEN(15)
DCL VAR(&P_DELAI) TYPE(*DEC) LEN(5)

/* Variables / DCL VAR(&L_SQL) TYPE(CHAR) LEN(1300)
DCL VAR(&L_ERR) TYPE(LGL) / Cote */
DCL &L_COTE *CHAR 1 VALUE( » »)

/* Corps */

LOOP: /* Boucle principale */

/* Ping /

CHGVAR &L_ERR VALUE(‘0’)

PING RMTSYS(&P_IP) MSGMODE(QUIET ESCAPE)

MONMSG MSGID(TCP0000)

EXEC(DO)

CHGVAR &L_ERR VALUE(‘1’)

ENDDO /* Log* /

IF COND( &L_ERR = ‘0’ ) THEN(DO)

        
   /* values( 'PING', 'OK', '8.8.8.8' )                 */         
          CHGVAR     VAR(&L_SQL) VALUE('insert into pinglog +      
                       values( ''OK'', ''' *TCAT &P_IP *TCAT ''' + 
                       , current date, current time   )')          
ENDDO                                                              
ELSE       CMD(DO)                                                 
          CHGVAR     VAR(&L_SQL) VALUE('insert into pinglog +      
                       values( ''KO'', ''' *TCAT &P_IP *TCAT ''' + 
                       , current date, current time   )')          
ENDDO                                                              
/* Logger le binz */                                               
RUNSQL     SQL(&L_SQL) COMMIT(*NONE)                               

/* Continuer */                                            
 IF         COND( &P_DELAI > 0 ) THEN(DLYJOB &P_DELAI)       
DLYJOB &P_DELAI        
GOTO       LOOP                                             ENDLOOP:       

ENDPGM

ce programme va loguer toutes les n secondes

3) Il est conseiller d’associer une commande


CMD PROMPT(‘trace ping’)
PARM KWD(IPADR) TYPE(CHAR) LEN(50) + PROMPT(‘Adresse ip’)

PARM KWD(DELAY) TYPE(DEC) LEN(5) DFT(15) MIN(0) +
PROMPT(‘Delai en secondes’)

Conseils :


Entre 15 et 30 secondes semble être le bon compromis !
Si vous voulez savoir ou est le problème vous devez tester les éléments discriminants,
d’abord sur votre réseau local, ensuite sur le wan, et puis le lan distant, par exemple.


Attention certain équipements ne répondent au trames ICMP

, 5 astuces pour utiliser SMTP sur l’IBMi

1) Utilisez l’annuaire SMTP

Il faut arrêter d’utiliser la directory SNA, l’objectif est se passer complètement de SNA
c’est le paramètre DIRTYPE, exemple CHGSMTPA DIRTYPE(*SMTP)
Il vous faudra inscrire les utilisateurs à SMTP , addsmtpusr ou wrksmtpusr pour qu’ils puissent envoyer des mails

Sinon vous recevrez un message TCP5090 comme celui ci !

2) Utilisez un user mail en NOREPLY

Créer un utilisateur NOREPLY sans mot de passe
inscrivez le à la directory SMTP
wrksmtpusr ou addsmtpusr

et ensuite envoyer vos mails en les soumettant avec cet utilisateur

exemple :

SBMJOB CMD(SNDSMTPEMM RCP((‘xxx@gaia.fr’)) SUBJECT(‘votre sujet’) NOTE(‘ici texte’)) JOB(MAIL)
USER(NOREPLY)

3) Utiliser du HTML dans le corps du message

paramètre CONTENT(*HTML)

dans la commande SNDSMTPEMM … CONTENT(*HTML)

Vous pouvez alors utiliser des balises HTML dans votre message
Un très bon site ici !
https://openclassrooms.com/fr/courses/1603881-apprenez-a-creer-votre-site-web-avec-html5-et-css3/1608357-memento-des-balises-html

4) Historique des mails

A partir du moment ou vous êtes en DIRTYPE(*SMTP)
Vous n’écrivez plus dans le journal QZMF de QUSRSYS, il est conseillé de passer à JOURNAL(*NO) et ALLMAILMSF(*NO)

pour arrêter MSF qui ne sert plus à rien vous devez supprimer le job à démarrage automatique avec la jobd QZMFEJBD ou vous pouvez changer la jobd et remplacer le STRMSF … par un SNDMSG (‘coucou’) TOUSR(*SYSOPR)

5) Utilisez un sous-système spécifique

Pour des questions d’administration, vous pouvez mettre un sous système spécifique qui permet de mieux gérer les travaux relatives aux mails et qui par défaut sont dans QSYSWRK

CHGSMTPA SBSD(QSYS/QSMTP)

Vous devez arrêter et redémarrer le service pour la prise en compte

Conclusion:

C’est la meilleur solution pour envoyer des mails, il y a des nouveautés à chaque version.

, Advanced Job Scheduler avec alerte sur plantage !

Vous utilisez AJS sur votre machine pour planifier les jobs sur votre IBMi.

Vous connaissez l’interface 5250, mais certaines options ne sont disponibles que dans l’interface Navigator for i.

Exemple, si vous voulez avoir un message en cas de plantage de votre job planifié.

Vous aurez défini au préalable la liste des utilisateurs avec leur rôle et leur mail, ici De garde

Remarque :

Attention si vous avez des robots de supervision qui vont analyser la msgq QSYSOPR

Cette option ne devra être mise que sur certain jobs plus stratégiques que d’autres !

Merci à Laurent pour les informations

, Analyser les homedir de vos utilisateurs

Vous utilisez de plus en plus les fichiers dans l’IFS pour échanger vos csv , PDF etc … ou par des connexions qui utilisent l’open source.

.

Ces chiffres sont ceux , constatés sur les clients du groupe Gaia Volubis et incluent la partie complètes des fichiers de l’IFS (/home et le reste).

Par défaut quand vous créer un profil par la commande CRTUSRPRF, vous avez le paramètre HOMEDIR( *USRPRF) ce qui indique un répertoire par défaut /home/USRPRF.

Le Homedir correspond au répertoire par défaut comme la *Curlib du coté de QSYS.LIB.

Attention il n’y a pas de contrôle d’existence et si le répertoire n’existe pas l’utilisateur va travailler à la racine ce qui peut créer des fichiers indésirables à la racine de votre système, et qui contribue à une désorganisation de l’IFS !

De même si certains utilisateurs ont un répertoire par défaut différent de cela peut complexifier vos procédures de ménage. Les répertoires homedir de vos users devant servir le plus souvent à des échanges et non pas du stockage.

Voici quelques requêtes pour vous aider à analyser cela

Liste des répertoires utilisateurs avec leur répertoire théorique

Select AUTHORIZATION_NAME as user_profile, home_directory from QSYS2.USER_INFO

Liste des utilisateurs avec leur répertoire associé existant

create table exploit.usr_dir as(
WITH TEMP_A AS(
SELECT cast(substr(PATH_NAME , 1 , 132) as char(132)) as path_name, ALLOCATED_SIZE
FROM TABLE(IFS_OBJECT_STATISTICS(
START_PATH_NAME => ‘/HOME’ ,
OBJECT_TYPE_LIST => ‘*ALLDIR’))
where
LOCATE_IN_STRING(path_name, ‘/’, 1 , 2) > 1
)
select * from temp_a join QSYS2.USER_INFO on ucase(‘/home/’ concat authorization_name) = ucase(path_name)
) with data

dans ce cas je crée un fichier temporaire, mais vous pouvez le faire en une seule requête

Voici donc 2 principales erreurs à surveiller

Liste des utilisateurs avec un homedir qui n’est pas dans /home

select * from QSYS2.USER_INFO
where ucase(home_directory) not like(‘/HOME/%’)

Liste des utilisateurs avec une homedir inexistante

select a.AUTHORIZATION_NAME, a.HOME_DIRECTORY from QSYS2.USER_INFO as a exception join exploit.usr_dir as b on ucase(trim(a.Home_directory)) = ucase(trim(b.Path_name))

Liste des partages avec sur /home

SELECT SERVER_SHARE_NAME, PATH_NAME, PERMISSIONS FROM QSYS2.SERVER_SHARE_INFO
where ucase(path_name) like(‘/HOME%’) and SHARE_TYPE = ‘FILE’

Vous devez en avoir un seul avec *RW

Rappel , par contre vous ne devez pas partager la racine pour contrôler passez la requête suivante,

SELECT SERVER_SHARE_NAME, PATH_NAME, PERMISSIONS FROM QSYS2.SERVER_SHARE_INFO
where path_name = ‘/’

Remarque :

Dans cette partie de l’ifs pas de différentiation majuscule minuscule

Si vous avez beaucoup de fichiers à la racine, regardez les propriétaires, vous avez surement un homedir mal paramétré.

Rappel, vous ne devez pas partager la racine

, Faire une sauvegarde complète de votre système.

On parle souvent de Sauvegarde 21 à cause de l’option du menu qui servait à le lancer historiquement

Cette sauvegarde nécessite d’être en mode restreint

Voici comment passer dans ce mode sans vous signer sur la console

On peut passer en mode restreint grâce au paramètre BCHTIMLMT de la commande ENDSBS

Pour passer en mode restreint, vous devez indiquer la durée en minutes avant redémarrage !

ENDSBS SBS(ALL) OPTION(IMMED) BCHTIMLMT(240)

Ici au bout de 3 Heures, le système se relancera de lui même en interrompant votre sauvegarde si besoin.

Par contre si votre sauvegarde se termine votre système redémarrera de suite grâce à la commande STRSBS SBSD(QCTL)
Si votre sous système de contrôle est qctl

Pour estimer votre temps de sauvegarde regarder la sauvegarde précédente.
Si vous n’avez pas de référence mettez 480 soit 8 heures lancer votre sauvegarde un weekend ajustez ensuite le temps avec les chiffres constatés, prenez toujours un peu de marge !

Pour la liste des éléments à sauvegarder voir le schéma ci dessous extrait de la documentation IBM

Quelle est la bonne fréquence pour faire une sav21

Si vous pouvez en faire une tous les soirs faites le !

Sinon un fois par mois semble être le minimum, même si vous avez du backup !

Ci joint un exemple à améliorer en ajoutant des contrôles d’erreur par exemple !

PGM parm(&dev &time)
dcl &dev *char 10
dcl &time *char 3
/**/
dcl &timn *dec 3
ENDHOSTSVR *ALL
ENDTCPSVR *ALL
DLYJOB DLY(300)
ENDTCP
ENDSBS SBS(ALL) OPTION(IMMED) BCHTIMLMT(&timn)
DLYJOB DLY(180)
SAVSYS DEV(&DEV) DTACPR(YES)

MONMSG MSGID(CPF0000) EXEC(DO)

SNDUSRMSG MSG(‘Probléme pendant le SAVSYS’) +

MSGTYPE(INFO)
return
enddo
SAVLIB LIB(NONSYS) DEV(&DEV) ACCPTH(YES) +
SPLFDTA(ALL) QDTA(DTAQ) PVTAUT(YES) +

DTACPR(YES)
MONMSG MSGID(CPF0000) EXEC(DO)
SNDUSRMSG MSG(‘Probléme pendant le SAVLIB’) +
MSGTYPE(INFO)

return

enddo

SAVDLO DLO(ALL) DEV(&DEV) DTACPR(YES)

MONMSG MSGID(CPF0000) EXEC(DO)

SNDUSRMSG MSG(‘Probléme pendant le SAVDLO’) +

MSGTYPE(INFO)
return
enddo
SAV DEV((‘/QSYS.LIB/’ *TCAT &DEV *TCAT ‘.DEVD’)) +
OBJ((‘/*’) (‘/QSYS.LIB’ *OMIT) (‘/QDLS’ +
OMIT)) UPDHST(YES) DTACPR(YES)

MONMSG MSGID(CPF0000) EXEC(DO)

SNDUSRMSG MSG(‘Probléme pendant le SAVIFS’) +

MSGTYPE(INFO)
return
enddo
STRSBS SBSD(QCTL)
ENPPGM

Remarque :


Votre programme devra être placé dans le sous système QCTL
Si vous utilisez BRMS la procédure diffère un peu , surtout pour la restauration

, , Rechercher dans l’IFS de votre IBMi

Il peut vous arriver de vouloir rechercher une chaine de caractères dans votre IFS voici comment vous pouvez faire en utilisant SQL service .

1) Recherche d’un nom fichier sur une chaine

SELECT cast(substr(PATH_NAME , 1 , 132) as char(132)) as PATH_NAME
FROM TABLE(IFS_OBJECT_STATISTICS(
START_PATH_NAME => ‘/HOME/PLB’ ,
OBJECT_TYPE_LIST => ‘*ALLSTMF’))
where ucase(PATH_NAME) like (‘%PRO%’)

Ici, recherche PRO dans le nom du fichier du répertoire /HOME/PLB

2) Recherche d’une chaine dans les fichiers

Création d’un fichier résultat !

CREATE OR REPLACE TABLE RETURN_TABLE
(STMF_NAME char(100),
LINE_NUMBER decimal(5 , 0),
LINE varchar(132))

Recherche de la chaine dans tous les fichiers

begin
for
SELECT PATH_NAME as IFS_PATH_NAME
FROM TABLE(IFS_OBJECT_STATISTICS(
START_PATH_NAME => ‘/HOME/PLB’ ,
OBJECT_TYPE_LIST => ‘*ALLSTMF’))
do
INSERT INTO RETURN_TABLE
SELECT IFS_PATH_NAME ,
LINE_NUMBER ,
cast(substr(LINE , 1 , 132) as char(132))
FROM TABLE(IFS_READ(
PATH_NAME => IFS_PATH_NAME))
WHERE UPPER(LINE) like ‘%’ concat ‘PRO’ concat ‘%’ ;

end for;
end

Ici, recherche PRO dans les fichiers du répertoire /HOME/PLB

Attention

Ces recherches sont très consommatrices elles doivent être soumises en batch

Conclusions :


Ça peut vous aidez dans vos recherches, mais attention au nombre de fichiers à scanner.
Si vous êtes amené à faire régulièrement ce type de recherche, préférer la mise en œuvre de OMNIFIND

Si vous voulez l’exemple en fonction table il est ici :

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

, 5 Choses (expertes) sur la gestion des mots de passe

1) Crypter le mot de passe

Voici quelques informations complémentaires sur la gestion de vos mots de passe qui sont un peu plus compliquer à mettre en œuvre mais qui peuvent vous éviter des problèmes et vous faciliter la gestion .


Par défaut les mots de passe circulent en clair sur votre réseau et avec TRCCNN sur L’IBMi ou en utilisant un outil réseau par exemple, wireshark vous pouvez voir le mot passe.
La solution est donc de passer en SSL.
Voici les étapes à réaliser :

  • Vous devez créer un certificat autosigné en utilisant DCM

  • Indiquer les applications qui seront protégées par ce service

  • Indiquer sur le client que la connexion se fait en TLS

  • La première connexion vous demandera d’accepter d’échanger avec le site distant est par la suite tous vos échanges seront cryptés

2) Supprimer les mots de passe


La volonté est de plus pour éviter la prolifération des mots de passe d’aller vers du SSO, ce qui simplifierait la gestion des mots de passe utilisateurs.
Sur l’IBMi la solution à mettre en œuvre c’est Kerberos qui s’appuiera sur votre AD Windows, pour en savoir plus regardez ici https://blog.devensys.com/kerberos-principe-de-fonctionnement/
Vous devrez alors gérer un annuaire sur votre IBMi qui s’appelle EIM pour en savoir plus, regardez ici https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_74/rzalv/rzalvmst.htm
dans cette annuaire vous aurez toutes les correspondances entre vos logins IBM i et Windows, vous pouvez également utiliser kerberos pour sécuriser vos accès entre partitions IBMi, FTP par exemple .

3) Mise en place d’un programme de validation

Si les règles de contrôle de mot de passe ne suffisent pas vous pouvez indiquer un programme complémentaire.
Si vous êtes en niveau de mot de passe 1 ou 0 valeur système QPWDLVL, vous pouvez indiquer un programme dans la valeurs système QPWDVLDPGM voici un exemple

PGM (&NEWPWD &OLDPWD &sts &usrprf)
DCLPRCOPT USRPRF(OWNER) / Programme de controle de mot de passe / / Il est déclaré par la valeur système QPWDVLDPGM / / PWDLVL Doit être à Zéro ou à 1 / DCL VAR(&NEWPWD) TYPE(CHAR) LEN(10)
DCL VAR(&OLDPWD) TYPE(*CHAR) LEN(10)
dcl &sts *char 1 /* résultat du controle / / 0 ok / / 1 pas ok / DCL VAR(&USRPRF) TYPE(CHAR) LEN(10)
/* Renvoyer ‘0’ si ok dans tous les cas */
chgvar &sts ‘0’
endpgm

Si le niveau de mot de passe est 2 ou 3, vous devrez utiliser un programme exit QIBM_QSY_CHK_PASSWRD , ou QIBM_QSY_VLD_PASSWRD vous pouvez ajouter votre programme par WRKREGINF puis option 8.

d/INCLUDE QSYSINC/QRPGLESRC,ECHKPWD1
dcl-s old ucs2(128) based(oldPtr) ;
dcl-s new ucs2(128) based(newPtr) ;
dcl-s old2 ucs2(128) based(oldPtr) ;
dcl-s new2 ucs2(128) based(newPtr) ;

dcl-pi *N ;
P_Buffer char(1024) ;
P_status char(1) ;
end-pi ;

ECHQCPI00 = P_Buffer;

oldPtr = %addr( P_Buffer ) + ECHOTOP ;
newPtr = %addr( P_Buffer ) + ECHOTNP ;
old2 = %subst( old : 1 : ECHLOOP * 2 ) ;
new2 = %subst( new : 1 : ECHLONP * 2 ) ;
// Votre contrôle
// si ok on renvoit ‘0’ si Ko on renvoit KO
P_status = ‘0’ ;
*inlr = *on ;

attention les mots de passe sont en UCS2, et le mot de passe old est toujours à *NOPWD

Le programme ne se déclenchera que si les règles de contrôle de mot de passe sont vérifiés avant

Ces programmes devront être compiler en adoption de droit par rapport à QSECOFR

4) Mettre en place un rendu de mot de passe automatique


Il peut être important de faciliter le rendu de mot de passe, un peu comme sur internet avec le bouton mot de passe oublié.
le principe est le suivant :
il faudra avoir un fichier qui comporte à minima l’utilisateur IBMi et le mail pour faire le lien

vous devrez avoir un programme en CLLE par exemple
/* 1 récupération du mail* /

call pgm(rtvmail &usr &mail )

/* 2 calcul du mot de passe */

chgvar &PWD …….

/* 3 modification du mot de passe * /

CHGUSRPRF USRPRF(&USR ) PASSWORD(&PWD ) + PWDEXP(YES) STATUS(ENABLED)

/*6 envoi du nouveau mot de passe */
CHGVAR VAR(&NOTE) VALUE(‘Votre nouveau mot de passe +
est, ‘ *BCAT &PWD *BCAT ‘, vous devrez le +
changer à la première utilisation’)
SNDSMTPEMM RCP((&MAIL)) SUBJECT(‘Mot de passe perdu’) +
NOTE(&NOTE)

/* 5 log de l’information */
SNDMSG MSG(‘Mot de passe pour l »utilisateur’ *BCAT +
&USR *BCAT ‘réinitialiser par’ *BCAT +
&USRE) TOMSGQ(*HSTLOG)

Ce programmes devra être compiler en adoption de droit par rapport à QSECOFR

Attention,
vous pouvez en fonction de votre organisation, envoyer un mail au responsable , etc…
vous pouvez lancer ce programme par un autre utilisateur qui fera la demande
vous pouvez, et c’est le mieux, faire une page web sur votre IBMi, PHP, NODEJS, Autres qui fera cette demande
Il est conseillé malgré tout de bien suivre ces opérations de rendu de mot de passe

5) Auditer les violations de mot de passe


Vous pouvez tracer les erreurs de mot de passe, pour faire ça sur l’IBMi, vous devez mettre en place l’audit
C’est la valeurs système QAUDLVL vous devez au moins indiquer *AUTFAIL
C’est les codes PW qui vont indiquer une erreur de mot de passe
Vous pouvez avoir un suivi en analysant les postes de journaux exemple
DSPJRN JRN(QAUDJRN) JRNCDE((T)) ENTTYP(PW)
Vous pouvez être proactif en mettant en place une solution IDS
En utilisant un programme d’exit de journal par exemple :

RCVJRNE JRN(QAUDJRN) EXITPGM(VOTREBIB/VOTREPGM) RCVRNG(*CURCHAIN) +
FROMENTLRG(poste de début) +
JRNCDE((T)) ENTTYP(‘PW’)

Attention à soumettre votre traitement pour pouvoir l’arrêter proprement

Conclusions

Une bonne politique de mots de passe est une des pierres angulaires de la stratégie de sécurité

, 5 Choses (avancées) sur la gestion des mots de passe

Voici quelques informations, un peu plus sensibles sur la gestion des mots de passe.

1) Mot de passe SST


Pour accéder aux outils de maintenance système (SST), vous devez avoir un profil créé (CRTSSTUSR) et votre profil IBMi devra avoir le droit *SERVICE
vous pouvez ensuite lancer une session SST par STRSST

2) Mot de passe iNetServer


iNetServer gère son propre contrôle de mot de passe identique pour accéder à vos partages.
vous avez sans doute déjà reçu des messages CPIB682 qui indiquent que l’utilisateur est désactivé pour NetServer
pour le réactiver vous pouvez passer par Navigator For i ou utiliser l’API QZLSCHSI
exemple ici

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

3) Contrôler un mot de passe


Par la commande CHKPWD sur le profil en cours , monmsg CPF2300 à traiter
Par API QSYGETPH, plus d’information, sur le site https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_74/apis/QSYGETPH.htm
exemple
PGM PARM(&userid &passwrd &STS)
/* Paramètres*/

DCL VAR(&USERID) TYPE(CHAR) LEN(10) /* input */

DCL VAR(&PASSWRD) TYPE(CHAR) LEN(10) /* input */
DCL &STS *CHAR 01 /* output */

/* Variables de travail / DCL VAR(&ERRORCODE) TYPE(CHAR) LEN(272)
DCL VAR(&MSGID) TYPE(CHAR) STG(DEFINED) LEN(7) DEFVAR(&ERRORCODE 9)
DCL VAR(&HANDLE) TYPE(CHAR) LEN(12)

/* Récupère le handle */

CHGVAR VAR(&ERRORCODE) VALUE(X’0110′) CALL QSYGETPH (&USERID &PASSWRD &HANDLE &ERRORCODE X’0000000A’ X’FFFFFFFF’) /* test message d’erreur */
If (&MSGID *ne ‘ ‘) THEN(Do)
CHGVAR VAR(&STS) VALUE(‘1’)
SNDPGMMSG MSGID(CPF9897) MSGF(*LIBL/QCPFMSG) +
MSGDTA(&MSGID *BCAT ‘Erreur contrôle de +
mot de passe’) MSGTYPE(ESCAPE) ENDDO ELSE CMD(DO) CHGVAR &STS VALUE(‘0’) SNDPGMMSG MSGID(CPF9897) MSGF(LIBL/QCPFMSG) +
MSGDTA(‘Mot de passe correct pour le +
profil ‘ !! &USERID) MSGTYPE(*COMP)
ENDDO
ENDPGM

4) Supprimer le mot de passe

Certains utilisateurs ne servent pas à se connecter et il peut être important de leurs enlever celui c’est le cas des profils de QSRV et QSRVBAS par exemple !
pour réaliser cette opération vous devez faire un chgusrprf en indiquant le paramètre PASSWORD(*NONE)

5) Rendre un mot de passe utilisateur sans être *SECADM


Par défaut un utilisateur ne peut modifier que son mot de passe. Pour qu’un utilisateur puisse rendre un mot de passe, on peut faire un programme en adoption de droit par rapport à un profil qui lui a *SECADM.
exemple
commande
CMD PROMPT(‘Changement PWD Utilisateur’)
PARM KWD(USRPRF) TYPE(NAME) LEN(10) MIN(1) + PROMPT(‘Profil utilisateur’)

programme

PGM PARM(&USR)

DCLPRCOPT USRPRF(OWNER)
/* paramètres */
dcl &usr *char 10
/* variables de travail */
dcl &usre *char 10
CHKOBJ OBJ(&USR) OBJTYPE(*USRPRF)
monmsg cpf9801 exec(do)
SNDUSRMSG MSG(‘Profil,’ *BCAT &USR BCAT ‘inexistant’) + MSGTYPE(INFO)
RETURN
enddo
RTVJOBA USER(&USrE)
CHGUSRPRF USRPRF(&USR ) PASSWORD(&USR ) +
PWDEXP(YES) STATUS(ENABLED)
monmsg cpf0000 exec(do)
SNDMSG MSG(‘Modification de passe impossible pour +
l »utilisateur’ *BCAT &USR *BCAT ‘demandée +
par’ BCAT &USRE) TOMSGQ(HSTLOG)
RETURN
enddo
SNDMSG MSG(‘Mot de passe pour l »utilisateur’ *BCAT +
&USR *BCAT ‘réinitialisé par’ BCAT + &USRE) TOMSGQ(HSTLOG)
endpgm