Il est difficile de déboguer un watcher parce qu’on ne maitrise pas son lancement.

Voici une méthode en utilisant RDI, qui va vous permet de le faire :

  1. Trouver le nom du programme à analyser :

WRKWCH WCH(*ALL) :

  • 5 pour le détail
  • Dans RDI, clic droit sur le programme à déboguer => débogage ou couverture de code (entrée de service) => définir un point d’entrée de service

Le message d’affiche :

Pour tester, on peut simuler un traitement qui va planter. Dans notre cas, on fait un call d’un programme qui n’existe pas, et donc ça va faire un plantage dans QSYSOPR.

SBMJOB CMD(CALL PGM(GAIA/ERREURA)) 

        JOB(ERREURA)                

        JOBQ(QSYSNOMAX)         

Une fois le programme a été lancé, sur RDI s’affichera le message suivant :

Cliquer sur « Afficher *LISTING »

Pour avancer d’un pas on peut utiliser la touche F5 ou en cliquant sur la flèche :

Pour afficher les valeurs des variables il suffit de passer la souris sur le nom de la variable :

Conclusion : c’est une solution simple pour déboguer un watcher ou un programme dont vous ne maitrisez pas le lancement.

Le programme doit être compilé avec le source.

Vous devrez avoir le droit pour faire ce type d’opération. Soit au niveau de profil, soit par les fonctions usages.

, , Informations sur les SAVF

Les groupes DB2 pour la TR2 de la V7R5 et de la TR8 de la V7R4 sont disponibles, une des nouveautés c’est les vues sur les fichiers de sauvegarde

La première vue sur les SAVF SAVE_FILE_INFO permet d’avoir des informations sur le SAVF

par exemple
vous voulez connaitre les SAVF qui date de plus de 6 mois

select * from QSYS2.SAVE_FILE_INFO
where SAVE_TIMESTAMP < current date – 6 month
order by SAVE_TIMESTAMP desc

Vous pouvez par exemple utiliser la fonction SQL QCMDEXC pour faire le ménage plus d’informations ici
https://www.gaia.fr/qcmdexc-en-fonction-sql/

La deuxième vue sur les objets sauvegardés dans les SAVF, QSYS2.SAVE_FILE_OBJECT permet d’avoir des informations sur les ojets contenus dans le SAVF

Par exemple vous voulez savoir, si un objet est dans une sauvegarde et sa date de sauvegarde

select * from QSYS2.SAVE_FILE_OBJECTS
where OBJECT_NAME = ‘votre objet’ and OBJECT_TYPE = ‘votre type’
order by SAVE_TIMESTAMP desc

Attention
Ces fonctions sont à lancer en batch, c’est des informations qui mettent du temps à être extraites

, Messages CPF1124 et CPF1164

Quand un travail démarre, il crée dans la log système un message CPF1124 et un message CPF1164 quand il se termine.

C’est comme ca qu’on sait qu’un job à tourné

Mais attention, Il existe des travaux pour lesquels les messages CPF1124 et CPF1164 ne sont pas logués dans QHST : il s’agit des SPAWN jobs.

Les travaux QP0ZSPWP & QP0ZSPWT en sont de bons exemples.

Spawn batch jobs : https://www.ibm.com/docs/en/i/7.4?topic=jobs-spawn-batch

Spawn est une fonction qui crée un nouveau processus de travail (processus enfant) qui hérite de nombreux attributs du processus appelant (processus parent). Un nouveau programme est spécifié et commence à s’exécuter dans le processus enfant. Lorsque vous lancez un travail par lots, vous utilisez un travail parent pour transmettre des arguments et des variables d’environnement au travail enfant. L’API spawn() utilise des travaux batch immédiats, des travaux pré-démarrés ou des travaux batch pré-démarrés.

https://www.ibm.com/docs/en/i/7.4?topic=ssw_ibm_i_74/apis/spawn.htm

https://www.ibm.com/docs/en/i/7.4?topic=programs-example-using-process-related-apis

Ca peut être le cas aussi pour les jobs QCTXDMON (IBM transformer)

plus rigolo

Vous pouvez demander à supprimer ces messages

Pour cela vous devez créer une dtaara QWTFMSG dans QUSRSYS :

CRTDTAARA DTAARA(QUSRSYS/QWTFMSG) TYPE(*CHAR) LEN(14) VALUE(‘CPF1124CPF1164’)

Cette valeur est prise en compte au démarrage de vos sous systémes

elle est globale c’est dommage qu’on ne puisse préciser un sous système

Attention


Beaucoup d’outils d’analyse utilise ces messages pour vérifier le bon traitement d’une tache

, Les instructions SQL d’un profil

Vous voulez récupérer les requêtes SQL exécutées sous une session interactive

Si vous pouvez vous connecter sous le profil c’est relativement simple

Connectez vous sous le profil et sous STRSQL faites <F13>

Vous pouvez indiquer un fichier avec différentes options, le fichier par défaut s’appelle QSQLSESS de QGPL

La difficulté existe, si vous ne pouvez pas vous connecter sous le profil en effet ces informations sont stockées dans le profil.

Pour les voir vous devrez donc utiliser la commande DMPSYSOBJ

Comme ceci

DMPSYSOBJ OBJ(‘ISQLSTvotreuser*’) +
CONTEXT(QRECOVERY) TYPE(19) SUBTYPE(EE)

Vous obtenez un spool QPSRVDMP que vous pourrez analyser

Bien sur vous devez avoir le droit de dumper et le droit sur le profil

Pour vous aider nous avons fait un outil DMPSQLUSR que vous pouvez trouvez ici https://github.com/Plberthoin/PLB/tree/master/GTOOLS

Il n’est pas parfait, mais il produit un fichier SQLLISTE dans QTEMP qui contiendra toutes instructions exécutées

Rappel :

Vous pouvez également retrouver des informations sur l’exécution des requêtes dans des moniteurs DB ou dans le cache SQL.

Il existe un comcept dans SQL sur les tables qui s’appelle les zones cachées.
Je vais essayer de vous expliquer ce que c’est.

Exemple :

CREATE TABLE SALAR (
NUMERO CHAR(6) CCSID 1147 NOT NULL DEFAULT  » ,
NOM CHAR(20) CCSID 1147 NOT NULL DEFAULT  » ,
PRENOM CHAR(30) CCSID 1147 NOT NULL DEFAULT  » ,
SALAIRE DECIMAL(5, 0) NOT NULL DEFAULT 0 IMPLICITLY HIDDEN )

Pour faire simple ces des zones qui n’apparaîtront pas si vous faites un select *


Il y plusieurs buts à cette démarche , caché sommairement des informations ou simplifier des requêtes en cachant des informations utiles et enfin les zones complétables automatiquement les bien connues date, heure et utilisateur de modification.
Maintenant que vous savez ce que c’est je vais vous expliquer l’impact sur vos développements existants.
D’abord bien sûr si vous avez des select * dans vos développements ça produira une erreur si vous respectez les règles de développement vous ne devriez pas en avoir.
Ensuite sur les insert , par défaut il ne connait que les zones non cachées vous devrez indiquer explicitement les zones cachées que vous voulez alimenter.

Conclusion
Ça peut être intéressant dans certains cas pour éviter une vue qui aurait juste pour fonction de limiter les zones.
Attention toutefois, si voulez utiliser cette possibilité toutes les zones sont visibles dans les invites Sql …

Et enfin une zone ajoutée même en hidden change le niveau de format puisqu’il est calculé sur l’ensemble des zones.

, Gestion des clefs SSH

Prérequis

L’utilisateur doit avoir un répertoire initial dans l’IFS. (C’est lui qui sera indiqué par le ~ dans les commandes ci-dessous)
Produits Open Sources :
OpenSSL
SFTP

S’assurer que le service SSH est démarré :

Démarrage du service SSH

S’assurer que le service SSH est démarré :

WRKTCPSTS OPTION(*CNN)

S’il n’est pas démarré, via 5250 :

STRTCPSVR SERVER(*SSHD)

Génération des clefs SSH

En 5250 (QSH ou QP2TERM) :

CALL PGM(QP2TERM)

S’il n’exsite pas, on crée le répertoire .ssh, via la commande mkdir, dans le répertoire par défaut de
l’utilisateur, on lui attribue les droits de lecture, écriture et execution via la commande chmod, puis on execute
la commande ssh-keygen :

mkdir ~/.ssh/
chmod 700 ~/.ssh
ssh-keygen -t rsa -b 2048 -f ~/.ssh/sftp_key -N ''

Voici une idée du résultat obtenu :

Generating public/private rsa key pair.
Your identification has been saved in /home/exploit/.ssh/sftp_key.
Your public key has been saved in /home/exploit/.ssh/sftp_key.pub.
The key fingerprint is:
SHA256:pDxRGtx4YBKbsHTVLpDg8OXyF5VcSBKgfpX4eGXqaGY
The key's randomart image is:
+---[RSA 2048]----+
|. +.**BO++.      |
| = Bo*oBB        |
| * =.*o+         |
| . o =.O.        |
| . + O.S         |
| . = .           |
| E .             |
| +               |
|                 |
+----[SHA256]-----+
Informations supplémentaires :
Options
-t Type de clef créée.
-b Nombres de bits dans la clef créée.
-f Fichier de sortie.
-N Phrase de chiffrement.

Mise en place de la configuration des clefs

Côté client

ATTENTION aux droits des fichiers contenus dans le dossier /.ssh qui ne doit contenir, en principe, que les clefs privées et le fichier config (qui est optionnel).

Côté serveur

S’il n’exsite pas, on crée le répertoire .ssh sur le serveur, via la commande mkdir, dans le répertoire par
défaut de l’utilisateur, on lui attribue les droits de lecture, écriture et execution via la commande chmod :

mkdir ~/.ssh
chmod 700 ~/.ssh

Déposer la clef publique sur le serveur distant puis, ajouter la clef publique au fichier authorized_keys :

cat [sshKey.pub] >> authorized_keys

Puis vérifier le propriétaire et les droits du fichier authorized_keys :

chown [userName] ~/.ssh/authorized_keys
chmod 600 authorized_keys

Supprimer le fichier contenant la clef publique.

ATTENTION aux droits des fichiers contenus dans le dossier /.ssh qui ne doit contenir, en principe, que la clef publique

Tester la liaison SSH

Via QSH ou QP2TERM

ssh -T -i [privateKey] [remoteUserName]@[serverName]

Options :

-T Désactivez l’allocation de pseudo-terminal

-i Fichier privé

Tester la liaison SFTP

Via QSH ou QP2TERM

sftp -i [privateKey] [remoteUserName]@[serverName]

-i Fichier privé

Merci à Julien LAURIER pour sa contribution à l’écriture de cet article.

, , Les tables de conversion

Les tables de conversion sont des objets de type *TBL

Vous en trouvez un grand nombre dans QSYS ou QUSRSYS les 2 plus connues sont

QEBCDIC *TBL QSYS ASCII TO EBCDIC TRANSLATE TO ASCII
QASCII *TBL QSYS EBCDIC TO ASCII TRANSLATE TO EBCDIC

elles servent à convertir une donnée, elle sont utilisées dans certaines commandes FTP ou QUERY Etc …

Vous pouvez également les utiliser vous dans vos développements (bien qu’aujourd’hui SQL semble une meilleur alternative)

Imaginons que vous voulez crypter quelque chose par exemple dans une field proc et que pour vous l’utilisation des API Qc3EncryptData et Qc3DecryptData soit un peu compliqué.

Vous pouvez utiliser cette solution c’est pas le top mais la multiplication des moyens de cryptage ralenti les hackers …

Vous devrez donc créer votre table de conversion
dans un fichier source le plus souvent QTBLSRC

Vous devez alors compiler votre table par la commande CRTTBL …

j’ai choisi pour mon exercice de faire une table alternative, la première fois elle crypte la deuxième elle decrypte

il existe une API système qui s’appelle QCDXLATE qui a un format très simple

https://www.ibm.com/docs/en/i/7.3?topic=ssw_ibm_i_74/apis/QDCXLATE.html

Voici un exemple d’utilisation en RPG et en CLP

les programmes donneront ce résultat

en CLP 

pgm                                                 
dcl &MyValLen *dec (5 0) 30                         
dcl &MyVal *char 30                                 
chgvar &myval 'Bonjour Michel'                      
sndusrmsg ('Avant :' *bcat &myval) msgtype(*info)   
     call QDCXLATE (&MyValLen &MyVal 'CONVERT')     
sndusrmsg ('Premier :' *bcat &myval) msgtype(*info) 
     call QDCXLATE (&MyValLen &MyVal 'CONVERT')     
sndusrmsg ('Second :' *bcat &myval) msgtype(*info)  
endpgm                                              
en RPGLE

**free                                         
 CTL-OPT                                       
   DFTACTGRP(*NO)                              
   DATFMT(*ISO)                                
   OPTION(*SRCSTMT : *NODEBUGIO)  ;            
Dcl-PR Translate  ExtPgm('QDCXLATE');          
 Length         Packed(5:0) const;             
 Data           Char(30) options(*varsize);    
 Table          Char(10)   const;              
End-PR;                                        
dcl-s  Texte  Char(30) ;                       
Texte = 'Bonjour Michel' ;                     
dsply ('Avant : ' + Texte);                    
       Translate(128 : Texte : 'CONVERT');     
dsply ('Premier :' + Texte) ;                  
       Translate(128 : Texte : 'CONVERT');     
dsply ('Second : ' + Texte) ;                
*inlr = *on ;                                  

Conclusion :

Ce n’est pas forcément beaucoup utilisé mais ca peut être utilisé pour des conversions basiques ASCII EBCDIC ANSII etc …

Ne plus utiliser pour mettre en majuscule les fonctions UCASE en RGP ou SQL sont plus performantes et plus simples

un source de table peut être extrait par la commande RTVTBLSRC …

, , , , Gérer vos certificats par DCM

Nous utilisons de plus en plus de certificats pour crypter nos communications. Leur gestion via DCM sur l’IBM i devient donc de plus en plus nécessaire et « subtile ».

Les outils standards

Interface web de DCM (Digital Certificate Manager)

Accès par http://partition:2001/dcm

Beaucoup plus pratique et réactive depuis sa réécriture, elle comprend l’ensemble des fonctions (presque en réalité) : création des autorités, création des certificats, gestion des applications (au sens DCM), affectation, renouvellement, importation et exportation :

C’est propre, pratique.

Pour rappel, le principe : DCM permet de gérer les certificats (stocker, renouveler etc …), mais également de les affecter à une ou plusieurs applications IBM i. La notion d’application dans DCM est proche d’une notion de service : serveur telnet, serveur http, serveur ou client FTP et bien d’autres.

Ainsi un certificat peut être assigné à aucune, une ou plusieurs applications :

Et chaque application dispose de ses propres attributs, permettant par exemple de choisir les niveaux de protocoles :

A priori, on a pas de raison d’aller modifier ces attributs très souvent, l’interface web est parfaite pour ces actions

Services SQL

Pour plus de facilité, et de capacité d’automatisation, IBM délivre une fonction table (UTDF) : qsys2.certificate_info

Documentation : https://www.ibm.com/docs/en/i/7.5?topic=services-certificate-info-table-function

Disponible avec IBM i 7.5, 7.4 avec SF99704 niveau 13 et 7.3 avec SF99703 niveau 24

Exemple (IBM) :

Très utile pour obtenir directement toutes les informations, les dates de péremption etc …

Si vous êtes dans des niveaux incompatibles (ce ne devrait plus être le cas), nous avions fait pour vous une commande équivalente basée sur les APIs : https://github.com/FrenchIBMi/Outils/tree/master/API%20securite

DCM-tools

Grâce à Jesse Gorzinski (M. Open Source chez IBM), vous disposez également de commandes shell pour effectuer les principales actions de DCM : création, affectation de certificats, liste …

Voir le produit et l’installation ici : https://github.com/ThePrez/DCM-tools

Il faut absolument l’installer, cela vous permet d’automatiser de nombreuses actions courantes.

Exemple :

Les applications ?

« Houston, nous avons un problème ! ». Pas si grave non plus …

Il est facile de déterminer quels sont les certificats expirés ou qui vont expirer. Donc ceux à renouveler (création par DM ou importation). Par contre, seul l’interface web de DCM permet de voir les applications assignées, et donc les impacts de la péremption du certificat !

La connaissance des applications est primordiale : certaines nécessitent un arrêt/redémarrage du service (donc une interruption pour les utilisateurs), d’autres non.

Si aucune application n’est liée, on ne va peut être rien faire. Sinon, on va anticiper (sisi).

DCM permet de voir les applications, mais il vous faut aller sur le certificat et voir le détail par l’interface graphique. Donc humainement sur chacune de vos partitions.

API -> fonction table (UDTF)

Cette information est accessible par les APIs de DCM.

Pour plus de faciliter, nous vous proposons une fonction table SQL : listedcmapplication

Disponible en open source ici : https://github.com/FrenchIBMi/Outils/tree/master/dcm

L’objectif est de lister les applications ET les certificats associés :

Les deux paramètres permettent de sélectionner les applications avec ou sans certificat, les applications serveur ou client.

Vous pouvez également facilement utiliser les informations conjointes de qsys2.certificate_info. Par exemple, quels certificats vont expirer dans le mois et quelles sont les applications impactées :

Le code est open source, il est perfectible, n’hésitez pas à participer !

Quelques idées : agrégation des informations de différentes partitions, service correspondant actif ou non …

, , Sécuriser le SQL embarqué

SQL prend une place de plus en plus importante dans les développements.

Il faut donc prendre des mesures de protection spécifiques sur le SQL embarqué qu’on ne prenait pas forcément en RPGLE.

Par exemple si vous utilisez du cryptage avec les fonctions ENCRYPT et DECRYPT il est important de ne pas afficher la clé de cryptage.

1) Le debug

Le premier risque c’est le debug : vous allez voir la clé de décryptage, même si vous utilisez une variable host c’est facile à voir.

La solution, c’est quand vous compilez votre programme le paramètre DBGENCKEY(‘Votre_clé’)

Vous devrez désormais indiquer votre clé pour débuguer.

Attention bien à ne pas perdre cette clé qui vous sera demandée à chaque de bug !

2) Informations sur les instructions SQL embarquées

Vous avez des vues qui vous permettent de voir le code sql embarqué dans vos programmes RPGLE

exemple :

la vue QSYS2.SYSPROGRAMSTMTSTAT

Pour vous prémunir vous devrez utiliser une variable host et ainsi vous n’aurez pas la valeur de décryptage dans l’instruction …

3) Le cache sql

Vous avez l’instruction exécutée que vous pouvez consulter dans le cache SQL, par exemple par ACS

Comment faire pour que la valeur ne soit pas affichée et pas affichable dans la requête avec les variables ?

Vous avez une procédure SYSPROC.SET_COLUMN_ATTRIBUTE

CALL SYSPROC.SET_COLUMN_ATTRIBUTE(‘GENVOI’, ‘GPARAM’, ‘PWORD’, ‘SECURE YES’);

plus de detail ici

Vous avez :h dans le cache et quand vous faites <gestion instruction SQL et variables>
la zone apparait en sécure

Vous devrez faire cette opérations sur toutes les zones !

https://www.ibm.com/docs/en/i/7.4?topic=services-set-column-attribute-procedure

4) Les SQL packages

Le SQL package est un objet qui stocke des informations pour en tirer partie au cours d’une future utilisation, depuis l’arrivée du moteur SQE, ils sont utilisés en second par rapport au cache SQL

Il faut différencier 2 types de SQL PACKAGE :

  • Les sql packages qui font partie de votre programme pour les SQL statiques, vous pouvez les consulter par la commande PRTSQLINF de votre programme sqlrpgle qui produira un spool comme celui ci :

On voit que également en ayant utilisé une variable hôte que l’information n’apparait pas en claire

  • Il existe une deuxième catégorie de packages SQL qui sont dus à l’utilisation du Extended Dynamic SQL, ce sont des objets qui sont créés essentiellement pour des accès ODBC et dynamiques, ce sont des objets de type *SQLPKG, ils sont en principe créés dans la bibliothèque qui contient la base de données. SQL utilisera les informations qui sont stockées à l’intérieur quand il en aura besoin. Il est difficile de voir le contenu des ces objets , cependant vous pouvez faire un dump de cet objet, par la commande DMPOBJ comme ci-dessous , mais encore une fois pas de contenu des variables hôtes.

Ces objets peuvent être supprimés, le système les recréera automatiquement quand, par exemple, vous changez de version d’IBM i ou quand il occupe trop de place. Attention cependant, il en existe certains qui font partie de SQL comme

QSQLPKG2 de QSYS
QSQXDPKG de QSYS

En règle générale, il ne faut pas toucher à ceux dont le nom commence par Q, ni aux objets qui sont dans QSYS.

Ci dessous un lien pour en savoir plus ces objets

https://www.ibm.com/support/pages/sql-package-questions-and-answers

Complément sur la procédure SET_COLUMN_ATTRIBUTE

Merci Christian

la procédure SET_COLUMN_ATTRIBUTE cache aussi :

  • la valeur des marqueurs qui sont dans les lignes QQRID=3010 des moniteurs de performance et images instantanées de cache de plan.
  • la valeur des marqueurs qui sont dans les attributs d’un graphe Visual Explain (voir image).
  • la valeur des marqueurs dans le pseudo SQL des nœuds de VE (voir image).

Conclusion :

SQL change la donne sur certains points, vous devrez adapter votre sécurité en fonction.

Dans tous les cas, préférez une variable host à un hardcoding qui apparait en clair.

Il y a certainement d’autres choses à mettre en œuvre, mais ces quelques astuces vous donnent une idée de ce que vous devrez mettre en œuvre

, , Liste des fonctions usage

Vous avez installé un nouveau système et il vous manque des fonctions usage dans navigator for i , attention il y a des fonctions qui ne sont pas administrables par cette interface mais uniquement en 5250 par la commande =>WRKFCNUSG, cela dépendra de la catégorie :

Pour gérer plus simplement les utilisateurs pour les fonctions non administrées dans navigator for i , (par exemple QIBM_DB_ZDA qui sert pour autoriser les accès ODBC) nous proposons un produit téléchargeable à cette adresse https://github.com/Plberthoin/PLB/blob/master/WRKUSRUSG/

Vous pouvez gérer le comportement globale de la fonction <F10> et les users en exception <F6>

Maintenant ,voici comment ajouter celles qui sont administrables et que vous ne voyez pas

Leur affichage dans Navigator for i peut dépendre des produits installés sur votre partition

Ouvrir l’onglet  

Ajouter des fonctions dans fonctions usage

Puis choisir dans les actions

sélectionnez l’enregistrement des fonctions

Quand vous revenez dans liste des fonctions, vous en avez maintenant beaucoup plus

On peut analyser les violations des fonctions usage, c’est les postes de type GR dans le journal d’audit.

Soit par un DSPJRN

Soit par une requête SQL

Liste des violations de Fonction Usage sur la journée précédente !

SELECT *

  FROM TABLE (

      SYSTOOLS.AUDIT_JOURNAL_GR (STARTING_TIMESTAMP => CURRENT DATE – 1 DAYS))

    WHERE FUNCTION_REGISTRATION_OPERATION = ‘USAGE FAILURE’

Conclusion :

L’utilisation de certaines de ces fonctions devient primordiale, et il faudra s’habituer à les utiliser .

Vous pouvez ajouter ou supprimer des fonctions liées à des applications installées sur votre partition dans navigator for i mais toutes ne sont pas gérées dans l’interface !