#InterSystems IRIS

0 Abonnés · 713 Publications

InterSystems IRIS est une plateforme complète de données
InterSystems IRIS vous offre tout le nécessaire pour capturer, partager, comprendre et agir sur la ressource le plus précieuse de votre entreprise : vos données.
En tant que plateforme complète, InterSystems IRIS élimine la nécessité d'intégrer plusieurs technologies de développement. Les applications nécessitent moins de code, moins de ressources système et moins de maintenance.

Annonce Irène Mykhailova · Juin 30, 2025

Vous avez au moins deux ans d'expérience en développement avec la plateforme de données InterSystems IRIS et des connaissances de base en InterSystems ObjectScript ?

Validez votre expertise avec le nouvel examen InterSystems IRIS Development Professional certification, notre premier examen de niveau professionnel !

Badge: InterSystems Certified. InterSystems IRIS Development Professional 

0
0 24
Article Iryna Mykhailova · Juin 24, 2025 3m read

J'écris cet article principalement pour recueillir un consensus informel sur la façon dont les développeurs utilisent Python avec IRIS. N'hésitez donc pas à répondre au sondage à la fin de cet article ! Dans le corps de l'article, je détaillerai chaque choix proposé, ainsi que ses avantages, mais n'hésitez pas à le parcourir et à simplement répondre au sondage.

0
0 36
Article Guillaume Rongier · Juin 23, 2025 27m read

Introduction

Dans le contexte actuel où les menaces évoluent rapidement, les organisations qui déploient des applications critiques doivent mettre en œuvre des architectures de sécurité robustes qui protègent les données sensibles tout en maintenant une haute disponibilité et des performances élevées. Cela est particulièrement crucial pour les entreprises qui utilisent des systèmes de gestion de bases de données avancés tels qu'InterSystems IRIS, qui alimentent souvent des applications traitant des données hautement sensibles dans les domaines de la santé, de la finance ou des données personnelles.

Cet article décrivent en détail une architecture de sécurité complète à plusieurs niveaux pour le déploiement de clusters InterSystems IRIS sur AWS à l'aide de Kubernetes (EKS) et InterSystems IAM. En appliquant les principes de défense en profondeur, cette architecture fournit une protection à tous les niveaux, du périmètre du réseau au niveau de l'application et du stockage des données.

Pourquoi une approche à plusieurs niveaux est-elle importante

Les stratégies de sécurité à un seul niveau sont de plus en plus inadéquates face à des vecteurs d'attaque sophistiqués. Lorsqu'un contrôle de sécurité échoue, des niveaux supplémentaires doivent être mis en place pour éviter une compromission totale. Notre architecture implémente des contrôles de sécurité à cinq niveaux critiques:

  1. Sécurité périmétrique: Utilisation d'AWS WAF et CloudFront pour filtrer le trafic malveillant avant qu'il n'atteigne vos services
  2. Sécurité réseau: Exploitation des stratégies réseau AWS VPC, des groupes de sécurité et de Kubernetes
  3. Sécurité des API: Implémentation d'InterSystems IAM avec des plug-ins de sécurité avancés
  4. Sécurité des applications: Renforcement de la passerelle Web grâce à des restrictions URI rigoureuses
  5. Sécurité des bases de données: Configuration du cluster IRIS avec authentification et chiffrement robustes

À la fin de cet article, vous comprendrez comment mettre en œuvre chaque couche de sécurité et comment elles fonctionnent conjointement pour créer une stratégie de défense en profondeur qui protège vos déploiements IRIS contre un large éventail de menaces tout en préservant les performances et l'évolutivité.
 


Aperçu de l'architecture

Notre architecture de sécurité repose sur le principe de la défense en profondeur, chaque niveau fournissant une protection complémentaire. Voici un aperçu général de la solution complète:


Structure de déploiement du cluster IRIS

Notre cluster IRIS est déployé à l'aide de l'Opérateur Kubernetes d'InterSystems (IKO) selon une topologie soigneusement conçue:

  1. Niveau de données: Deux instances IRIS dans une configuration en miroir pour une haute disponibilité et une redondance des données
  2. Niveau d'application: Deux serveurs d'applications IRIS qui accèdent aux données via ECP (Enterprise Cache Protocol)
  3. Passerelle API: InterSystems IAM (basé sur Kong) pour la gestion et la sécurité des API
  4. Passerelle Web: Trois instances de passerelle Web (CSP+Nginx) pour traiter les requêtes Web
  5. Arbitre: Une instance d'arbitre pour le niveau de données en miroir

Cette architecture sépare les problèmes et fournit plusieurs niveaux de redondance:

  • Le niveau de données gère les opérations de base de données avec mise en miroir synchrone
  • Le niveau d'application se concentre sur le traitement de la logique métier
  • Le niveau IAM gère la sécurité des API
  • Le niveau de passerelle Web traite les requêtes HTTP/HTTPS

Chaque composant joue un rôle spécifique dans la pile de sécurité:

  1. AWS WAF (pare-feu d'application Web): filtre le trafic malveillant à l'aide d'ensembles de règles qui protègent contre les exploits Web courants, les injections SQL et les scripts intersites (XSS). Il met également en œuvre une liste blanche d'URI pour restreindre l'accès aux seuls chemins d'application légitimes.
  2. AWS CloudFront: Agit comme un réseau de diffusion de contenu (CDN) qui met en cache le contenu statique, réduisant ainsi la surface d'attaque en traitant les demandes à la périphérie. Il fournit également un niveau supplémentaire de protection contre les attaques DDoS.
  3. AWS ALB (Équilibreur de charge d'application): Configuré comme un contrôleur d'entrée Kubernetes, il effectue la terminaison TLS et achemine le trafic vers les services backend appropriés en fonction des chemins d'URL.
  4. InterSystems IAM: Basée sur Kong, cette passerelle API applique l'authentification, l'autorisation, la limitation du débit et la validation des requêtes avant que le trafic n'atteigne l'application.
  5. Passerelle Web: La passerelle Web InterSystems, avec sa configuration renforcée, restreint l'accès à des chemins URI spécifiques et fournit une validation supplémentaire.
  6. Cluster IRIS: La base de données IRIS déployée dans un cluster Kubernetes avec une configuration sécurisée, un chiffrement TLS et des contrôles d'accès basés sur les rôles.

Cette approche à plusieurs niveaux garantit que même si un contrôle de sécurité est contourné, les autres restent en place pour protéger vos applications et vos données.


Niveau 1: Sécurité périmétrique avec AWS WAF et CloudFront

La première ligne de défense de notre architecture se situe au périmètre du réseau, où nous mettons en œuvre AWS WAF et CloudFront pour filtrer le trafic malveillant avant qu'il n'atteigne nos services.

1.1 Mise en œuvre d'AWS WAF

Le pare-feu d'application Web AWS est configuré avec des ensembles de règles personnalisées afin de protéger contre les exploits Web courants et de restreindre l'accès aux chemins URI autorisés uniquement. Voici comment nous l'avons configuré:

# WAF Configuration in Ingress alb.ingress.kubernetes.io/wafv2-acl-arn: arn:aws:wafv2:region-1:ACCOUNT_ID:regional/webacl/app_uri_whitelisting/abcdef123456 

Nos règles WAF sont les suivantes:

  • Liste blanche des chemins URI: Autorisation du trafic uniquement vers les chemins d'application spécifiés, tels que /app/, /csp/broker/, /api/, and /csp/appdata
  • Protection contre les injections SQL: Blocage des requêtes contenant des modèles d'injection SQL
  • Protection XSS: Filtrage des requêtes contenant des charges utiles de type cross-site scripting
  • Regles basées sur les taux: Blocage automatique des adresses IP qui dépassent les seuils de requêtes
  • Règles de limitation géographique: Limitation de l'accès à certaines zones géographiques lorsque cela est nécessaire

En appliquant ces règles à la périphérie, nous empêchons une grande partie du trafic malveillant d'atteindre notre infrastructure d'applications.
 

1.2 Intégration CloudFront

AWS CloudFront fonctionne avec WAF pour fournir des avantages supplémentaires en matière de sécurité:

  • Mise en cache intelligente: le contenu statique est mis en cache à des emplacements périphériques, ce qui réduit la charge sur les services backend et minimise la surface d'attaque
  • Protection contre les attaques DDoS: L'infrastructure distribuée à l'échelle globale de CloudFront aide à absorber les attaques DDoS
  • Application du protocole TLS: Toutes les connexions sont sécurisées à l'aide du protocole TLS 1.2+ et de suites de chiffrement modernes
  • Identité d'accès à l'origine: Garantie que les compartiments S3 hébergeant du contenu statique sont uniquement accessibles via CloudFront

CloudFront est configuré pour transférer des en-têtes spécifiques vers les services backend, garantissant ainsi la préservation des contextes de sécurité tout au long du flux de requêtes:

  • X-Forwarded-For
  • X-Real-IP

Cette configuration permet aux services en aval d'identifier l'adresse IP client d'origine à des fins de limitation du débit et de journalisation, même lorsque les requêtes transitent par plusieurs niveaux.


Niveau 2: Sécurité réseau avec AWS VPC et groupes de sécurité

Le deuxième niveau de notre architecture de sécurité se concentre sur les contrôles au niveau du réseau mis en œuvre via AWS VPC, les groupes de sécurité et les stratégies réseau Kubernetes.

2.1 Conception VPC pour l'isolation

Notre déploiement IRIS s'exécute dans un VPC personnalisé avec les caractéristiques suivantes:

  • Sous-réseaux privés: Tous les pods IRIS et IAM s'exécutent dans des sous-réseaux privés sans accès direct à l'Internet
  • Passerelles NAT: Outbound internet access
  • Plusieurs zones de disponibilité: Les ressources sont réparties sur trois zones de disponibilité pour une haute disponibilité

Cette conception garantit qu'aucun service backend n'est directement exposé à l'Internet, tout le trafic passant par des points d'entrée contrôlés.

2.2 Configuration des groupes de sécurité

Les groupes de sécurité agissent comme des pare-feu virtuels qui contrôlent le trafic entrant et sortant. Notre implémentation comprend plusieurs groupes de sécurité avec des règles rigoureusement définies:

# Groupes de sécurité référencés dans Ingress alb.ingress.kubernetes.io/security-groups: sg-000000000, sg-0100000000, sg-012000000, sg-0130000000  Ces groupes de sécurité mettent en œuvre:
  • Règles d'entrée: N'autorisent le trafic que sur les ports requis (443 pour HTTPS)
  • Restrictions IP source: Limitent l'accès à des blocs CIDR spécifiques pour les interfaces administratives
  • Règles de sortie: Restriction des connexions sortantes aux destinations nécessaires

Ce niveau de contrôle très précis garantit que, même si un conteneur est compromis, sa capacité à communiquer avec d'autres ressources est limitée par les règles du groupe de sécurité.

2.3 Stratégies réseau Kubernetes

Au sein du cluster EKS, nous mettons en œuvre des stratégies réseau Kubernetes afin de contrôler la communication de pod à pod:

apiVersion:networking.k8s.io/v1kind:NetworkPolicymetadata:
  name:allow-iam-webgateway
  namespace:app1spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/component:webgateway
  policyTypes:
    -Ingress
  ingress:
    -ports:
        -protocol:TCP
          port:443

 

Ces stratégies garantissent que:

  • Les pods IRIS n'acceptent que les connexions provenant de sources autorisées (passerelle Web, IAM)
  • Les pods IAM n'acceptent que les connexions provenant du contrôleur Ingress
  • Les pods de passerelle Web n'acceptent que les connexions provenant d'IAM

Cette approche de sécurité réseau à plusieurs niveaux crée des périmètres d'isolation qui contiennent les violations de sécurité potentielles et limitent les mouvements latéraux au sein de l'environnement d'application.


Niveau 3: Sécurité des API avec IAM d'InterSystems

Au cœur de notre architecture de sécurité se trouve IAM d'InterSystems , une solution de gestion des API puissante basée sur Kong. Ce composant fournit des fonctionnalités de sécurité essentielles, notamment l'authentification, l'autorisation, la limitation du débit et la validation des requêtes.

3.1 Aperçu d'IAM d'InterSystems

IAM d'InterSystems sert de passerelle API pour toutes les requêtes adressées aux services IRIS, garantissant que seul le trafic autorisé et légitime atteint votre application. Dans notre implémentation, IAM est déployé en tant que StatefulSet au sein du même cluster Kubernetes que les instances IRIS, ce qui permet une intégration transparente tout en maintenant l'isolation des préoccupations.

La passerelle IAM est configurée avec une terminaison TLS/SSL et n'est exposée que par des points de terminaison sécurisés. Toutes les communications entre IAM et la passerelle Web IRIS sont cryptées, ce qui garantit la confidentialité des données en transit.

3.2 Configuration avancée de la limitation des taux

Afin de vous protéger contre les attaques par déni de service et l'utilisation abusive de l'API, nous avons mis en place une limitation avancée des taux via le rate-limiting-advanced plugind'IAM. Cette configuration utilise Redis comme magasin backend pour suivre les taux de requêtes sur les instances IAM distribuées.

{ "name": "rate-limiting-advanced", "config": { "identifier": "ip", "strategy": "redis", "window_type": "sliding", "limit": [2000, 3000], "window_size": [60, 60], "redis": { "host": "my-release-redis-master.default.svc.cluster.local", "port": 6379, "timeout": 2000, "keepalive_pool_size": 30 }, "error_message": "API rate limit exceeded" } }  

Cette configuration fournit deux niveaux de limitation des taux:

  • Niveau 1: 2,000 requêtes par minute avec une fenêtre glissante
  • Niveau 2: 3,000 requêtes par minute avec une fenêtre glissante

L'approche par fenêtre glissante fournit une limitation des taux plus précise que les fenêtres fixes, empêchant ainsi les pics de trafic aux périmètres des fenêtres. Lorsqu'un client dépasse ces limites, il reçoit un code d'état 429 accompagné d'un message d'erreur personnalisé.

3.3 Gestion sécurisée des sessions

Pour les applications nécessitant des sessions utilisateur, nous avons configuré le plugin de session IAM avec des paramètres sécurisés afin d'empêcher le détournement de session et de maintenir un cycle de vie approprié à la session:

{ "name": "session", "config": { "secret": "REDACTED", "cookie_secure": true, "cookie_same_site": "Strict", "cookie_http_only": true, "idling_timeout": 900, "absolute_timeout": 86400, "rolling_timeout": 14400 } }

Les principales fonctionnalités de sécurité mises en œuvre sont les suivantes:

  • Uniquement des cookies HTTP: Cela empêche JavaScript d'accéder aux cookies de session, ce qui atténue les attaques XSS
  • Indicateur de sécurité: Assure que les cookies ne sont envoyés que via des connexions HTTPS
  • Restriction au même site: empêche les attaques CSRF en limitant l'utilisation des cookies aux requêtes provenant du même site
  • Plusieurs mécanismes de timeout:
    • Timeout d'inactivité (15 minutes): Met fin aux sessions après une période d'inactivité
    • Timeout glissant (4 heurs): Nécessite une réauthentification périodique
    • Timeout absolu (24 heurs): Durée maximale de la session, quelle que soit l'activité

3.4 Validation des requêtes pour la sécurisation des entrées

Afin de nous protéger contre les attaques par injection et les requêtes malformées, nous avons mis en place une validation de requêtes stricte à l'aide du plugin de validation des requêtes IAM. Cela est particulièrement important pour sécuriser le broker CSP, qui est un composant essentiel chargé de gérer la communication client-serveur dans les applications InterSystems.

{ "name": "request-validator", "config": { "version": "kong", "body_schema": [ { "RequestParam": { "type": "integer", "required": true, "between": [1, 10] } }, { "EventType": { "type": "string", "required": true, "match": "^[a-zA-Z0-9$_]{100}$" } }, { "SessionID": { "type": "string", "required": true, "match": "^00b0[a-zA-Z0-9]{40}$" } } ], "verbose_response": true, "allowed_content_types": ["application/x-www-form-urlencoded"] } } 

Cette configuration impose des règles de validation rigoureuses:

  • Les champs de saisie doivent correspondre exactement aux types de données et aux contraintes
  • Les entrées de chaîne doivent correspondre à des modèles d'expressions régulières spécifiques
  • Les types de contenu autorisés sont les seuls acceptés

Le broker CSP est particulièrement sensible, car il sert de canal de communication entre les navigateurs clients et le serveur IRIS. En validant toutes les requêtes au niveau IAM avant qu'elles n'atteignent le broker, nous créons une barrière de sécurité supplémentaire qui protège contre les requêtes malformées ou malveillantes ciblant ce composant critique. Lorsqu'une requête échoue à la validation, l'IAM renvoie une réponse d'erreur détaillée qui aide à identifier le problème de validation sans révéler d'informations sensibles sur vos systèmes backend.

3.5 Configuration d'adresses IP fiables/p>

Pour renforcer encore davantage la sécurité, l'IAM est configuré pour reconnaître les proxys fiables et déterminer correctement les adresses IP des clients:

{ "trusted_ips": [ "10.0.0.0/24", "10.1.0.0/24", "10.0.3.0/24" ], "real_ip_header": "X-Forwarded-For", "real_ip_recursive": "on" }

Cette configuration garantit que:

  • La limitation du taux identifie correctement les adresses IP des clients, même via des proxys
  • Les règles de sécurité utilisant l'identification IP fonctionnent correctement
  • Les journaux d'accès enregistrent les adresses IP réelles des clients plutôt que celles des proxys

En implémentant ces fonctionnalités de sécurité avancées dans InterSystems IAM, nous avons créé un niveau de sécurité API robuste qui complète les mesures de sécurité périmétrique et réseau tout en protégeant les niveaux application et base de données contre le trafic malveillant ou excessif.


Niveau 4 : Sécurité des applications avec renforcement de la passerelle Web

Le quatrième niveau de notre architecture de sécurité se concentre sur le renforcement de la passerelle Web InterSystems, qui sert d'interface entre la passerelle IAM API et la base de données IRIS.

4.1 Configuration de la passerelle Web dans Kubernetes

TLa passerelle Web est déployée dans le cadre de la ressource personnalisée IrisCluster, avec une configuration spécifique axée sur la sécurité:

webgateway:

  image:containers.intersystems.com/intersystems/webgateway-nginx:2023.3
  type:nginx
  replicas:2
  applicationPaths:
    -/csp/app1
    -/csp/app2
    -/app3
    -/csp/app4
    -/app5
    -/csp/bin
  alternativeServers:LoadBalancing
  loginSecret:
    name:iris-webgateway-secret

Cette configuration limite la passerelle Web à la prise en charge de chemins d'accès spécifiques aux applications, ce qui réduit la surface d'attaque en empêchant l'accès aux points de terminaison non autorisés.

4.2 Renforcement de la sécurité de CSP.ini

La configuration CSP.ini de la passerelle Web est renforcée par plusieurs mesures de sécurité:

[SYSTEM]No_Activity_Timeout=480System_Manager=127.0.0.1Maximum_Logged_Request_Size=256KMAX_CONNECTIONS=4096Server_Response_Timeout=60Queued_Request_Timeout=60Default_Server=IRIS[APP_PATH:/app]Alternative_Servers=LoadBalancingAlternative_Server_0=1~~~~~~server-compute-0Response_Size_Notification=ChunkedTransferEncodingandContentLengthKeepAlive=NoActionGZIP_Compression=EnabledGZIP_Exclude_File_Types=jpeggificopnggzzipmp3mp4tiffGZIP_Minimum_File_Size=500

 

Les principales fonctionnalités de sécurité de cette configuration sont les suivantes:

  1. Gestionnaire de système désactivé: L'interface du gestionnaire de système est désactivée, sauf pour localhost
  2. Configuration manuelle uniquement: La configuration automatique est désactivée pour empêcher toute modification non autorisée
  3. Restrictions d'accès aux chemins: Chaque chemin d'application a des paramètres de sécurité spécifiques
  4. Mise en œuvre de l'authentification: AutheEnabled=64 impose l'authentification
  5. Timeout de session: Timeout de session de 15 minutes conformément aux paramètres IAM
  6. Les noms CSP verrouillés: Empêche les attaques transversales en verrouillant les noms CSP

4.3 Configuration avancée de la sécurité Nginx

Notre implémentation utilise une configuration Nginx fortement renforcée pour la passerelle Web, qui fournit plusieurs niveaux de défense:

# Définition d'une liste blanche à l'aide d'une carte

map $request_uri $whitelist_uri {

    default 0;

    "~^/app/.*$" 1;

    "~^/app/.*\.(csp|css|ico|js|png|woff2|ttf|jpg|gif)$" 1;

    "~^/csp/broker/cspxmlhttp.js$" 1;

    "~^/csp/broker/cspbroker.js$" 1;

    "~^/csp/app/.*$" 1;

    "~^/csp/bin/Systems/Module.cxw.*$" 1;

}



# Blocage global d'URI spécifiques
map $request_uri $block_uri {

    default 0;

    "~*%25login" 1;

    "~*%25CSP\.PasswordChange\.cls" 1;

    "~*%25ZEN\.SVGComponent\.svgPage" 1;

}



# Pages d'erreur personnalisées
error_page 403 /403.html;



# Application de la liste blanche d'URI
if ($whitelist_uri = 0) {

    return 403;

}



# Interdirction d'accès aux types de fichiers interdits
location ~* \.(ppt|pptx)$ {

    deny all;

    return 403;

}



# Interdiction d'accès aux URI bloqués
if ($block_uri) {

    return 403;

}



# Journalisation complète for security analysis
log_format security '$real_client_ip - $remote_user [$time_local] '

                   '"$request" $status $body_bytes_sent '

                   '"$http_referer" "$http_user_agent" '

                   '"$http_x_forwarded_for" "$request_body"';

Cette configuration met en œuvre plusieurs commandes de sécurité essentielles:

  1. Liste blanche d'URI: Seuls les chemins explicitement autorisés sont accessibles
  2. Blocage des chemins dangereux: Blocage automatique de l'accès aux points de terminaison dangereux
  3. Blocage des types de fichiers à risque: Cela empêche l'accès aux types de fichiers potentiellement dangereux
  4. Journalisation sécurisée: Journalisation détaillée de toutes les requêtes à des fins d'analyse
  5. Extraction de l'adresse IP client: Extraction correcte des adresses IP réelles des clients à partir des en-têtes X-Forwarded-For
  6. Pages d'erreur personnalisées: Réponses d'erreur standardisées qui ne divulguent pas d'informations sur le système

De plus, nous mettons en œuvre des en-têtes de sécurité renforcés et des limites de requêtes:

# Les en-têtes de sécurité

add_header X-XSS-Protection "1; mode=block" always;

add_header X-Content-Type-Options "nosniff" always;

add_header X-Frame-Options "SAMEORIGIN" always;

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

# Limites de taille des tampons et des requêtes

client_max_body_size 50M;

client_body_buffer_size 128k;

client_header_buffer_size 1k;

large_client_header_buffers 4 4k;

# Sécurité SSL/TLS

ssl_protocols TLSv1.2 TLSv1.3;

ssl_prefer_server_ciphers on;

ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';

Ces paramètres protègent contre les menaces suivantes:

  • Script inter-sites (XSS)
  • Attaques par confusion de types MIME
  • Clickjacking
  • Attaques par rétrogradation SSL
  • Tentatives de débordement de mémoire tampon
  • Attaques à charge utile importante

4.4 Configuration TLS

La passerelle Web est configurée pour utiliser des paramètres TLS modernes, garantissant ainsi une communication sécurisée:

tls:     

  webgateway:  secret:    secretName:iris-tls-secret

Notre implémentation TLS garantit:

  • Seuls les protocoles TLS 1.2+ sont autorisés
  • Des suites de chiffrement robustes avec confidentialité persistante sont renforcées
  • Les certificats sont correctement validés
  • La gestion des sessions est sécurisée

En mettant en œuvre ce dispositif complet de renforcement de la sécurité de la passerelle Web, nous créons un niveau de sécurité robuste qui protège la base de données IRIS contre les accès non autorisés et les vulnérabilités courantes des applications Web.

Niveau 5: Sécurité des bases de données dans les clusters IRIS

Le dernier niveau de notre architecture de sécurité vise à sécuriser la base de données IRIS elle-même, afin de garantir la protection des données même si tous les niveaux précédents sont compromis.

5.1 Configuration sécurisée d'IrisCluster avec l'Opérateur Kubernetes d'InterSystems (IKO)

Le cluster IRIS est déployé à l'aide de la définition de ressource personnalisée IrisCluster fournie par l'opérateur InterSystems Kubernetes (IKO), avec une configuration axée sur la sécurité:

apiVersion:intersystems.com/v1alpha1kind:IrisClustermetadata:
  name:example-app
  namespace:example-namespacespec:
  tls:     

    common:
      secret:
        secretName:iris-tls-secret
    mirror:
      secret:
        secretName:iris-tls-secret
    ecp:
      secret:
        secretName:iris-tls-secret
  topology:     

    data:
      image:containers.intersystems.com/intersystems/iris:2023.3
      preferredZones:
        -region-1a
        -region-1b
      mirrored:true
      podTemplate:
        spec:
          securityContext:
            runAsUser:51773  # irisowner
            runAsGroup:51773
            fsGroup:51773
      irisDatabases:
        -name:appdata
          mirrored:true
          ecp:true
      irisNamespaces:
        -name:APP
          routines:appdata
          globals:appdata
    compute:
      image:containers.intersystems.com/intersystems/iris:2023.3
      replicas:1
      compatibilityVersion:"2023.3.0"
      webgateway:
        image:containers.intersystems.com/intersystems/webgateway-nginx:2023.3
        replicas:1
        type:nginx
        applicationPaths:
          -/csp/sys
          -/csp/bin
          -/api/app
          -/app
    iam:
      image:containers.intersystems.com/intersystems/iam:3.4
    arbiter:
      image:containers.intersystems.com/intersystems/arbiter:2023.3
      preferredZones:
        -region-1c

Notre déploiement IKO comprend plusieurs fonctionnalités de sécurité essentielles:

  1. Cryptage TLS: Toutes les communications entre les instances IRIS sont cryptées à l'aide du protocole TLS
  2. Mise en miroir de la base de données: Haute disponibilité avec mise en miroir synchronisée garantissant l'intégrité des données
  3. Exécution non root: IRIS s'exécute en tant qu'utilisateur irisowner sans privilèges
  4. Sécurité ECP: Les connexions Enterprise Cache Protocol sont sécurisées avec TLS
  5. Répartition par zone: Les composants sont répartis entre plusieurs zones de disponibilité pour assurer la tolérance aux pannes
  6. Isolation des ressources: Séparation nette entre les données et les nœuds de calcul
  7. Espaces de noms IRIS: Espaces de noms correctement configurés et mappés à des bases de données sécurisées
  8. Nœud arbitre: Nœud arbitre dédié dans une zone de disponibilité distincte

5.2 Paramètres de sécurité de la base de données IRIS

Au sein de la base de données IRIS, les meilleures pratiques en matière de sécurité comprennent la mise en œuvre de plusieurs paramètres de sécurité clés:

  1. Authentification déléguée: Configuration IRIS pour utiliser des mécanismes d'authentification externes pour la gestion centralisée des identités
  2. Journalisation des audits: Activation d'un audit complet pour les événements liés à la sécurité, tels que les connexions, les modifications de configuration et l'augmentation des privilèges
  3. Sécurité du système: application des paramètres de sécurité au niveau du système conformément aux normes de l'industrie

Ces pratiques garantissent une gestion centralisée de l'authentification, la journalisation de toutes les activités liées à la sécurité à des fins d'analyse et la conformité du système aux normes de configuration sécurisées.

5.3 Sécurité basée sur les ressources IRIS

IRIS fournit un cadre de sécurité robuste basé sur les ressources et les rôles qui permet un contrôle d'accès très précis. Ce cadre peut être utilisé pour mettre en œuvre le principe du moindre privilège, en accordant aux utilisateurs et aux services uniquement les autorisations dont ils ont besoin pour exercer leurs fonctions.

Modèle de sécurité basé sur les ressources

Le modèle de sécurité basé sur les ressources d'IRIS comprend:

  1. Ressources: Objets sécurisés tels que les bases de données, les services, les applications et les opérations systèmes
  2. Autorisations: Différents niveaux d'accès aux ressources (lecture, écriture, utilisation)
  3. Rôles: Ensembles d'autorisations sur les ressources qui peuvent être attribués aux utilisateurs
  4. Utilisateurs: Comptes auxquels des rôles sont attribués et qui peuvent se connecter au système

Ce modèle permet aux administrateurs de sécurité de créer une structure de sécurité qui restreint l'accès en fonction des tâches et des besoins. Par exemple:

  • Les administrateurs de bases de données peuvent avoir un accès complet aux ressources de la base de données, mais un accès limité aux ressources de l'application
  • Les utilisateurs de l'application peuvent avoir accès uniquement à certaines fonctions spécifiques de l'application
  • Les comptes de service pour les intégrations peuvent avoir des autorisations restreintes adaptées à leurs besoins spécifiques

Documentation InterSystems

La mise en œuvre de la sécurité basée sur les rôles dans IRIS est bien documentée dans la documentation officielle d'InterSystems:

En tirant parti du cadre de sécurité intégré d'IRIS, les organisations peuvent créer un modèle de sécurité respectant le principe du moindre privilège, ce qui réduit considérablement le risque d'accès non autorisé ou d'augmentation des privilèges.

5.4 Cryptage des données

Les fichiers de la base de données IRIS sont cryptés à l'aide du cryptage AWS EBS au repos avec des clés KMS gérées par l'utilisateur:

kind:StorageClassapiVersion:storage.k8s.io/v1metadata:  name:iris-ssd-storageclassprovisioner:kubernetes.io/aws-ebsparameters:  type:gp3  encrypted:"true"volumeBindingMode:WaitForFirstConsumerallowVolumeExpansion:true

Le cluster EKS est configuré pour utiliser des volumes EBS chiffrés pour tout le stockage persistant, garantissant ainsi que les données inactives sont protégées par un chiffrement AES-256.

5.5 Sauvegarde et reprise après incident

Pour protéger contre la perte de données et garantir la continuité des activités de nos clients, notre architecture met en œuvre les mesures suivantes:

  1. Mise en miroir des journaux: Les journaux IRIS sont stockés sur des volumes distincts et mis en miroir
  2. Sauvegardes automatisées: Sauvegardes régulières vers des buckets S3 cryptés
  3. Réplication AZ croisée: Les données critiques sont répliquées vers une zone de disponibilité (AZ) AWS secondaire

Cette approche garantit que même en cas de panne catastrophique ou d'incident de sécurité, les données peuvent être récupérées avec un minimum de pertes.

Guide de mise en œuvre

Pour mettre en œuvre cette architecture de sécurité à plusieurs niveaux pour vos propres déploiements IRIS sur AWS, suivez ces étapes générales:

Étape 1 : Configuration de l'infrastructure AWS

  1. Créez un VPC avec des sous-réseaux privés et publics dans plusieurs zones de disponibilité
  2. Configurez des passerelles NAT pour la connectivité sortante à partir des sous-réseaux privés
  3. Créez des groupes de sécurité avec des règles d'entrée et de sortie appropriées
  4. Déployez un cluster EKS dans des sous-réseaux privés

Étape 2: Configuration des services de sécurité AWS

  1. Créez une liste de contrôle d'accès Web AWS WAF avec les ensembles de règles appropriés
  2. Configurez la distribution CloudFront avec l'association WAF
  3. Configurez AWS ALB pour Kubernetes Ingress

Étape 3 : Déployez l'IAM d'InterSystems

  1. Créez les informations secrètes Kubernetes nécessaires pour les certificats et les informations d'identification
  2. Déployez l'IAM StatefulSet à l'aide de l'opérateur IrisCluster
  3. Configurez les plugins de sécurité IAM (limitation du taux, gestion des sessions, validation des requêtes)

Étape 4 : Déploiement et sécurisation du cluster IRIS

  1. Créez une ressource personnalisée IrisCluster avec des configurations de sécurité
  2. Configurez TLS pour toutes les communications
  3. Déployez la passerelle Web avec une configuration renforcée
  4. Configurez la mise en miroir de la base de données et la sécurité ECP

Étape 5 : Mise en œuvre de la surveillance et de la journalisation

  1. Configurez la journalisation centralisée avec ElasticSearch
  2. Configurez la surveillance de la sécurité avec Datadog
  3. Mettez en œuvre des alertes pour les événements de sécurité
  4. Activez la journalisation d'audit IRIS

Surveillance et réponse aux incidents

Une architecture de sécurité robuste doit inclure des capacités de surveillance continue et de réponse aux incidents. Notre mise en œuvre comprend:

6.1 Surveillance de la sécurité

L'architecture comprend une surveillance complète à l'aide de Datadog et ElasticSearch:

  1. Analyse des journaux en temps réel: Tous les composants envoient leurs journaux à un cluster ElasticSearch centralisé
  2. Tableaux de bord de sécurité: Les tableaux de bord Datadog visualisent les mesures de sécurité et les anomalies
  3. Alertes automatisées: Des alertes sont générées en cas d'activités suspectes ou de violations de la sécurité

6.2 Réponse aux incidents

Un processus défini de réponse aux incidents garantit une réaction rapide aux événements de sécurité:

  1. Détection: Détection automatisée des incidents de sécurité grâce à la surveillance
  2. Classification: Les incidents sont classés par gravité et par type
  3. Contention: procédures visant à contenir les incidents, y compris les réponses automatisées
  4. Éradication: Mesures visant à éliminer la menace et à rétablir la sécurité
  5. Récupération: Procédures de restauration du fonctionnement normal
  6. Leçons apprises: Analyse post-incident pour améliorer le niveau de sécurité

Considérations relatives aux performances

La mise en œuvre de plusieurs niveaux de sécurité peut avoir un impact sur les performances. Notre architecture répond à ce problème grâce aux éléments suivants:

7.1 Stratégies de mise en cache

  1. Mise en cache CloudFront: Le contenu statique est mis en cache à la périphérie
  2. Mise en cache de la passerelle API: IAM implémente la mise en cache des réponses pour les points de terminaison appropriés
  3. Mise en cache de la passerelle Web: Les pages CSP sont mises en cache lorsque cela est possible

7.2 Équilibrage de charge

  1. Déploiement multizone de disponibilité (AZ): Les services sont répartis entre plusieurs zones de disponibilité
  2. Mise à l'échelle horizontale: Les composants peuvent être mis à l'échelle horizontalement en fonction de la charge
  3. Paramètres d'affinité: L'anti-affinité des pods garantit une distribution adéquate

7.3 Mesures de performance

Au cours de la mise en œuvre, nous avons observé les impacts suivants sur les performances:

  1. Latence: La latence moyenne des requêtes n'a augmenté que de 20 à 30 ms malgré toutes les niveaux de sécurité
  2. Débit: Le système peut traiter plus de 2 000 demandes par seconde avec toutes les mesures de sécurité
  3. Utilisation des ressources: Les composants de sécurité supplémentaires ont augmenté l'utilisation du processeur d'environ 15%

Ces mesures démontrent qu'une architecture de sécurité robuste peut être mise en œuvre sans dégradation significative des performances.

Conclusion

L'architecture de sécurité à plusieurs niveaux décrite dans cet article fournit une protection complète pour les déploiements InterSystems IRIS sur AWS. En mettant en œuvre des contrôles de sécurité à chaque niveau, du périmètre du réseau à la base de données, nous créons une stratégie de défense en profondeur qui réduit considérablement le risque d'attaques réussies.

Les principaux avantages de cette approche sont les suivants:

  1. Protection complète: Plusieurs niveaux fournissent une protection contre un large éventail de menaces
  2. Défense en profondeur: Si une mesure de sécurité échoue, les autres restent en place
  3. Évolutivité: l'architecture est scalable horizontalement pour gérer une charge accrue
  4. Simplicité de gestion: L'approche "infrastructure en tant que code" rend les contrôles de sécurité reproductibles et versionnables
  5. Conformité: L'architecture aide à respecter les exigences réglementaires en matière de protection des données

En tirant parti des services de sécurité AWS, d'IAM d'InterSystems et des configurations IRIS sécurisées, les organisations peuvent créer des applications sécurisées et hautement performantes tout en protégeant les données sensibles contre les menaces émergentes.

Références

  1. Documentation InterSystems: Guide de sécurité IRIS
  2. Meilleures pratiques en matière de sécurité AWS: Pilier de la sécurité AWS
  3. Sécurité Kubernetes: Guide des meilleures pratiques EKS
  4. Sécurité API OWASP: Les 10 principaux risques liés à la sécurité API
  5. Registre de conteneurs InterSystems: containers.intersystems.com
0
0 17
Article Lorenzo Scalese · Juin 18, 2025 5m read

Le bon vieux temps

La classe %Library.DynamicObject existe dans IRIS depuis bien avant que IRIS ne devienne IRIS. Si vous l'utilisez depuis l'époque de Cache, vous souhaiterez peut-être vous familiariser avec certaines de ses modifications.

Dans Cache 2018, la méthode %Get n'avait qu'un seul argument. Il s'agissait de la clé permettant de récupérer les données dans le JSON. Ainsi, si votre objet JSON s'appelait myObj, cela ressemblerait à ceci:

{
    “mybool”:true,
    “mynum”:1234,
    “mystring”:”Hello World!”
}

L'exploitation de myObj.%Get(“mybool”) renverrait 1, myObj.%Get(“mynum”) renverrait 1234 et myObj.%Get("mystring") renverrait la chaîne "Hello World!" 

La définition de ces paramètres, en revanche, nécessitait un peu plus de travail. Par exemple, l'attribution d'une propriété JSON à 0 pouvait signifier le nombre 0, une valeur booléenne signifiant faux ou une chaîne littérale "0". C'est pourquoi la méthode %Set avait toujours un troisième argument facultatif. Pour créer l'objet JSON mentionné ci-dessus, nous pouvions utiliser le code suivant:

set myObj = ##class(%Library.DynamicObject).%New()
do myObj.%Set(“mybool”,1,”boolean”)
do myObj.%Set(“mynum”,1234,”number”)
do myObj.%Set(“mystring”,”Hello World!”,”string”)

Cependant, dans ce cas, nous pourrions également omettre le troisième argument des deux derniers. Ainsi, 1234 serait reconnu comme un nombre, car il n'est pas entre guillemets, tandis que "Hello World!" serait identifié comme une chaîne, car il est entre guillemets. Si nous voulions ajouter la valeur 1234 à l'objet en tant que chaîne, nous pourrions changer la chaîne en nombre. Nous pourrions également spécifier le type "null". Dans ce cas, la valeur doit être "". En pratique, cependant, nous ajoutons souvent ces valeurs à partir de variables dans notre code ObjectScript. Pour cette raison, il peut être préférable de spécifier cet argument, juste au cas où la variable serait une chaîne ou un nombre, afin de garantir que notre JSON arrive à destination correctement encodé.

Comment j'ai appris à ne plus m'inquiéter à propos de <MAXSTRING> et aimer JSON

Comme l'a dit un jour le sage Billy Joel, ""Le bon vieux temps n'était pas toujours bon, demain n'est pas aussi mauvais qu'il n'y paraît." La liste des types pour %Set s'est allongée, et la méthode %Get a acquis deux nouveaux arguments. Ce qui est crucial, c'est qu'elles prennent toutes deux en charge le type "stream". Si vous avez déjà traité de grandes quantités de données JSON, vous avez probablement déjà rencontré une erreur lorsque les données contenues dans le JSON dépassaient la longueur maximale autorisée pour une chaîne dans IRIS. La nouvelle méthode %Get vous permet de spécifier deux arguments supplémentaires, une valeur par défaut et un type. Votre ancien code continue toutefois de fonctionner, car ces deux arguments sont facultatifs et, s'ils sont omis, les méthodes fonctionnent exactement comme en 2018. Si rien n'est trouvé pour la clé donnée, la valeur par défaut est renvoyée. La fonction type fonctionne de manière similaire à l'argument type de la méthode %Set. Vous pouvez également spécifier le type de données que vous récupérez. Prenons l'exemple suivant du bloc try/catch:

try{
    Set mydata = myObj.%Get(“mydata”,”N/A”)
}
catch ex{
    if ex.Name = “<MAXSTRING>”{
        set mydata = myObj.%Get(“mydata”,,”stream”)
    }
}

Il tentera de définir mydata à la valeur située à l'intérieur de "mydata" dans l'objet JSON. Si cet élément n'existe pas, il renverra "N/A" à la place. Si cet élément est trop long pour une chaîne, le système lèvera une exception vers le bloc catch. Nous devons vérifier le nom de cette exception, car si une exception différente s'est produite, il ne serait pas logique d'essayer d'obtenir les données sous forme de flux. Vous pouvez en savoir plus sur la gestion des exceptions ici. Si la valeur est , nous spécifions que nous voulons récupérer mydata sous forme de flux. La récupération des données sous forme de flux renvoie un objet de la classe %Stream.DynamicCharacter. Cela ne déclenche jamais d'exception , mais peut générer une exception si la limite de mémoire du processus est dépassée.

Si vous suivez l'approche décrite ci-dessus, vous ne saurez pas si mydata dans le code est une chaîne ou un flux. Cela signifie que vous devrez suivre le code similaire à celui ci-dessous:

if$ISOBJECT(mydata){
    //Traitement des flux ici
}
else{
    //Traitement des chaînes ici
}

Vous pouvez également utiliser l'option stream chaque fois afin de vous assurer que vous avez toujours un flux à votre disposition. Cependant, cela entraînerait une utilisation inutile des ressources et alourdirait votre code.

Une autre option consiste à ajouter un flux à un objet dynamique à l'aide de %Set. Consultez l'exemple suivant:

set mystream = ##class(%Stream.FileBinary).%New()
do mystream.LinkToFile(“/path/to/your/file”)
do myObj.%Set(“mydata”,mystream,”stream”)

Les données de votre fichier seront désormais enregistrées dans le champ mydata de votre objet dynamique.

%Set et %Get encodent et décodent également les chaînes à l'aide de l'encodage Base64. 

Gardez toujours à l'esprit que l'encodage Base64 est un encodage et non un cryptage ! Il n'y a pas de clés secrètes ni de mots de passe pour décoder votre message, et il est facilement réversible. Par conséquent, vous devez toujours utiliser un protocole crypté, tel que TLS ou HTTPS, pour la transmission ! Base64 est utilisé pour transmettre des caractères non ASCII de manière à ce que les systèmes ASCII puissent les recevoir et les transmettre.

Maintenant que cette remarque importante est faite, nous pouvons enfin voir comment cela fonctionne. Si nous apportons une petite modification à l'exemple de code précédent, le contenu du flux de fichiers sera encodé en Base64.

set mystream = ##class(%Stream.FileBinary).%New()
do mystream.LinkToFile(“/path/to/your/file”)
do myObj.%Set(“mydata”,mystream,”stream>base64”)

D'autre part, si les données du fichier étaient déjà encodées en Base64 et que nous voulions les convertir en données décodées, il suffirait de changer un seul caractère.

set mystream = ##class(%Stream.FileBinary).%New()
do mystream.LinkToFile(“/path/to/your/file”)
do myObj.%Set(“mydata”,mystream,”stream<base64”)

Les signes " supérieur à" ou "inférieur à" indiquent toujours la direction dans laquelle la conversion a lieu. Si nous convertissons un flux non codé en une chaîne Base64, le signe pointera vers Base64. Si nous convertissons un flux codé en Base64 en un flux non codé, le signe pointera de Base64 vers le flux. La même fonctionnalité existe pour les chaînes lorsque string>base64 et string

set something = myObj.%Get(“something”,”NA”,”string>base64”)

Si l'élément "quelque chose" existe, il sera renvoyé sous sa forme encodée en Base64. Cependant, s'il n'existe pas, "NA" sera renvoyé sans être encodé.

Il existe une restriction concernant l'option d'encodage Base64. Seuls les caractères dont le code est compris entre 0 et 255 peuvent être encodés en Base64. Les codes de caractères supérieurs à 255 entraîneront une exception <WIDE CHAR>. FPar exemple, la ligne suivante provoquera une telle exception:

set mychar = $C(256)
do myobj.%Set(“mychar”,mychar,”string>base64”)

Alors, j'ai entendu dire que vous aimiez JSON . . .

Parfois, il y a du JSON à l'intérieur de votre JSON. La manière par défaut de gérer cette situation est généralement celle que vous choisiriez. Cependant, une autre option a été ajoutée à l'argument de type pour traiter un cas d'utilisation différent. Il s'agit du type "json". Regardez l'objet JSON suivant:

{
    “mystring”:”Hello World!”,
    “mynumber”:1234,
    “myjson”:{
        “subitem1”:”Hello Mars!”,
        “subitem2”:”Hello Stars!”
    }
}

En règle générale, lorsque vous rencontrez ce problème, vous devez utiliser la méthode %Get avec la clé « myjson » pour obtenir un objet dynamique. Voici un exemple:

set myjson = myobj.%Get(“myjson”)
write myjson.%Get(“subitem1”)

La ligne ci-dessus écrirait "Hello Mars!". C'est le cas le plus courant dans cette situation. Cependant, dans certains cas, vous préférerez peut-être obtenir le JSON réel contenu dans cet élément sous forme de chaîne. Dans ce cas, vous pouvez procéder comme suit:

set myjson = myobj.%Get(“myjson”,,”json”)
write myjson

La chaîne JSON sera écrite exactement telle qu'elle est:

{“subitem1”:”Hello Mars!”,”subitem2”:”Hello Stars!”}

Cela peut s'avérer utile dans les cas où nous voulons transmettre le JSON tel quel à un autre processus. Notez que, contrairement à tous les autres types nouveaux, celui-ci n'est pris en charge que pour la méthode %Get, et non pour la méthode %Set.

Hourra, hourra, les massives!

Jusqu'à présent, nous avons discuté de ces nouveaux objets dans le contexte de la classe %Library.DynamicObject, mais ils sont également pris en charge pour la classe %Library.DynamicArray. Dans cette classe, %Set et %Get prennent en charge les mêmes arguments de type que dans la classe %Library.DynamicObject. La classe de tableaux dynamiques dispose toutefois d'une méthode %Push supplémentaire. Elle prend en charge les mêmes types que %Set, à l'exception du type JSON.

Sans plus attendre, c'est probablement le bon moment pour revoir vos anciens codes et implémenter ces changements à votre avantage!

0
0 35
Article Guillaume Rongier · Juin 12, 2025 4m read

   

L'incroyable Iris-nator est arrivé en ville.

Il lit dans vos pensées : en vous posant quelques questions, il devine le personnage auquel vous pensez.

Oserez-vous vous y risquer?

Certains d'entre vous connaissent peut-être le jeu Akinator, où un génie devine le personnage auquel vous pensez en vous posant des questions et en vous laissant répondre par "oui" ou "non".

Pas d'IA qui analyse vos réseaux sociaux, pas de microphones qui vous écoutent... Alors comment ça marche?

Le secret réside dans un algorithme simple et dans le grand nombre de personnes qui jouent et alimentent la base de données.

Comment ça marche?

Définissons un terme: Nœud.

Un nœud peut être une question ou le nom d'un personnage.

Si c'est une question, elle aura deux réponses : Oui ou Non.

 

Attribuons-lui maintenant une valeur.

À la question, nous attribuerons l'ID 1, à la réponse affirmative, nous attribuerons l'ID 2 et à la réponse négative, l'ID 3.

Imaginons maintenant que les réponses affirmative et négative renvoient chacune une autre question, avec les caractères correspondants pour "oui" et "non".

 

Nous pouvons voir une tendance entre les questions et les réponses.

Les réponses affirmatives sont deux fois l'identifiant de la question, et les réponses négatives sont deux fois l'identifiant de la question plus un.

Ensuite, si nous avons le nœud n, le nœud suivant à afficher sera le nœud n*2 si la réponse est "oui" ou le nœud (n*2)+1 si la réponse est "non".

Prenons un exemple:

 

Supposons que je pense à Snoopy et que la question soit "Votre personnage est-il fictif?". La réponse "oui" nous indiquerait que le personnage auquel nous avons pensé est "Superman", mais ce n'est pas correct.

Comment transformer notre réponse en une question qui nous mène à Snoopy?

Nous avons besoin d'une caractéristique qui nous différencie de Superman, dans ce cas, nous demanderons "Votre personnage est-il un chien?". La réponse affirmative serait alors "Snoopy" et la réponse négative "Superman".

Cette nouvelle question remplacera l'ID du nœud "Superman", le personnage "Snoopy" aura le double du nœud de la nouvelle question et le personnage "Superman" aura le double du nœud de la nouvelle question plus un.

 

De cette façon, si nous créons beaucoup de questions et de réponses, notre Iris-nator sera capable de deviner n'importe quel personnage auquel vous avez pensé.

Fonctionnement d'Iris-nator?

Créez une table contenant les informations relatives aux nœuds:

Class Irisnator.Data.Nodes Extends%Persistent
{

/// NodeId (ID du nœud)Property NodeId As%Numeric;/// Texte du nœudProperty Text As%String(MAXLEN = "");/// Type de nœud (0 = texte, 1 = question)Property Question As%Boolean [ InitialExpression = 0 ];/// Verbe de la questionProperty Verb As%String(MAXLEN = ""); }

Remarque: Pourquoi y a-t-il un champ appelé "verbe"? Parce que la question s'affiche sous la forme {verbe} votre personnage {texte}? Il faut donc savoir quel est le verbe (est, avait, fait, etc.)

Le front-end est créé avec Angular19. Pour communiquer avec IRIS, j'ai créé plusieurs méthodes API:

GET localhost:52773/irisnator/api/node/:nodeId

Renvoie les informations relatives au nœud, y compris le NodId pour les réponses Oui et Non

{
    "nodeId": 1,
    "text": "a woman",
    "verb": "is",
    "question": true,
    "nodeYes": 2,
    "nodeNo": 3
}

GET localhost:52773/irisnator/api/score/:top

Renvoie le meilleur score. Ce meilleur score correspond au nombre de fois où un caractère a été atteint.

{
    "score": [
        {
            "characterName": "Superman",
            "score": 8
        },
        {
            "characterName": "Maddona",
            "score": 3
        },
        {
            "characterName": "Snoopy",
            "score": 1
        }
    ]
}

POST localhost:52773/irisnator/api/node

Lorsque Iris-nator ne parvient pas à deviner votre personnage, nous remplissons un formulaire avec les données du nouveau personnage et la question à poser pour le différencier du personnage auquel il correspondait.

Ensuite, déplacez le personnage en cours vers la réponse "non" et attribuez l'identifiant à la nouvelle question.

{
    "nodeId": 507,
    "newCharacter": "Snoopy",
    "oldCharacter": "Superman",
    "text": "a dog",
    "verb": "is"
}

De plus, Snoopy sera ajouté à la liste des personnages échoués.

POST localhost:52773/irisnator/api/score

Cette méthode définit le score d'un personnage, qu'il ait réussi ou non.

{
    "characterName": "Snoopy",
    "success": true
}

 

Découvrez le fonctionnement de l'application dans la vidéo suivante, profitez-en bien!!!

<iframe allowfullscreen="" frameborder="0" height="360" src="https://www.youtube.com/embed/v5GsiXJDgC8" width="640"></iframe>

0
0 34
Article Lorenzo Scalese · Juin 10, 2025 11m read

Introduction

Les performances des bases de données sont devenues essentielles à la réussite des environnements applicatifs modernes. Il est donc indispensable d'identifier et d'optimiser les requêtes SQL les plus exigeantes en ressources afin de garantir une expérience utilisateur fluide et la stabilité des applications. 

Cet article présente une approche rapide pour analyser les statistiques d'exécution des requêtes SQL sur une instance InterSystems IRIS afin d'identifier les domaines à optimiser au sein d'une macro-application.

Au lieu de nous concentrer sur la surveillance en temps réel, nous allons mettre en place un système qui collecte et analyse les statistiques précalculées par IRIS une fois par heure.  Cette approche, bien qu'elle ne permette pas de surveillance instantanée, offre un excellent compromis entre la richesse des données disponibles et la simplicité de mise en œuvre. 

Nous utiliserons Grafana pour la visualisation et l'analyse des données, InfluxDB pour le stockage des séries chronologiques et Telegraf pour la collecte des métriques.  Ces outils, reconnus pour leur puissance et leur flexibilité, nous permettront d'obtenir un aperçu clair et exploitable.

Plus précisément, nous détaillerons la configuration de Telegraf pour récupérer les statistiques. Nous configurerons également l'intégration avec InfluxDB pour le stockage et l'analyse des données, et créerons des tableaux de bord personnalisés dans Grafana. Cela nous aidera à identifier rapidement les requêtes nécessitant une attention particulière.

Pour faciliter l'orchestration et le déploiement de ces différents composants, nous utiliserons Docker.

logos.png

Conditions préalables

Avant de commencer, assurez-vous d'avoir les éléments suivant:

  • Git: Git est nécessaire pour cloner le référentiel du projet contenant les fichiers de configuration et les scripts.
  • Docker ou Docker Desktop: Docker peut être utilisé pour conteneuriser les applications InfluxDB, Telegraf et Grafana, ce qui facilite leur déploiement et leur gestion.
  • Instance InterSystems IRIS:Au moins la version 2022.1, idéalement 2023.1 ou supérieure, avec le package sql-stats-api installé.  Ce package est essentiel pour exposer les statistiques SQL IRIS et permettre à Telegraf de les collecter. [Lien vers OpenExchange]

Bien que nos fichiers docker-compose incluent une instance IRIS, celle-ci ne contiendra aucune donnée statistique SQL, car elle vient d'être créée et démarrée. Elle ne constituera donc pas un choix pratique pour tester le système. C'est pourquoi nous vous recommandons vivement de disposer d'une autre instance IRIS "active" (celle qui contient l'historique des requêtes SQL) afin de pouvoir visualiser des données réelles et tester l'outil d'analyse.

À propos des statistiques

IRIS collecte des statistiques d'exécution des requêtes SQL à une granularité horaire et quotidienne. Les statistiques horaires identifient les variations de performances tout au long de la journée, tandis que les statistiques quotidiennes fournissent une vue d'ensemble de l'activité de la base de données.

Vous trouverez ci-dessous les données que nous collectons pour chaque requête SQL:

  • Nombre d'exécutions: indique le nombre de fois où la requête a été exécutée.
  • Durée totale d'exécution: mesure la durée totale d'exécution de la requête.
  • Variance des temps d'exécution: utilisée pour identifier les variations de performances et les problèmes ponctuels.
  • Nombre total de lignes renvoyées (RowCount): disponible pour IRIS 2023.1 et versions ultérieures, cette métrique indique le nombre total de lignes renvoyées par la requête. Elle peut vous aider à identifier les requêtes exigeantes en ressources.
  • Nombre total de commandes exécutées: également disponible pour IRIS 2023.1 et versions ultérieures, cette métrique facilite une analyse plus détaillée de l'activité de la base de données et identifie les requêtes qui pourraient être optimisées en réduisant le nombre d'opérations.

Ces informations sont accessibles via les tables suivantes:

  • INFORMATION_SCHEMA.STATEMENT_DAILY_STATS
  • INFORMATION_SCHEMA.STATEMENT_HOURLY_STATS

Ces tables sont disponibles depuis IRIS 2022.1. Vous trouverez ci-dessous un exemple de requête SQL permettant de récupérer des statistiques:

SELECT ds.* 
FROM INFORMATION_SCHEMA.STATEMENT_DAILY_STATS ds
INNERJOIN INFORMATION_SCHEMA.STATEMENTS st On ds.Statement = st.Hash


SELECTDATEADD('hh',"Hour",$PIECE(hs."Day",'||',2)) As DateTime, hs.*
FROM INFORMATION_SCHEMA.STATEMENT_HOURLY_STATS hs
INNERJOIN INFORMATION_SCHEMA.STATEMENTS st On $PIECE(hs."Day",'||',1) = st.Hash

Pour les versions plus anciennes que IRIS 2022.1, je recommande vivement l'article de David Loveluck, qui explique comment récupérer des statistiques similaires.

Architecture

Le projet repose sur l'interaction de quatre composants clés : IRIS, Grafana, InfluxDB et Telegraf. Le diagramme ci-dessous illustre l'architecture globale du système et le flux de données entre les différents composants:

archi.png

  • InterSystems IRIS: il s'agit de l'instance que nous utiliserons pour récupérer les statistiques.
  • Package sql-stats-api: ce package ObjectScript expose les données statistiques IRIS via l'API REST. Il offre deux formats de sortie : JSON pour une utilisation générale et Line Protocol, un format optimisé pour l'ingestion rapide de données de séries chronologiques dans InfluxDB.
  • Telegraf: il s'agit d'un agent de collecte de métriques qui fournit le lien entre IRIS et InfluxDB. Dans ce projet, nous utiliserons deux instances de Telegraf:
    • un agent interroge périodiquement l'API REST IRIS pour récupérer les statistiques SQL en temps réel.
    • Un autre agent fonctionne en mode "scan de répertoire". Il surveille un répertoire contenant les fichiers stockés et les transmet à InfluxDB, ce qui permet d'intégrer les données inaccessibles via l'API REST.
  • InfluxDB:  cette base de données de séries chronologiques stocke et gère les statistiques SQL collectées par Telegraf, car son architecture est optimisée pour ce type de données. InfluxDB offre également une intégration native avec Grafana, ce qui facilite la visualisation et l'analyse des données. Nous avons préféré InfluxDB à Prometheus, car ce dernier est davantage axé sur la surveillance en temps réel et n'est pas bien adapté au stockage de données agrégées, telles que les sommes ou les moyennes horaire ou journalière, qui sont essentielles pour notre analyse.
  • Grafana: il s'agit d'un outil de visualisation qui permet de créer des tableaux de bord personnalisés et interactifs pour analyser les performances SQL. Il récupère les données d'InfluxDB et offre une variété de graphiques et de widgets pour visualiser les statistiques de manière claire et exploitable.

Installation

Commencez par cloner le référentiel:

git clone https://github.com/lscalese/iris-sql-dashboard.git
cd irisiris-sql-dashboard

Configuration de l'environnement

Ce projet utilise Docker pour orchestrer Grafana, InfluxDB, Telegraf et IRIS. Pour des raisons de sécurité, les informations sensibles telles que les clés API et les mots de passe sont stockées dans un fichier .env.

Créez le fichier .env en utilisant l'exemple fourni ci-dessous:

cp .env.example .env

Éditez le fichier .env pour configurer les variables:

Configuration des variables

  • TZ: fuseau horaire. Il est recommandé de modifier cette variable en fonction de votre fuseau horaire afin de garantir l'exactitude de l'horodatage des données.
  • DOCKER_INFLUXDB_INIT_PASSWORD: mot de passe administrateur permettant d'accéder à InfluxDB.
  • IRIS_USER: il s'agit d'un utilisateur IRIS de l'instance Docker IRIS (_system par défaut).
  • IRIS_PASSWORD : Il s'agit du mot de passe de l'instance IRIS Docker (SYS par défaut).

Les clés API permettent les connexions suivantes:

  • GRAFANA_INFLUX_API_KEY : Grafana <-> InfluxDB.
  • TELEGRAF_INFLUX_API_KEY : Telegraf <-> InfluxDB.

Génération de clés API

Pour des raisons de sécurité, InfluxDB nécessite des clés API pour l'authentification et l'autorisation.  Ces clés sont utilisées pour identifier et autoriser divers composants (Telegraf, Grafana) à accéder à Influx DB.

Le script init-influxdb.sh, inclus dans le référentiel, facilite la génération de ces clés.  Il sera exécuté automatiquement lors du premier démarrage du conteneur infxludb2:

docker compose up -d influxdb2

Après quelques secondes, le fichier .env sera mis à jour avec vos clés API générées.

Remarque: cette étape ne doit être effectuée que lors du premier démarrage du conteneur.

Vérifiez si vous avez accès à l'interface d'administration InfluxDB via l'URL http://localhost:8086/

Connectez-vous avec le nom d'utilisateur "admin" et le mot de passe spécifiés dans la variable d'environnement "DOCKER_INFLUXDB_INIT_PASSWORD" dans le fichier ".env". Lorsque vous naviguez dans "Load Data >> Buckets”, vous devriez découvrir un bucket "IRIS_SQL_STATS" préconfiguré.   

influxdb-2.png
En parcourant "Load Data >> API Tokens", vous devriez trouver nos deux clés API : "Grafana_IRIS_SQL_STATS" et "Telegraf_IRIS_SQL_STATS":

influxdb-3.png

L'environnement est prêt maintenant, et nous pouvons passer à l'étape suivante!

Démarrage

L'environnement étant configuré et les clés API générées, vous pouvez enfin lancer l'ensemble de conteneurs. Pour ce faire, exécutez la commande suivante dans le répertoire racine du projet:

docker compose up -d

Cette commande lancera en arrière-plan tous les services définis dans le fichier docker-compose.yml : InfluxDB, Telegraf, Grafana et l'instance IRIS.

Tableau de bord Grafana

Grafana est désormais disponible à l'adresse http://localhost:3000.

Connexion à Grafana

Ouvrez votre navigateur Web et rendez-vous à l'adresse http://localhost:3000. Le nom d'utilisateur et le mot de passe par défaut sont admin/admin. Cependant, vous serez invité à modifier le mot de passe lors de votre première connexion.

grafana-login.png

Vérification de la source de données InfluxDB

La source de données InfluxDB est préconfigurée dans Grafana. Il vous suffit de vérifier son bon fonctionnement.

Accédez à “Connections > Data sources (sources de données)”.

grafana-ds.png

Vous devriez voir une source de données nommée “influxdb”.Cliquez dessus pour la modifier.

Cliquez ensuite sur “Save & Test”. Le message “Datasource is working. 1 bucket found” (La source de données fonctionne. 1 bucket trouvé) devrait maintenant s'afficher à l'écran.

grafana-datasources-influxdb.png

Exploration des tableaux de bord

À ce stade, vous avez vérifié que la communication entre Grafana et InfluxDB est établie, ce qui signifie que vous pouvez explorer les tableaux de bord prédéfinis.

Passez à “Dashboards” (tableaux de bord).

grafana-dashboard-list.png

Vous trouverez deux tableaux de bord prédéfinis:

  • InfluxDB - SQL Stats: ce tableau de bord affiche des statistiques générales sur l'exécution des requêtes SQL, par exemple le nombre d'exécutions, le temps total d'exécution et la variance du temps d'exécution.
  • InfluxDB - SQL Stats Details: ce tableau de bord fournit des informations plus détaillées sur chaque requête SQL, par exemple le nombre total de lignes renvoyées ou de commandes exécutées.

Pourquoi les tableaux de bord sont vides

Si vous ouvrez les tableaux de bord, vous verrez qu'ils sont vides.  Cela s'explique par le fait que notre agent Telegraf est actuellement connecté à l'instance IRIS fournie dans le référentiel Docker, dont les tables ne contiennent aucune donnée statistique. Les statistiques SQL ne sont collectées que si l'instance IRIS est active et conserve un historique des requêtes SQL.

Dans la section suivante, nous allons voir comment injecter des données dans l'instance IRIS afin d'afficher les statistiques dans Grafana.

 

Telegraf

Le système de surveillance utilise deux agents Telegraf ayant des rôles spécifiques:

  • telegraf-iris.conf:cet agent collecte des données en temps réel à partir d'une instance IRIS active. Il interroge l'API REST IRIS pour récupérer des statistiques SQL afin de les envoyer à InfluxDB.
  • telegraf-directory-scan.conf: cet agent intègre les données historiques stockées dans des fichiers. Il surveille le répertoire ./telegraf/in/, lit les fichiers contenant des statistiques SQL et les envoie à InfluxDB.

Pour collecter des données en temps réel, il faut connecter Telegraf à une instance IRIS active sur laquelle le package sql-stats-api est installé.  Ce package expose les statistiques SQL via une API REST, ce qui permet à Telegraf d'y accéder.

Configuration de telegraf-iris.conf

Pour connecter Telegraf à votre instance IRIS, vous devez modifier le fichier ./telegraf/config/telegraf-iris.conf. Vous trouverez ci-dessous un exemple de configuration:

[[inputs.http]]  ## Une ou plusieurs URL à partir desquelles lire les métriques formatées  urls = [    "http://iris:52773/csp/sqlstats/api/daily",    "http://iris:52773/csp/sqlstats/api/hourly"  ]  ## Méthode HTTP  method = "GET"
  ## En-têtes HTTP facultatifs  headers = {"Accept" = "text/plain"}  ## Informations d'identification pour l'authentification HTTP de base (facultatif)  username = "${IRIS_USER}"  password = "${IRIS_PASSWORD}"  data_format = "influx"

Assurez-vous que${IRIS_USER} et ${IRIS_PASSWORD} sont correctement définis dans votre dossier .env file.
Remarque: Vous pouvez copier le fichier et modifier les paramètres pour connecter Telegraf à plusieurs instances IRIS.

Redémarrage de Telegraf:

Après avoir modifié le fichier de configuration, il est nécessaire de redémarrer le conteneur Telegraf pour que les modifications prennent effet:

docker compose up -d telegraf --force-recreate

Récupération des données historiques

Pour récupérer les statistiques SQL historiques, utilisez la méthode ObjectScript CreateInfluxFile sur votre instance IRIS:

; Adaptez le chemin à vos besoinsSet sc = ##class(dc.sqlstats.services.SQLStats).CreateInfluxFile("/home/irisowner/dev/influxdb-lines.txt",,1)

Ce script enregistre l'historique des statistiques SQL dans des fichiers texte dont la longueur maximale est de 10 000 lignes par fichier. Vous pouvez ensuite placer ces fichiers dans le répertoire ./telegraf/in/ afin de les traiter et de les injecter dans InfluxDB.

Vérification de l'injection des données

Vous pouvez vérifier que les données ont été correctement injectées dans InfluxDB à l'aide de l'interface Web. Accédez à "Data Explorer" (Explorateur de données) et vérifiez:

influxdb-explorer.png

Visualisation des données dans Grafana

Une fois les données injectées, vous pouvez les afficher dans vos tableaux de bord Grafana fournis.

grafana-dashboard-daily-stats.png

grafana-dashboard-daily-details.png

Nous sommes arrivés à la fin de notre article. J'espère qu'il vous a été utile et qu'il vous avez appris à configurer facilement un système de surveillance et d'analyse des statistiques SQL sur vos instances IRIS.

Comme vous l'avez peut-être constaté, cet article a mis l'accent sur les aspects pratiques de la configuration et de l'utilisation de divers outils. Nous n'avons pas étudié en détail le fonctionnement interne d'InfluxDB, du format Line Protocol ou du langage Flux Query, ni examiné la multitude de plugins disponibles pour Telegraf.

Ces sujets, aussi fascinants soient-ils, nécessiteraient un article beaucoup plus long.  Je vous encourage vivement à consulter la documentation officielle d'InfluxDB Get started with InfluxDB (Débuter avec InfluxDB) et Telegraf Plugin Directory (Répertoire des plugins) pour approfondir vos connaissances et découvrir toutes les possibilités offertes par ces outils.

N'hésitez pas à partager vos expériences dans les commentaires.

Merci d'avoir lu cet article, et à bientôt!

0
0 53
InterSystems officiel Adeline Icard · Juin 10, 2025

InterSystems a publié de nouvelles mises à jour afin de corriger un défaut affectant les versions antérieures les plus récentes (2025.1.0, 2024.1.4, 2023.1.6 et 2022.1.7), pour les gammes de produits prises en charge suivantes :

  • InterSystems IRIS
  • InterSystems IRIS for Health
  • HealthShare Health Connect

Ce problème pouvait entraîner des erreurs <PROTECT> inattendues ou des anomalies d'accès lors de l'utilisation de fonctionnalités telles que :

0
0 33
Article Andre Larsen Barbosa · Juin 6, 2025 3m read

image

Tel un coup de grâce, sans laisser aucune chance à l'adversaire, Kubernetes, plateforme open source, offre un univers de possibilités grâce à sa disponibilité (c'est-à-dire la facilité d'accès au support, aux services et aux outils). Cette plateforme permet de gérer les tâches et les services dans des conteneurs, ce qui simplifie grandement la configuration et l'automatisation de ces processus.

Justifions l'image du titre et donnons à l'outil en question le nom « correct » : InterSystems Kubernetes Operator.

Le principe est simple : vous choisissez les services et définissez les règles du jeu (en faisant ici encore référence à Knockout), et tout est fourni de la manière la plus transparente et la plus efficace possible, que ce soit pour l'installation, la réparation ou la restauration éventuelle, lorsque les exigences prédéfinies ne sont pas respectées.

Mais qu'est-ce qui différencie IKO des autres opérateurs ? En tant qu'extension de l'API Kubernetes (appelons-la K8s pour faire court), le composant personnalisé IrisCluster permet de déployer un cluster IRIS verrouillé, un cluster Caché distribué ou même une instance anonyme. Le tout sur les plateformes Kubernetes les plus diverses. Enfin, il intègre des fonctionnalités de gestion de cluster InterSystems, permettant d'automatiser certaines tâches en ajoutant des nœuds, ce qui auparavant ne pouvait être réalisé que manuellement.

Tout cela est bien beau, cela fait référence à un sport ou à un jeu, mais pourquoi en ai-je besoin ? La réponse est relativement simple. Je n'ai pas besoin d'IrisCluster pour intégrer InterSystems IRIS à K8s. Cependant, comme K8s est une application autonome, il serait nécessaire de créer les définitions et les éventuels scripts pour configurer ces instances IRIS. IKO automatise ainsi ce processus, facilitant ainsi la maintenance. L'utilisation de conteneurs est un excellent moyen de regrouper ces activités.

Mais, profitant de cette opportunité, savez-vous ce qu'est un conteneur ? Un indice : ce n'est pas qu'un jeu de société.

image

La réponse est bien plus liée au « transport » d'un package, car il empaquete et isole les applications et les services afin qu'ils puissent être exécutés séparément du reste. Cela facilite le « transport » d'un environnement à un autre, selon les besoins.

En exploitant la vaste documentation d'InterSystems, vous trouverez ci-dessous le lien vers l'installation d'IKO et les étapes de configuration et d'ajustement qui s'ensuivent.

https://docs.intersystems.com/components/csp/docbook/DocBook.UI.Page.cls...

Pour que personne ne s'interroge sur le surnom K8s, le nom Kubernetes vient du grec et signifie ni plus ni moins que pilote ou timonier, autrement dit, celui qui dirige. Le nombre de caractères entre les lettres « K » et « S » est de 8. D'où le nom « K8s ».

0
0 38
Article Developer Community Admin · Juin 2, 2025 6m read

Le déplacement d'InterSystems IRIS et d'InterSystems IRIS for Health d'un environnement sur site vers le cloud offre de nombreux avantages aux Fournisseurs d'applications et de solutions. Ces avantages comprennent notamment la simplification des opérations, l'accès à des ressources flexibles et une résilience accrue. Les entreprises n'ont plus à se soucier des contraintes physiques et des dépenses liées à la maintenance d'une infrastructure sur site, telles que les besoins en énergie et en espace, ainsi que le coût élevé du matériel informatique.

L'un des avantages les plus convaincants est la possibilité d'accélérer la vitesse de commercialisation. En supprimant la charge liée à la maintenance de l'infrastructure, les environnements cloud permettent des cycles de développement et de déploiement plus rapides, ce qui permet aux entreprises de réagir rapidement aux demandes et aux opportunités du marché. Les coûts opérationnels sont également réduits, car les entreprises peuvent sadapter leurs ressources à la hausse ou à la baisse en fonction de leurs besoins réels, ce qui se traduit par une utilisation plus efficace du capital. De plus, la migration vers le cloud peut contribuer à réduire l'empreinte carbone en optimisant la consommation d'énergie grâce à une infrastructure cloud partagée.

Le déplacement vers le cloud peut impliquer des changements importants. Les entreprises peuvent bénéficier d'une orientation plus opérationnelle, en gérant et en optimisant en permanence les ressources cloud. Cette évolution peut nécessiter des changements dans les modèles commerciaux, une redéfinition des marges et des stratégies d'expansion ou de réduction des activités. Bien qu'ils nécessitent des investissements plus importants, ces changements peuvent améliorer la flexibilité et l'avantage compétitif sur le marché.

Choix architecturaux dans la migration vers le cloud

Lorsqu'elles envisagent la migration vers le cloud la plus simple, les entreprises doivent choisir un ou plusieurs services (AWS, Azure, Google ou autre) pour déplacer une application existante sur site vers l'un des clouds publics. Elles sont alors confrontées à un choix architectural important : migrer entièrement vers le cloud ou créer un cluster hybride sur site et dans le cloud. InterSystems IRIS et InterSystems IRIS for Health prennent tous deux entièrement en charge ces deux options. Un cluster hybride miroite l'instance sur site vers le cloud de manière asynchrone. Cette alternative peut être utile dans des situations telles que celles où l'OLTP continue de fonctionner sur site, mais où l'instance cloud fournit une prise en charge pour l'analyse, la création de rapports et d'autres opérations en lecture seule.

Options de migration

Chaque choix architectural pour la migration vers le cloud a ses avantages et ses limites,  il est donc essentiel pour les entreprises d'évaluer leurs besoins et leurs objectifs spécifiques lors de la planification d'une stratégie cloud. La première étape consiste à choisir entre une migration complète vers le cloud ou une configuration hybride.

Choix migratoireNombre de  déploiements InterSystems IRIS après la migrationCaractéristiques
Lift & Shift: migration complète vers le cloud1Configuration sur site locale transférée vers une architecture cloud
Cluster hybride : sur site plus copie miroir dans le cloud ("cluster étendu")2Cluster sur site mis en miroir vers une copie cloud en lecture seule mise à jour de manière asynchrone

Le choix Lift & Shift permet de profiter des avantages du cloud tout en conservant la propriété d'une seule copie d'InterSystems IRIS.

Le choix Hybrid combine la stabilité et la familiarité des systèmes sur site avec la flexibilité et l'évolutivité du cloud.

Consultez notre documentation en ligne pour plus d'informations sur la mise en miroir Mirroring.

Architecture multitenant ou monotenant avec InterSystems IRIS

Bien que la migration ne nécessite aucune modification de votre méthode de mutualisation, le cloud offre de puissantes options d'évolutivité et de facturation. Pour cette raison, vous souhaiterez peut-être réévaluer votre modèle de mutualisation. Pour toutes nos offres, lors du déploiement d'applications InterSystems IRIS dans le cloud, les entreprises peuvent choisir entre les architectures suivantes pour plusieurs utilisateurs:

  • Mono-tenant: Déploiements multiples ; un pour chacun de vos utilisateurs.
  • Multi-tenant: Plusieurs utilisateurs sur un seul déploiement.

Chaque architecture présente des avantages et des inconvénients distincts. Cela est particulièrement important pour les fournisseurs d'applications et de solutions qui ont développé des solutions à l'aide de la technologie InterSystems IRIS, que ce soit pour un grand nombre d'utilisateurs, dans le cadre d'une expansion majeure ou pour l'hébergement de données sensibles ou réglementées.

Évolutivité des ressources et des opérations

  • Multi-tenant: L'évolutivité d'un environnement multi-tenant implique l'ajout de ressources à une instance partagée unique pour chaque utilisateur (tenant), ce qui peut s'avérer plus rentable et plus simple à gérer. Cependant, les performances d'un tenant peuvent affecter celles des autres si les ressources allouées sont insuffisantes, ce qui peut entraîner des contention de ressources.
  • Mono-tenant: Faire évoluer un environnement mono-tenant signifie provisionner davantage de ressources pour chaque utilisateur individuellement. Bien que cela offre des performances plus prévisibles, le besoin d'infrastructure supplémentaire et les frais généraux liés à la gestion peuvent rendre ce choix plus complexe à faire évoluer.

Isolation des données

  • Multi-tenant: Dans une configuration multi-tenant, plusieurs tenants partagent la même instance de l'application et de la base de données. L'isolation des données est assurée par un partitionnement au niveau logiciel, qui garantit la sécurité et la séparation des données de chaque tenant. Cette approche peut être efficace en termes d'utilisation des ressources, mais elle peut nécessiter des mesures de sécurité rigoureuses pour prévenir les violations de données.
  • Mono-tenant: Avec une architecture mono-tenant, chaque utilisateur dispose d'une instance distincte de l'application et de la base de données. Cette configuration fournit un niveau plus élevé d'isolation des données, car les données de chaque tenant résident dans un environnement distinct. Ce choix peut être plus sûr et plus facile à gérer, facilitant la conformité aux réglementations en matière de protection des données. 

Méthodes de migration

Plusieurs approches sont disponibles pour migrer votre solution InterSystems IRIS de vos sites vers le service cloud de votre choix.

Les deux méthodes les plus courantes sont décrites ci-dessous. Elles commencent toutes deux par la même étape, qui consiste à miroiter un déploiement existant vers le cloud, mais elles divergent ensuite.

Choisir entre miroir et lift-and-shift

Les méthodes du miroir et du lift-and-shift commencent toutes deux par la copie de votre InterSystems IRIS existant depuis votre environnement sur site vers une plateforme cloud. Une fois la copie cloud synchronisée avec l'instance sur site, vous choisissez définitivement où se termine le chemin de migration:

  • Miroir: vous continuez à utiliser l'instance sur site comme instance principale et l'instance cloud comme instance de sauvegarde et pour les opérations en lecture seule, telles que l'analyse et l'apprentissage automatique. L'instance cloud est asynchrone, mais mise à jour régulièrement.
  • Lift-and-shift: Une fois l'instance principale sur site et les instances secondaires basées sur le cloud synchronisées, les opérations de "basculement" s'effectuent depuis l'instance sur site vers la copie dans le cloud, qui devient alors l'instance principale pour toutes les opérations (et pas seulement en lecture seule). À ce stade, le déploiement sur site peut être archivé sous forme de sauvegarde instantanée.

La mise en miroir de votre instance InterSystems IRIS locale existante vers le cloud est le moyen le plus courant, le plus résilient et le plus simple de migrer votre déploiement sur site. Pour plus d'informations, consultez le Guide de migration du serveur Server Migration Guide dans notre documentation en ligne.


Plus d'articles sur le sujet:

Source: Déplacement d'InterSystems IRIS vers le cloud

0
0 38
Article Sylvain Guilbaud · Mai 30, 2025 3m read

Kong fournit en open source un outil de gestion de ses configurations (écrit en Go), appelé decK (pour declarative Kong)

  • Vérifiez que decK reconnaît votre installation Kong Gateway via deck gateway ping
deck gateway ping   
Successfully connected to Kong!
Kong version:  3.4.3.11
  • Exporter la configuration de Kong Gateway dans un fichier "kong.yaml" via deck gateway dump
deck gateway dump -o kong.yaml
  • Après avoir modifié les adresses IP dans le fichier kong.yaml, afficher les différences via deck gateway diff
0
0 25
Article Iryna Mykhailova · Mai 29, 2025 8m read

J'ai un nouveau projet qui consiste à stocker des informations provenant de réponses REST dans une base de données IRIS. Il me faudra synchroniser les informations provenant d'au moins deux douzaines de points de terminaison REST distincts, ce qui implique la création de presque autant de classes ObjectScript pour stocker les résultats de ces points de terminaison.

Puis-je utiliser ChatGPT pour créer ces classes? La réponse est "Oui", ce qui est génial puisqu'il s'agit de ma première tentative d'utiliser l'IA générative pour quelque chose d'utile. En effet, générer des images de girafes mangeant de la soupe devenait un peu vieux….

Voici ce que j'ai fait:

  • Obtenez un exemple de sortie d'appel REST JSON en utilisant "curl" pour interroger le point de terminaison.
  • Visitez ChatGPT (InterSystems fournit une licence à l'échelle de l'entreprise pour les employés)
  • Accédez au dialogue suivant avec ChatGPT.

J'ai placé la demande suivante dans la fenêtre de message de ChatGPT:

Moi: Générer une classe ObjectScript qui contiendra les données du JSON suivant:

J'ai appuyé sur "Return" avant d'entrer le JSON et ChatGPT m'a donc dirigé comme suit:

ChatGPT: Veuillez fournir la structure JSON pour laquelle vous souhaitez que je génère la classe ObjectScript. Si vous avez un exemple d'objet JSON, collez-le ici et je créerai pour vous la classe ObjectScript InterSystems correspondante.

J'ai saisi ce qui suit dans la fenêtre de message:

{
  "id": 335818632,
  "appId": 113,
  "appName": "Batch",
  "contentId": 182455380233,
  "subject": "Test Subject",
  "name": "Test email campaign name",
  "counters": {
    "processed": 3910,
    "deferred": 86,
    "unsubscribed": 17,
    "statuschange": 17,
    "bounce": 153,
    "mta_dropped": 8,
    "dropped": 299,
    "delivered": 3749,
    "sent": 3903,
    "click": 16,
    "open": 323
  },
  "lastProcessingFinishedAt": 1733232499000,
  "lastProcessingStartedAt": 1733232303000,
  "lastProcessingStateChangeAt": 1733232499000,
  "numIncluded": 4201,
  "processingState": "DONE",
  "scheduledAt": 1733232300000,
  "type": "BATCH_EMAIL"
}

Réponse de ChatGPT:

Voici la classe ObjectScript InterSystems qui correspond à la structure JSON fournie:

Class MyNamespace.MyJSONData Extends (%Persistent, %JSON.Adaptor)
{
Property id As%Integer;Property appId As%Integer;Property appName As%String;Property contentId As%Integer;Property subject As%String;Property name As%String;Property counters As MyNamespace.Counters;Property lastProcessingFinishedAt As%BigInt;Property lastProcessingStartedAt As%BigInt;Property lastProcessingStateChangeAt As%BigInt;Property numIncluded As%Integer;Property processingState As%String;Property scheduledAt As%BigInt;Property type As%String;ClassMethod%OnJSONImport(jsonObject As%Object, instance As MyNamespace.MyJSONData) As%Status
{
    Quit ..%JSONImport(jsonObject, .instance)
}
}

Class MyNamespace.Counters Extends (%SerialObject, %JSON.Adaptor)
{
Property processed As%Integer;Property deferred As%Integer;Property unsubscribed As%Integer;Property statuschange As%Integer;Property bounce As%Integer;Property mta_dropped As%Integer;Property dropped As%Integer;Property delivered As%Integer;Property sent As%Integer;Property click As%Integer;PropertyopenAs%Integer;
}

Avec une explication:

Ce code est un bon départ, mais j'aimerais qu'il s'intègre dans mon paquetage nommé “MyPkg” et que la classe porte le nom “EmaiCampaign”. De plus, grâce à mes connaissances en NI, je sais que les valeurs qui ont généré les propriétés “%BigInt” sont en fait des horaires Linux et que les propriétés devraient être %Library.PosixTime”.

Je fais la demande suivante (je ne sais pas trop pourquoi je dis "s'il vous plaît" à une machine;  je suppose que mes parents ont fait du bon travail):

Moi: Pouvons-nous recréer la classe, s'il vous plaît, en renommant le paquetage " MyPkg" et la classe "EmailCampaign"? De plus, veuillez changer les types de propriétés de %BigInt à %Library.PosixTime.

Reponse de ChatGPT:

Voici la classe ObjectScript mise à jour avec le nom de paquetage et le nom de classe spécifiés, et les propriétés d'horodatage mises à jour pour l'utilisation de %Library.PosixTime:

Class MyPkg.EmailCampaign Extends (%Persistent, %JSON.Adaptor)
{
Property id As%Integer;Property appId As%Integer;Property appName As%String;Property contentId As%Integer;Property subject As%String;Property name As%String;Property counters As MyPkg.Counters;Property lastProcessingFinishedAt As%Library.PosixTime;Property lastProcessingStartedAt As%Library.PosixTime;Property lastProcessingStateChangeAt As%Library.PosixTime;Property numIncluded As%Integer;Property processingState As%String;Property scheduledAt As%Library.PosixTime;Property type As%String;ClassMethod%OnJSONImport(jsonObject As%Object, instance As MyPkg.EmailCampaign) As%Status
{
    Quit ..%JSONImport(jsonObject, .instance)
}
}

Class MyPkg.Counters Extends (%SerialObject, %JSON.Adaptor)
{
Property processed As%Integer;Property deferred As%Integer;Property unsubscribed As%Integer;Property statuschange As%Integer;Property bounce As%Integer;Property mta_dropped As%Integer;Property dropped As%Integer;Property delivered As%Integer;Property sent As%Integer;Property click As%Integer;PropertyopenAs%Integer;
}

Avec une explication suivante:

Après avoir copié le code "tel quel" dans VSCode, des problèmes de syntaxe avec les accolades ont été mis en évidence. Les classes ObjectScript ne permettent pas de définir des classes internes.

Demander à ChatGPT de résoudre le problème des « accolades » en faisant de la classe interne MyPkg.Counters une classe séparée est une opération impossible “no-op”; un humain devra déplacer cette classe dans un autre fichier. ChatGPT a renommé cette classe après la demande suivante:

Moi: La classe telle qu'elle est écrite ne compile pas. Pouvons-nous déplacer la classe interne nommée MyPkg.Counters de la classe principale vers sa propre classe et la renommer en MyPkg.CampaignCounters?

Reponse de ChatGPT:

Voici le code ObjectScript mis à jour avec la classe MyPkg.CampaignCounters déplacée comme sa propre classe:

Class MyPkg.EmailCampaign Extends (%Persistent, %JSON.Adaptor)
{
Property id As%Integer;Property appId As%Integer;Property appName As%String;Property contentId As%Integer;Property subject As%String;Property name As%String;Property counters As MyPkg.CampaignCounters;Property lastProcessingFinishedAt As%Library.PosixTime;Property lastProcessingStartedAt As%Library.PosixTime;Property lastProcessingStateChangeAt As%Library.PosixTime;Property numIncluded As%Integer;Property processingState As%String;Property scheduledAt As%Library.PosixTime;Property type As%String;ClassMethod%OnJSONImport(jsonObject As%Object, instance As MyPkg.EmailCampaign) As%Status
{
    Quit ..%JSONImport(jsonObject, .instance)
}
}

Class MyPkg.CampaignCounters Extends (%SerialObject, %JSON.Adaptor)
{
Property processed As%Integer;Property deferred As%Integer;Property unsubscribed As%Integer;Property statuschange As%Integer;Property bounce As%Integer;Property mta_dropped As%Integer;Property dropped As%Integer;Property delivered As%Integer;Property sent As%Integer;Property click As%Integer;PropertyopenAs%Integer;
}

Après avoir collé ce qui précède dans VSCode et l'avoir compilé, le compilateur a signalé que le type nommé "%Object" n'existe pas dans ObjectScript. v %JSONImport() de %JSON.Adaptor est flexible:

“L'argument d'entrée est soit JSON en tant que chaîne ou flux, soit une sous-classe de %DynamicAbstractObject.

Après avoir supprimé la propriété "As %Object" pour le premier paramètre de %OnJSONImport() dans la première classe et avoir séparé les deux classes dans des fichiers distincts, la classe MyPkg.EmailCampaign s'est compilée avec succès. Cependant, la classe MyPkg.CampaignCounters ne s'est pas compilée ; ChatGPT ne sait pas (pour l'instant ?) que l'underscore est un caractère spécial en ObjectScript (l'opérateur de concaténation de chaînes de caractères).  

Essayons de le lui enseigner.

Moi: Le caractère underscore "_" est un caractère spécial dans ObjectScript. Veuillez changer les propriétés dont le nom contient un underscore en camel case et supprimer l'underscore.

Reponse de ChatGPT:

Voici le code mis à jour avec les propriétés qui avaient des underscores dans leurs noms convertis en camel case:

Class MyPkg.EmailCampaign Extends (%Persistent, %JSON.Adaptor)
{
Property id As%Integer;Property appId As%Integer;Property appName As%String;Property contentId As%Integer;Property subject As%String;Property name As%String;Property counters As MyPkg.CampaignCounters;Property lastProcessingFinishedAt As%Library.PosixTime;Property lastProcessingStartedAt As%Library.PosixTime;Property lastProcessingStateChangeAt As%Library.PosixTime;Property numIncluded As%Integer;Property processingState As%String;Property scheduledAt As%Library.PosixTime;Property type As%String;ClassMethod%OnJSONImport(jsonObject As%Object, instance As MyPkg.EmailCampaign) As%Status
{
    Quit ..%JSONImport(jsonObject, .instance)
}
}

Class MyPkg.CampaignCounters Extends (%SerialObject, %JSON.Adaptor)
{
Property processed As%Integer;Property deferred As%Integer;Property unsubscribed As%Integer;Property statusChange As%Integer;Property bounce As%Integer;Property mtaDropped As%Integer;Property dropped As%Integer;Property delivered As%Integer;Property sent As%Integer;Property click As%Integer;PropertyopenAs%Integer;
}

Avec une explication suivante:

ChatGPT s'est surpassé et a changé une autre propriété, nommée avec deux mots distincts, en camel case également (statuschange); je garde ce changement puisque d'autres propriétés nommées de la même manière dans la classe principale sont toutes en camel case.

Avec le dernier code généré dans deux fichiers séparés (et en supprimant la définition "As %Object" dans la définition de la méthode %OnJSONImport()), tout le code se compile avec succès.

Ces classes générées sont un excellent point de départ pour ce dont j'ai besoin et je répéterai le processus pour les autres sources de données REST de ce projet, ce qui me permettra d'éviter de nombreuses saisies inutiles.

0
0 27
Question Anthony Decorte · Mai 13, 2025

Bonjour,

J'ai rencontré un problème lors du déploiement. Quand je déploie en utilisant la classe Ens.Deployment.Deploy, je ne reçois plus les logs dans le terminal. Cependant, le déploiement s'est bien passé, je le vois dans l'historique sur le portail.

Cela fonctionne sur notre environnement mais pas sur celui du client.

Set tSC = ##class(Ens.Deployment.Deploy).DeployCode(chemin_"GESL_SVCCLI_DEPLOY_CPT-243_V4_0.xml","SVCCLI.ProdClient",1,chemin_"GESL_SVCCLI_DEPLOY_CPT-243_V4_0_rb.xml","L",chemin_"GESL_SVCCLI_DEPLOY_CPT-243_V4_0.log",1,1)

Merci 🙂

3
0 41
InterSystems officiel Adeline Icard · Mai 22, 2025

Nous publions une version intermédiaire pour InterSystems IRIS, IRIS for Health et Health Connect 2025.1 (version 2025.1.0.225.1) afin de résoudre un problème d'interopérabilité critique affectant les utilisateurs utilisant des hôtes métier compatibles SDS.

Quel est le problème ?

0
0 21
Article Sylvain Guilbaud · Mai 19, 2025 3m read

Bonjour à la communauté,

Exploitez tout le potentiel d'InterSystems IRIS et accompagnez votre équipe dans son intégration grâce à la gamme complète de ressources de formation InterSystems, disponibles en ligne et en présentiel, adaptées à chaque rôle de votre organisation. Les développeurs, administrateurs système, analystes de données et intégrateurs peuvent rapidement se familiariser avec la solution.

Ressources d'intégration pour chaque rôle

Développeurs

0
0 54
Article Lorenzo Scalese · Mai 15, 2025 10m read

Introduction

MonLBL est un outil permettant d'analyser des performances d'exécution de code ObjectScript ligne par ligne. codemonitor.MonLBL est un wrapper reposant sur le package %Monitor.System.LineByLine d'InterSystems IRIS pour collecter des métriques précises sur l'exécution de routines, classes ou CSP.

Le wrapper et tous les exemples présentés dans cet article sont disponibles dans le repository GitHub suivant : iris-monlbl-example

Fonctionnalités

L'utilitaire permet de collecter plusieurs types de métriques :

  • RtnLine : Nombre d'exécutions de la ligne
  • GloRef : Nombre de références globales générées par la ligne
  • Time : Temps d'exécution de la ligne
  • TotalTime : Temps total d'exécution incluant les sous-routines appelées

Le tout exporté dans des fichiers CSV.

En plus des métriques par ligne, dc.codemonitor.MonLBL collecte des statistiques globales :

  • Temps d'exécution total
  • Nombre total de lignes exécutées
  • Nombre total de références globales
  • Temps CPU système et utilisateur :
    • Le temps CPU utilisateur correspond au temps passé par le processeur à exécuter le code de l'application
    • Le temps CPU système correspond au temps passé par le processeur à exécuter des opérations du système d'exploitation (appels système, gestion mémoire, I/O)
  • Temps de lecture disque

Prérequis

Pour pouvoir monitorer du code avec MonLBL :

  1. Disposez de la classe dc.codemonitor.MonLBL (disponible ici)
  2. Les routines ou classes à analyser doivent être compilées avec les flags "ck"

⚠️ Mise en garde importante

L'utilisation du monitoring ligne par ligne a un impact sur les performances du serveur. Il est important de respecter les recommandations suivantes :

  • N'utilisez cet outil que sur un ensemble limité de code et de processus (idéalement de l'exécution ponctuel dans un terminal)
  • Évitez son utilisation sur un serveur de production
  • Utilisez de préférence cet outil dans un environnement de développement ou de test

Ces précautions sont essentielles pour éviter des problèmes de performance qui pourraient affecter les utilisateurs ou les systèmes en production. Sachez que le code monitoré s'exécute environ 15-20% plus lentement que s'il ne l'est pas.

Utilisation

Exemple basique

// Création d'une instance de MonLBL
Set mon = ##class(dc.codemonitor.MonLBL).%New()

// Définition des routines à monitorer
Set mon.routines = $ListBuild("User.MaClasse.1")

// Démarrage du monitoring
Do mon.startMonitoring()

// Code à analyser...
// ...

// Arrêt du monitoring et génération des résultats
Do mon.stopMonitoring()

Note: Le monitoring démarré ici n'est valable que pour le processus courant.
Les autres processus qui exécuteraient le même code ne seront pas pris en compte dans les mesures.

Options de configuration

Le wrapper offre plusieurs options configurables :

  • directory : Répertoire où seront exportés les fichiers CSV (par défaut le répertoire Temp d'IRIS)
  • autoCompile : Recompile automatiquement les routines avec les flags "ck" si nécessaire
  • metrics : Liste personnalisable des métriques à collecter
  • decimalPointIsComma : Utilise la virgule comme séparateur décimal pour une meilleure compatibilité avec Excel
  • metricsEnabled : Active ou désactive la collecte des métriques ligne par ligne

Exemple d'utilisation avancée

Voici un exemple plus complet (disponible dans la classe dc.codemonitor.Example) :

ClassMethod MonitorGenerateNumber(parameters As %DynamicObject) As %Status
{
    Set sc = $$$OK
    Try {
        // Affichage des paramètres reçus
        Write "* Parameters :", !
        Set formatter = ##class(%JSON.Formatter).%New()
        Do formatter.Format(parameters)
        Write !
        
        // Création et configuration du moniteur
        Set monitor = ##class(dc.codemonitor.MonLBL).%New()
        
        // ATTENTION : en environnement de production, définissez autoCompile à $$$NO
        // et compilez manuellement le code à monitorer
        Set monitor.autoCompile = $$$YES
        Set monitor.metricsEnabled = $$$YES
        Set monitor.directory = ##class(%File).NormalizeDirectory(##class(%SYS.System).TempDirectory())
        Set monitor.decimalPointIsComma = $$$YES

        // Configuration de la routine à monitorer (forme "int" de la classe)
        // Pour trouver le nom exact de la routine, utilisez la commande :
        // Do $SYSTEM.OBJ.Compile("dc.codemonitor.DoSomething","ck")
        // La ligne "Compiling routine XXX" vous donnera le nom de la routine
        Set monitor.routines = $ListBuild("dc.codemonitor.DoSomething.1")

        // Démarrage du monitoring
        $$$TOE(sc, monitor.startMonitoring())
        
        // Exécution du code à monitorer avec gestion des erreurs
        Try {
            Do ##class(dc.codemonitor.DoSomething).GenerateNumber(parameters.Number)

            // Important : toujours arrêter le monitoring
            Do monitor.stopMonitoring()
        }
        Catch ex {
            // Arrêt du monitoring même en cas d'erreur
            Do monitor.stopMonitoring()
            Throw ex
        }
    }
    Catch ex {
        Set sc = ex.AsStatus()
        Do $SYSTEM.Status.DisplayError(sc)
    }

    Return sc
}

Cet exemple montre plusieurs bonnes pratiques importantes:

  • Utilisation d'un bloc Try/Catch pour gérer les erreurs
  • Arrêt systématique du monitoring, même en cas d'erreur
  • Documentation sur la façon de trouver le nom exact de la routine correspondant à une classe à monitorer
  • Paramétrage complet du moniteur

Exemple d'utilisation avec des pages CSP

MonLBL permet également de monitorer des pages CSP. Voici un exemple (également disponible dans la classe dc.codemonitor.ExampleCsp) :

ClassMethod MonitorCSP(parameters As %DynamicObject = {{}}) As %Status
{
    Set sc = $$$OK
    Try {
        // Affichage des paramètres reçus
        Write "* Parameters :", !
        Set formatter = ##class(%JSON.Formatter).%New()
        Do formatter.Format(parameters)
        Write !
        
        // Création et configuration du moniteur
        Set monitor = ##class(dc.codemonitor.MonLBL).%New()
        Set monitor.autoCompile = $$$YES
        Set monitor.metricsEnabled = $$$YES
        Set monitor.directory = ##class(%File).NormalizeDirectory(##class(%SYS.System).TempDirectory())
        Set monitor.decimalPointIsComma = $$$YES

        // Pour monitorer une page CSP, on utilise la routine générée
        // Exemple: /csp/user/menu.csp --> classe: csp.menu --> routine: csp.menu.1
        Set monitor.routines = $ListBuild("csp.menu.1")

        // Les pages CSP nécessitent les objets %session, %request et %response
        // On crée ces objets avec les paramètres nécessaires
        Set %request = ##class(%CSP.Request).%New()
        // Configurer les paramètres de requête si nécessaire
        // Set %request.Data("<param_name>", 1) = <value>
        Set %request.CgiEnvs("SERVER_NAME") = "localhost"
        Set %request.URL = "/csp/user/menu.csp"

        Set %session = ##class(%CSP.Session).%New(1234)
        // Configurer les données de session si nécessaire
        // Set %session.Data("<data_name>", 1) = <value>

        Set %response = ##class(%CSP.Response).%New()
            
        // Démarrage du monitoring
        $$$TOE(sc, monitor.startMonitoring())
        
        Try {
            // Pour éviter d'afficher le contenu de la page CSP dans le terminal,
            // on peut utiliser la classe IORedirect pour rediriger la sortie vers null
            // (nécessite l'installation via zpm "install io-redirect")
            Do ##class(IORedirect.Redirect).ToNull() 
            
            // Appel de la page CSP via sa méthode OnPage
            Do ##class(csp.menu).OnPage()
            
            // Restauration de la sortie standard
            Do ##class(IORedirect.Redirect).RestoreIO()

            // Arrêt du monitoring
            Do monitor.stopMonitoring()
        }
        Catch ex {
            // Toujours restaurer la sortie et arrêter le monitoring en cas d'erreur
            Do ##class(IORedirect.Redirect).RestoreIO()
            Do monitor.stopMonitoring()
           
            Throw ex
        }
    }
    Catch ex {
        Set sc = ex.AsStatus()
        Do $SYSTEM.Status.DisplayError(sc)
    }

    Return sc
}

Points importants pour le monitoring des pages CSP :

  1. Identification de la routine : Une page CSP est compilée en une classe et une routine. Par exemple, /csp/user/menu.csp génère la classe csp.menu et la routine csp.menu.1.

  2. Environnement CSP : Il est nécessaire de créer les objets de contexte CSP (%request, %session, %response) pour que la page s'exécute correctement.

  3. Redirection de sortie : Pour éviter que le contenu HTML ne s'affiche dans le terminal, on peut utiliser l'utilitaire IORedirect (disponible sur OpenExchange via zpm "install io-redirect").

  4. Appel de la page : L'exécution se fait via la méthode OnPage() de la classe générée.

Exemple de sortie

Voici un exemple de sortie obtenue lors de l'exécution de la méthode MonitorGenerateNumber :

USER>d ##class(dc.codemonitor.Example).MonitorGenerateNumber({"number":"100"})
* Parameters :
{
  "number":"100"
}

* Metrics are exported to /usr/irissys/mgr/Temp/dc.codemonitor.DoSomething.1.csv
* Perf results :
{
  "startDateTime":"2025-05-07 18:45:42",
  "systemCPUTime":0,
  "userCPUTime":0,
  "timing":0.000205,
  "lines":19,
  "gloRefs":14,
  "diskReadInMs":"0"
}

On peut observer dans cette sortie :

  1. L'affichage des paramètres d'entrée
  2. La confirmation que les métriques ont été exportées dans un fichier CSV
  3. Un résumé des performances globales au format JSON, incluant :
    • La date et l'heure de début
    • Le temps CPU système et utilisateur
    • Le temps d'exécution total
    • Le nombre de lignes exécutées
    • Le nombre de références globales
    • Le temps de lecture disque

Interprétation des résultats CSV

Après l'exécution, des fichiers CSV (1 par routine dans le $ListBuild routines) sont générés dans le répertoire configuré. Ces fichiers contiennent :

  • Le numéro de ligne
  • Les métriques collectées pour chaque ligne
  • Le code source de la ligne (attention si vous n'avez pas compilé les classes avec le flag "k", le code source ne sera pas disponible dans le fichier csv)

Voici un exemple du contenu d'un fichier CSV exporté (dc.codemonitor.DoSomething.1.csv) :

LigneRtnLineGloRefTimeTotalTimeCode
10000 ;dc.codemonitor.DoSomething.1
20000 ;Generated for class dc.codemonitor.DoSomething. Do NOT edit. 05/07/2025 10:16:07AM
30000 ;;59595738;dc.codemonitor.DoSomething
40000 ;
50000GenerateNumber(n=1000000) methodimpl {
6100,0000050,000005 For i=1:1:n {
710000,0000190,000019 Set number = $Random(100000)
810000,0000150,000015 Set isOdd = number # 2
910000,0000130,000013 }
10100,0000030,000003 Return }

Dans ce tableau, nous pouvons analyser :

  • RtnLine : Indique combien de fois chaque ligne a été exécutée (ici, les lignes 6 et 10 ont été exécutées une fois)
  • GloRef : Montre les références globales générées par chaque ligne
  • Time : Présente le temps d'exécution propre à chaque ligne
  • TotalTime : Affiche le temps total incluant les appels à d'autres routines

Ces données peuvent être facilement importées dans un tableur pour analyse approfondie. Les lignes les plus coûteuses en termes de temps ou d'accès aux données peuvent ainsi être facilement identifiées.

Remarque sur l'efficacité du cache

L'efficacité du cache de base de données (global buffer) peut masquer des problèmes de performance réels. Lors de l'analyse, les accès aux données peuvent paraître rapides grâce à ce cache, mais pourraient être bien plus lents dans certaines conditions réelles d'utilisation.

Sur les systèmes de développement, vous pouvez vider le cache entre vos mesures avec la commande suivante :

Do ClearBuffers^|"%SYS"|GLOBUFF()

⚠️ ATTENTION : Soyez prudent avec cette commande, car elle s'applique à l'ensemble du système. Ne l'utilisez jamais sur un environnement de production, car cela pourrait impacter les performances de toutes les applications en cours d'exécution.

Conclusion

Le monitoring ligne par ligne est un outil précieux pour l'analyse de performance de code ObjectScript. En identifiant précisément les lignes de code qui consomment le plus de ressources, il permet aux développeurs de gagner beaucoup de temps dans l'analyse de problèmes de lenteurs.

0
0 45
Annonce Irène Mykhailova · Mai 14, 2025

Bonjour à tous,

L'équipe Certification d'InterSystems Learning Services est heureuse d'annoncer la sortie de notre nouvel examen InterSystems IRIS Development Professional. Il est désormais disponible à l'achat et à la réservation dans le catalogue d'examens InterSystems. Les candidats potentiels peuvent consulter les sujets d'examen et les questions d'entraînement pour se familiariser avec les approches et le contenu de l'examen. Les candidats ayant réussi l'examen recevront un badge de certification numérique à partager sur les réseaux sociaux comme LinkedIn. Si vous débutez avec la certification InterSystems, veuillez consulter les pages de notre programme qui incluent des informations sur les examens, les règles d'examen, la FAQ et bien plus encore.

0
0 12
Article Sylvain Guilbaud · Mai 9, 2025 9m read

L'indication de requête parallèle augmente les performances de certaines requêtes sur les systèmes multiprocesseurs par le biais du traitement parallèle. L'optimiseur SQL détermine les cas où cela est bénéfique. Sur les systèmes à un seul processeur, cette indication n'a aucun effet.

Le traitement parallèle peut être géré par:

  1.  Définition de l'option auto parallel pour l'ensemble du système.
    
  2. L'utilisation du mot-clé %PARALLEL dans la clause FROM de certaines requêtes.
    

Le mot clé %PARALLEL est ignoré lorsqu'il est appliqué aux requêtes suivantes:

  1. Les requêtes INSERT, UPDATE et DELETE (cette fonctionnalité ne s'applique qu'aux requêtes SELECT)
  2. Les requêtes impliquant des fonctions ou des variables spécifiques au processus
  3. Une sous-requête corrélée à une requête englobante.
  4. Une sous-requête contenant des prédicats complexes, tels que les prédicats FOR SOME et FOR SOME %ELEMENT.

En plus des raisons mentionnées précédemment, voici quelques raisons pour lesquelles le traitement parallèle des requêtes peut être ignoré:

  • Certaines requêtes complexes ne bénéficient pas d'un traitement parallèle, même si elles semblent en bénéficier au départ.
  • Certaines configurations et paramètres de base de données ne supportent pas le traitement %PARALLEL.
  • Les dépendances et les relations au sein de la structure des données peuvent empêcher une parallélisation efficace.

Dans des scénarios suivants, %PARALLEL n'effectuera pas de traitement parallèle:

  1.  La requête inclut à la fois les clauses TOP et ORDER BY, en optimisant le temps le plus rapide pour atteindre la première ligne.
    
  2.  La requête fait référence à une vue et renvoie un identifiant de vue.
    
  3.  La requête utilise des formats de stockage personnalisés ou des tables GLOBAL TEMPORARY ainsi que des tables avec un stockage de référence global étendu.
    
  4.  La requête accède à une table avec une sécurité au niveau de la ligne.
    
  5.  Les données sont stockées dans une base de données distante.
    
  6.  La collation NLS au niveau du processus ne correspond pas à la collation NLS de tous les globaux impliqués.
    

Pour plus de détails sur les options, les considérations et les restrictions, reportez-vous à Configure Parallel Query Processing (Interystems Documentation) et Specify Optimization Hints in Queries (Configuration du traitement parallèle des requêtes (Documentation Interystems) et Spécifier les conseils d'optimisation dans les requêtes). Ce sujet a été récemment exploré dans le cadre d'une discussion au sein de la Communauté de développeurs d'InterSystems (DC), qui a inspiré cet article sur IRIS, Cache et Ensemble.

InterSystems IRIS supporte le traitement parallèle à la fois pour le SQL intégré, le SQL dynamique et le SQL dans les QueryMethods. Lorsque le mot-clé %PARALLEL est utilisé dans la clause FROM d'une requête pour suggérer un traitement parallèle. L'optimiseur SQL déterminera si la requête peut bénéficier d'un traitement parallèle et l'appliquera le cas échéant.

Pour utiliser efficacement le traitement %PARALLEL dans InterSystems IRIS, plusieurs paramètres et restrictions doivent être pris en compte, tant au niveau du système qu'au niveau de la requête, afin d'en tirer tous les avantages.

Dans le cas où vous essayez d'obtenir le traitement %PARALLEL à l'aide du traitement parallèle des requêtes à l'échelle du système et que le mode adaptatif est désactivé, vous pouvez activer le traitement parallèle des requêtes à l'échelle du système via le Portail de gestion ou $SYSTEM.SQL.Util.SetOption() Exemple

USER>w ##class(%SYSTEM.SQL.Util).GetOption("AutoParallel")
0
USER>d ##class(%SYSTEM.SQL.Util).SetOption("AutoParallel",1,.oldParVal)
 
USER>w ##class(%SYSTEM.SQL.Util).GetOption("AutoParallel")
1
USER>zw oldParVal
oldParVal=0

Autres aspects importants à prendre en compte lors de la mise en œuvre de la fonctionnalité %PARALLEL.

  •   Lorsque le [AdaptiveMode](https://docs.intersystems.com/iris20242/csp/docbook/DocBook.UI.Page.cls?KEY=RACS_AdaptiveMode) est activé, le traitement parallèle automatique est appliqué à toutes les requêtes SELECT, en les accompagnant de la mention %PARALLEL. Cependant, toutes les requêtes ne peuvent pas utiliser le traitement parallèle, car l'optimiseur SQL peut en décider autrement.
    
  •   Lorsque nous essayons d'utiliser cette fonctionnalité %PARALLEL, nous devons également prendre en compte le paramètre  [AutoParallelThreshold](https://docs.intersystems.com/iris20242/csp/docbook/Doc.View.cls?KEY=RACS_AutoParallelThreshold) (la valeur par défaut est 3200) et ce paramètre n'est pas utile dans le cas où [AutoParallel](https://docs.intersystems.com/iris20242/csp/docbook/DocBook.UI.Page.cls?KEY=RACS_AutoParallel) est désactivé.
    
  •   Le paramètre AutoParallelThreshold détermine si une requête est exécutée en parallèle, les valeurs les plus élevées réduisant les chances de traitement en parallèle. La valeur par défaut est 3200, elle peut être ajustée via $SYSTEM.SQL.Util.SetOption("AutoParallelThreshold",n,.oldval).
    
  •   Dans les environnements partagés, le traitement parallèle est utilisé pour toutes les requêtes, quel que soit le seuil, lorsque le mode adaptatif AdaptiveMode est activé.
    
  •   Lorsque le mode AdaptiveMode est activé (défini à 1) et que la fonctionnalité AutoParallel est désactivée, le Mode adaptatif remplace le paramètre AutoParallel et active le traitement parallèle.
    

Exemple: Exemple de classe avec 100 000 enregistrements remplis

 Class SQLClass.MyTest Extends (%Persistent, %Populate)
  {
    
    Property Name As %String(MAXLEN = 255);
    
    Property Age As %Integer(MAXVAL = 100, MINVAL = 1);
    
    Property Address As %String(MAXLEN = 255);
    
    Property City As %String(MAXLEN = 255);
    
    Property State As %String(MAXLEN = 255);
    
    Property Zip As %String(MAXLEN = 255);
    
    Property Country As %String(MAXLEN = 255);
    
    Property Comment As %String(MAXLEN = 255);
    
    Property Hobby As %String(MAXLEN = 255);
    
    Property JobTitle As %String(MAXLEN = 255);
    
    Property Company As %String(MAXLEN = 255);
    
    Property PhoneNumber As %String(MAXLEN = 255);
    
    Property Email As %String(MAXLEN = 255);
    
    Property Gender As %String(MAXLEN = 1);
    
    Property Ethnicity As %String(MAXLEN = 255);
    
    Property Race As %String(MAXLEN = 255);
    
    Property Religion As %String(MAXLEN = 255);
    
    Property MaritalStatus As %String(MAXLEN = 255);
    
    Property Children As %Integer(MAXVAL = 10, MINVAL = 0);
    
    Property Income As %Integer(MAXVAL = 100000, MINVAL = 0);
    
    Property Occupation As %String(MAXLEN = 255);
    
    Property Education As %String(MAXLEN = 255);
    
    Property HomePhone As %String(MAXLEN = 255);
    
    Property MobilePhone As %String(MAXLEN = 255);
    
    Property WorkPhone As %String(MAXLEN = 255);
    
    Property WorkEmail As %String(MAXLEN = 255);
    
    Property HomeEmail As %String(MAXLEN = 255);
    
    Property HomeAddress As %String(MAXLEN = 255);
    
    Property HomeCity As %String(MAXLEN = 255);
    
    Property HomeState As %String(MAXLEN = 255);
    
    Property HomeZip As %String(MAXLEN = 255);
    
    Property HomeCountry As %String(MAXLEN = 255);
    
    Property WorkAddress As %String(MAXLEN = 255);
    
    Property WorkCity As %String(MAXLEN = 255);
    
    Property WorkState As %String(MAXLEN = 255);
    
    Property WorkZip As %String(MAXLEN = 255);
    
    Property WorkCountry As %String(MAXLEN = 255);
    
    Property WorkPhoneNumber As %String(MAXLEN = 255);
    
    Property WorkMobilePhone As %String(MAXLEN = 255);
    
    Property WorkFax As %String(MAXLEN = 255);
    
    Property WorkWebsite As %String(MAXLEN = 255);
    
    Property WorkComments As %String(MAXLEN = 255);
    
    
    Index IdxAge On Age;
}

Test n° 1Exemple d'exécution sans % PARALLEL (pour afficher 10 000 enregistrements en SMP)

select * from SQLClass.MyTest where age>40
  • 3.2069 secondes
  • 10404 références globales
  • 3325407 commandes exécutées

Exemple d'exécution avec %PARALLEL(pour afficher 10 000 enregistrements dans SMP)

select * from %PARALLEL SQLClass.MyTest where age>40
  • 2.8681 secondes
  • 10404 références globales
  • 3325407 commandes exécutées

Test n° 2 :Exemple d'exécution sans % PARALLEL (pour afficher 1 enregistrement en SMP)

select COUNT(Children),MAX(Children),MIN(Children),AVG(Children) from SQLClass.MyTest where age>10
  • 0.4037 secondes
  • 46559 références globales
  • 1459936 commandes exécutées

Exemple d'exécution avec %PARALLEL (pour afficher 1 enregistrement en SMP)

select COUNT(Children),MAX(Children),MIN(Children),AVG(Children) from %PARALLEL SQLClass.MyTest where age>10
  • 0.0845 secondes
  • 46560 références globales
  • 1460418 commandes exécutées

Exemple avec SQL intégré

ClassMethod embeddedSQL() As %Status
{
    // w ##Class(SQLClass.MyTest).embeddedSQL()
    Set sc = $$$OK
    DO ClearBuffers^|"%SYS"|GLOBUFF()
    set stime=$p($zts,",",2)
    &sql(select COUNT(Children),MAX(Children),MIN(Children),AVG(Children) from SQLClass.MyTest where age>10)
    w:'SQLCODE "Without %Parallel : ",($p($zts,",",2)-stime),!
    DO ClearBuffers^|"%SYS"|GLOBUFF()
    set stime=$p($zts,",",2)
    &sql(select COUNT(Children),MAX(Children),MIN(Children),AVG(Children) from %PARALLEL SQLClass.MyTest where age>10)
    w:'SQLCODE "With %Parallel : ",($p($zts,",",2)-stime),!
    Return sc
}

Résultats (SQL intégré) : USER> D ##Class(SQLClass.MyTest).embeddedSQL() 5466 blocs supprimés Sans %Parallel : .355737 5217 blocs supprimés Avec %Parallel : .3407056

USER>

Exemple avec SQL dynamique

ClassMethod dynamicSQL() As %Status
{
     // w ##Class(SQLClass.MyTest).dynamicSQL()
    Set sc = $$$OK
    DO ClearBuffers^|"%SYS"|GLOBUFF()
    set stime=$p($zts,",",2), recCnt=0
    Set rs=##class(%ResultSet).%New()
    Set sc=rs.Prepare("select COUNT(Children),MAX(Children),MIN(Children),AVG(Children) from SQLClass.MyTest where age>10")
    Set sc=rs.Execute()
    While(rs.Next()) {
	 	w "COUNT(Children) : ",rs.GetData(1),"; MAX(Children) : ",rs.GetData(2),"; MIN(Children) : ",rs.GetData(3),"; AVG(Children) : ",rs.GetData(4),!
    }
    w "Without %Parallel : ",($p($zts,",",2)-stime),!!!
    DO ClearBuffers^|"%SYS"|GLOBUFF()
    set stime=$p($zts,",",2), recCnt=0
    Set sc=rs.Prepare("select COUNT(Children),MAX(Children),MIN(Children),AVG(Children) from SQLClass.MyTest where age>10")
    Set sc=rs.Execute()
    While(rs.Next()) {
	 	w "COUNT(Children) : ",rs.GetData(1),"; MAX(Children) : ",rs.GetData(2),"; MIN(Children) : ",rs.GetData(3),"; AVG(Children) : ",rs.GetData(4),!
	}
    w "With %Parallel : ",($p($zts,",",2)-stime),!
    Return sc
}

Résultats (SQL dynamique): USER>d ##Class(SQLClass.MyTest).dynamicSQL() 22163 blocs supprimés NOMBRE(Enfants) : 89908; MAX(Enfants) : 10; MIN(Enfants) : 0; AVG(Enfants) : 5.021989144458780086 Sans %Parallel : .4036913

5721 blocs supprimés NOMBRE(Enfants) : 89908; MAX(Enfants) : 10; MIN(Enfants) : 0; AVG(Enfants) : 5.021989144458780086 Avec %Parallel : .3693442

0
0 37
Article Lorenzo Scalese · Mai 7, 2025 6m read

Introduction

À mesure que l'automatisation pilotée par l'IA devient un élément essentiel des systèmes d'information modernes, l'intégration des capacités d'IA dans les plateformes existantes doit être transparente et efficace. Le projet IRIS Agent montre comment l'IA générative peut fonctionner sans effort avec InterSystems IRIS, grâce à son puissant cadre d'interopérabilité, sans qu'il soit nécessaire d'apprendre Python ou de créer des workflows d'IA distincts à partir de zéro.
Ce projet examine la manière dont ChatGPT et Anthropic Claude, deux modèles d'IA parmi les plus avancés, peuvent interagir avec IRIS à l'aide de GPT personnalisés et du protocole MCP (Model Context Protocol). Plutôt que de créer des pipelines d'IA isolés, IRIS Agent traite l'IA comme un service d'interopérabilité, permettant ainsi aux organisations d'améliorer l'automatisation, la prise de décision et le traitement des données sans perturber leur architecture existante.
En s'appuyant sur des outils d'interopérabilité natifs d'IRIS, les développeurs peuvent intégrer des modèles d'IA de manière transparente, comme n'importe quel autre composant du système. Cette approche garantit la stabilité, la sécurité, l'évolutivité et l'auditabilité, tout en permettant une interaction en langage naturel, la récupération de données en temps réel et l'administration automatisée du système, le tout dans l'environnement familier d'IRIS.

Technologies sous-jacentes à IRIS Agent

Le projet IRIS Agent s'appuie sur un ensemble de technologies puissantes pour garantir efficacité, évolutivité et intégration transparente:

  • InterSystems IRIS – Une plateforme robuste dédiée au développement d'applications et à l'intégration de données, qui utilise ObjectScript pour le code côté serveur.
  • Custom GPT Bot – Un assistant IA personnalisé conçu pour rationaliser les interactions avec le système, basé sur ChatGPT.
  • Claude AI Desktop – Facilite la communication avec le serveur via le protocole MCP (Model Context Protocol).
  • Node.js – Gère les communications avec le serveur MCP
  • OpenAPI – Documentation API standardisée.
  • Docker – Compartimente l'application pour simplifier le déploiement et la gestion des dépendances.

Présentation interne

Voici à quoi ressemble notre projet sous le capot IRIS:

La Production comprend les éléments suivants:

  • LanguageModelIn: un service qui reçoit une requête API et la redirige vers l'opération responsable.
  • Meds: une opération qui recherche des médicaments sur une API tierce.
  • Metrics: une opération qui recherche des informations OPS telles que les journaux, les erreurs et les messages dans le système Iris.
  • Namespaces: une opération qui répertorie, recherche et modifie les espaces de noms dans le système Iris.
  • Users: une opération qui répertorie, recherche, crée et supprime des utilisateurs dans le système Iris.

Le fonctionnement du service est particulièrement visible dans l'afficheur de messages et les traces. Il peut nous aider à suivre les opérations et à diagnostiquer les problèmes, par exemple les requêtes:

…et les réponses:


L'un des points forts de ce projet réside dans le fait que le service LanguageModelIn génère automatiquement une documentation API ouverte pour les opérations métier dans le cadre de la production IRIS Interoperability. Cette API  nous permet de connecter facilement les GPT personnalisés à ChatGPT et au serveur MCP (Model Context Protocol) à Claude AI Desktop. 

Intégration avec ChatGPT 

Après avoir terminé tous les processus d'installation et de configuration, que vous trouverez dans notre fichier ReadMe, ReadMe, demandons à notre agent IRIS GPT d'OpenAI quelles sont ses fonctionnalités actuelles:

  

Et créez un nouvel utilisateur…

   


Vérification des mises à jour...

   

Intégration avec des Sources de données externes

L'une des fonctionnalités remarquables de l'agent IRIS est sa capacité à interroger de manière transparente non seulement les données stockées dans la base de données InterSystems IRIS, mais également des sources de données externes. Dans notre exemple, l'agent s'intègre à l'OpenFDA API pour fournir des informations en temps réel sur les médicaments. Cela permet aux utilisateurs de rechercher des informations sur les médicaments, des rapports de sécurité et des données de conformité réglementaire directement dans le système. 
Dans notre projet, l'API offre la possibilité de rechercher des médicaments par leur nom. Recherchons donc les médicaments dont le nom contient le mot "flu".

   

Si vous souhaitez l'essayer dès maintenant, suivez le lien et engagez une conversation avec notre IRIS Agent démo.

Intégration avec Claude AI Desktop

L'une des fonctionnalités clés de l'agent IRIS est sa capacité à interagir avec Claude AI Desktop, un assistant IA local développé par Anthropic. L'intégration est assurée par le protocole MCP (Model Context Protocol), qui facilite la communication entre Claude et les applications externes. Pour ce faire, l'agent IRIS utilise un serveur MCP Node.js dédié qui sert d'intermédiaire, traitant les requêtes entrantes et les acheminant entre Claude et le système IRIS.
Cette configuration permet aux utilisateurs d'interagir directement avec l'agent IRIS via l'interface Claude, en émettant des commandes en langage naturel pour récupérer des données système, gérer les configurations et exécuter des tâches administratives. Le serveur MCP garantit un échange de données fluide, tout en maintenant l'efficacité et la sécurité, et fournit aux administrateurs un assistant puissant basé sur l'IA pour la gestion du système.

         

Conclusion

Le projet IRIS Agent présente le potentiel de l'automatisation pilotée par l'IA dans les environnements d'entreprise modernes. En intégrant de manière transparente InterSystems IRIS, Claude AI et Custom GPT, il simplifie la gestion des systèmes, améliore l'efficacité et ouvre la voie à de futures innovations. Notre projet démontre également que vous êtes déjà prêt pour la révolution de l'IA avec InterSystems IRIS!


Si vous avez apprécié la découverte d'IRIS Agent et de ses fonctionnalités et que vous souhaitez nous soutenir, veuillez prendre quelques instants pour voter pour notre application ici https://openexchange.intersystems.com/contest/40. Je vous remercie!


Développeurs de projet:

Banksia Global est une société de conseil technologique de premier plan qui aide les organisations à exploiter pleinement le potentiel des solutions modernes de gestion des données. En mettant l'accent sur la plateforme InterSystems IRIS, Banksia Global fournit des conseils stratégiques, des services d'intégration de systèmes et de développement de logiciels personnalisés à des clients issus de divers secteurs. Son expertise réside dans la fourniture de solutions hautement performantes et évolutives qui permettent aux entreprises de stimuler l'innovation, de rationaliser leurs opérations et de saisir de nouvelles opportunités. Réputée pour son approche collaborative et agile, Banksia Global travaille en étroite collaboration avec ses clients afin de s'assurer que chaque solution est adaptée à leurs besoins spécifiques, favorisant ainsi des partenariats à long terme et une croissance durable.

0
0 59
Article Developer Community Admin · Mai 6, 2025 13m read

La plateforme de données InterSystems IRIS est à la base de toutes les applications InterSystems, ainsi que de milliers d'applications utilisées par nos clients et partenaires dans des domaines tels que la Santé, les Services financiers, la Chaîne logistique et d'autres écosystèmes. Il s'agit d'une plateforme convergente qui fournit une gestion des données transactionnelles et analytiques, une interopérabilité intégrée, une intégration des données, ainsi que des analyses intégrées et une IA. Elle prend en charge l'approche InterSystems Smart Data Fabric pour la gestion de données diverses et distribuées.

Notre architecture repose sur des installations permettant un traitement de données haute performance, multimodèle et multilingue dans notre moteur de données central, également appelé plan de données commun ou Common Data Plane. Tout cela s'appuie sur une infrastructure remarquable qui permet de traiter des volumes de données extrêmement importants et des taux de transaction élevés pouvant atteindre plus d'un milliard d'opérations de base de données par seconde.

Ensuite, deux sous-systèmes majeurs entrent en jeu : l'un axé sur l'analyse et l'intelligence artificielle (IA), l'autre sur l'interopérabilité et l'intégration des données. Ces sous-systèmes suivent notre philosophie fondamentale qui consiste à tout faire fonctionner à proximité des données afin de fournir des performances élevées avec une empreinte minimale.

Enfin, autour des sous-systèmes, nous avons construit une structure de données intelligentes qui permet aux utilisateurs de résoudre des problèmes complexes dans un seul empilement. Les sections suivantes explorent ces couches et leur interaction afin de mieux comprendre ce qui rend la technologie InterSystems IRIS si particulière.

Réputée pour ses performances, la technologie InterSystems repose sur un mécanisme très efficace de stockage de données, d'indexation et d'accès aux données. Contrairement à d'autres fournisseurs de bases de données, nous ne fournissons pas de base de données nativement relationnelle ou documentaire. Nous utilisons un format de stockage sous-jacent appelé globales. Ils sont modélisés dans un format multidimensionnel hautement optimisé, sous forme de tableau, construit comme un arborescence B+ qui est automatiquement indexée à chaque operation.InterSystems.com Construit à un niveau inférieur aux modèles de données (tels que relationnel, objet ou document), un format de stockage unique est projeté dans différents formats et modèles de données. Ceci est appelé Common Data Plane ou plan de données commun.

Le format global sous-jacent est très efficace et peut être traduit dans de nombreux modèles de données différents:

Les variables globales (précédées du préfixe "^") peuvent avoir plusieurs indices, dont chacun peut être numérique, alphanumérique ou symbolique. Les globales sont puissantes et représentent les données de manière générale, ce qui permet d'utiliser simultanément plusieurs paradigmes de données à partir d'une seule copie des données. Les cas tels que les tableaux associatifs et creux sont faciles à traiter avec cette approche. Nous encodons également dans le format de stockage lui-même, à l'aide d'encodages (désignés par le préfixe "$") qui fournissent un faible empreinte et une faible latence grâce à l'optimisation du disque et des E/S. Le format de ces encodages est le même en mémoire, sur disque ou sur le réseau. Cela minimise les transformations impliquées dans l'ingestion des données et permet d'atteindre les vitesses incroyables attendues d'une base de données en mémoire, tout en conservant la persistance typique d'une base de données sur disque.

Un exemple illustrant comment une seule globale peut prendre en charge plusieurs modèles de données est fourni par le cas où vous utilisez des outils SQL ou BI et souhaitez accéder aux données dans un format relationnel, sous forme de tables avec des lignes et des colonnes. Si vous effectuez un développement orienté objet, cependant, nous projetons automatiquement ces objets dans des globales, puis projetons ces données dans un format relationnel. De même, nous pouvons projeter JSON ou d'autres formats de document dans une forme relationnelle.

Cette fonctionnalité signifie qu'au lieu d'avoir plusieurs magasins de données, l'un relationnel, l'autre objet, l'autre document, et de les assembler, nous avons une seule copie projetée sous toutes ces différentes formes, sans duplication, déplacement ou mappage. Il en résulte également une combinaison pratique de schéma à l'écriture et de schéma à la lecture. Comme avec un lac de données, vous pouvez compter sur un niveau de structure tel qu'un lien de données, après avoir inséré les données et déterminé le meilleur schéma pour ces données en fonction de leur utilisation actuelle. Cette structure globale fonctionne bien pour les données structurées, ainsi que pour les documents et les données semi-structurées ou non structurées.

Quelques encodages, conçus de manière très rigoureuse, sont utilisés pour stocker efficacement les données et les index.

Bien que les listes constituent le codage de stockage par défaut, InterSystems IRIS peut représenter les données et les index dans un ou plusieurs de ces codages en fonction des caractéristiques des données et/ou des spécifications des développeurs. Les vecteurs permettent de stocker efficacement un grand nombre de données du même type et sont utilisés pour le stockage en colonnes dans les analyses, pour la recherche vectorielle, pour les séries temporelles et pour des cas plus spécialisés. Les tableaux de valeurs compactés (connus sous le nom de $pva) sont idéaux pour le stockage orienté document. Les bitmaps sont utilisés pour les données booléennes et pour les index bitmap très efficaces.

Toutes ces structures de données sont automatiquement indexées dans une mise à jour hautement optimisée à chaque opération. De nombreux utilisateurs utilisent l'indexation intégrée pour effectuer des étapes transactionnelles complètes à faible latence, comme les "milliards d'opérations de base de données par seconde" mentionnées précédemment. Cette indexation cohérente, effectuée presque instantanément, nous offre un accès cohérent et à faible latence à toutes les données, quel que soit leur format. 6 Les fonctionnalités multimodèles offertes par le format global sous-jacent sont pratiquement instantanées, car il n'y a qu'une seule copie des données à modifier, ce qui évite tout gain de temps ou d'espace pour la réplication des données. Cela offre également des avantages majeurs en termes de vitesse d'ingestion, de fiabilité et d'évolutivité.

Le système peut combiner plusieurs encodages. The multi-lingual capability that globals provide means that you can work in the programming language of your choice, with effortless access to all needed formats. La capacité multilingue fournie par les globales vous permet de travailler dans le langage de programmation de votre choix, avec un accès facile à tous les formats nécessaires. C'est clairement le cas pour l'accès relationnel via des normes telles que JDBC et ODBC, mais cela vaut également pour la correspondance automatique des objets dans .NET ou Java avec un format sous-jacent. Du point de vue du développement, vous n'avez pas à vous soucier du mappage relationnel des objets; vous travaillez simplement avec un objet et nous nous chargeons du format de stockage.

Autour du moteur de données central se trouve une mémoire cache distribuée offrant des garanties de cohérence intégrées. Ce cache utilise notre protocole Enterprise Cache Protocol, ou ECP, et répond aux garanties théoriques en matière de cohérence dans le cadre d'un système distribué et en cas de défaillance. L'ECP intègre ces règles de cohérence afin de préserver l'intégrité des données au sein d'un système distribué, même en cas de défaillance, en les encapsulant directement.

En d'autres termes, les performances des données distribuées restent élevées, même à grande échelle. Vous pouvez répartir ces nœuds ECP pour une mise à l'échelle horizontale, ce qui vous permet de gérer un débit plus élevé. Vous pouvez également les répartir pour la distribution des données, ce qui signifie que vous pouvez bénéficier de performances en mémoire sans avoir à vous limiter à la mémoire disponible pour chaque nœud. 

ECP fonctionne particulièrement bien dans le cloud en raison de son évolutivité. Nous avons intégré cette fonctionnalité à notre InterSystems Kubernetes Operator (IKO) afin de fournir une mise à l'échelle automatique, et nous pouvons ajouter et supprimer de manière transparente des nœuds à l'application à l'aide d'ECP. Cette mise à l'échelle est essentiellement linéaire, et vous pouvez faire évoluer indépendamment l'ingestion, le traitement des données et le stockage des données, et optimiser votre charge de travail. ECP étant robuste face aux changements de topologie, un nœud peut tomber en panne sans affecter le traitement des transactions. Vous pouvez ajouter des nœuds à la volée, et ceux-ci peuvent récupérer la charge. Cela fournit une élasticité transparente, ce qui signifie que vous pouvez dimensionner les éléments de manière dynamique et bénéficier d'un coût net inférieur. ECP est transparent pour l'application; aucune modification n'est nécessaire pour faire évoluer une application. Les utilisateurs ont également la possibilité d'associer des charges de travail spécifiques à des ensembles de nœuds spécifiques dans un cluster InterSystems IRIS. Par exemple, les charges de travail de reporting ou d'analyse peuvent être attribuées à un pod, et les charges de travail à forte intensité transactionnelle à un autre.

La couche suivante de l'architecture built-in interoperability est un sous-système d'interopérabilité intégré. Il intègre les données provenant de messages, de périphériques et d'API différents. Il intègre également les données de masse, selon les modèles ETL ou ELT (extraction-transformation-chargement ou extraction-chargement-transformation). InterSystems IRIS Interoperability utilise le plan de données commun comme référentiel intégré pour tous les éléments de gestion des messages et d'intégration des données. Cela bénéficie ainsi des performances et de la fiabilité des deux premières couches, ainsi que des capacités multimodèles.   Par exemple, les données de structure de masse ont tendance à être orientées relationnellement, et de nombreux protocoles de messagerie ont tendance à être orientés document.

Par défaut, l'interopérabilité est persistante, ce qui signifie que les messages de données et les transformations sont stockés dans le système à des fins d'audit, de relecture et d'analyse. Contrairement à de nombreuses autres offres de middleware d'interopérabilité, la livraison peut être garantie, tracée et auditée à tous les niveaux. Vous pouvez confirmer qu'un message a été livré ou savoir qui a envoyé quel message à qui, ce type d'information étant important tant pour l'analyse que pour la recherche. Le paradigme général de l'interopérabilité InterSystems IRIS est orienté objet. Cela facilite la création et la maintenance des adaptateurs: l'héritage d'objets minimise les efforts nécessaires à la création d'adaptateurs personnalisés, y compris les tests.   Il aide également à la création et à la maintenance des transformations de données.  Comme le montre la figure 8, l'utilisation d'un objet commun peut réduire considérablement le nombre de transformations nécessaires entre différents formats de données ou protocoles. Plutôt que de créer et de maintenir une transformation de données pour chaque paire, une seule transformation pour chaque format de données vers un objet commun fournit une approche plus simple, plus facile à tester et à maintenir.

Au sein du sous-système d'interopérabilité InterSystems IRIS, il existe un large éventail de scénarios d'intégration entre les messages, les périphériques et les API.

Cette interopérabilité comprend la gestion intégrée du cycle de vie complet des API, des fonctionnalités de streaming, l'intégration de l'IoT, la compatibilité avec les services cloud, etc. Nous fournissons également des passerelles dynamiques en plusieurs langues, permettant une intégration hautement performante des applications existantes dans ces flux de données, dans la langue de votre choix.

L'interopérabilité InterSystems IRIS s'accompagne d'un ensemble de fonctionnalités analytiques et d'IA intégrées.

Chacune de ces capacités fonctionne "à proximité des données", ce qui signifie qu'en général, nous traitons les données sur place plutôt que de les transférer vers le lieu de traitement, ce qui entraînerait des coûts et des délais considérables.

Plusieurs fonctionnalités analytiques ont été intégrées à InterSystems IRIS. L'une d'elles est InterSystems IRIS BI, une architecture cubique type MOLAP pour la veille stratégique (BI), optimisée pour la latence. Comme cet ensemble de sous-systèmes est intégré à InterSystems IRIS, nous pouvons déclencher des événements SQL et des événements dans le cube en seulement 10 à 20 millisecondes entre les données et le tableau de bord. Le fait d'avoir une seule copie des données pour toutes les transactions et toutes les analyses permet de maintenir cette latence à un faible niveau. Comme ECP permet à un ensemble de nœuds d'opérer sur les analyses en isolation de la charge de travail transactionnelle, les analyses ne présentent aucun risque pour la réactivité transactionnelle, et il n'est jamais nécessaire d'avoir plus d'une copie des données.

Une autre fonctionnalité est l' l'analyse adaptative ou Adaptive Analytics, qui, contrairement à InterSystems IRIS BI, n'utilise pas de cubes prédéfinis. Elle optimise et construit dynamiquement des cubes virtuels au fur et à mesure, les rendant disponibles à la fois pour la BI et l'analyse adaptative. Il s'agit d'une fonctionnalité d'analyse sans interface utilisateur de type ROLAP qui s'intègre de manière transparente à tous les principaux outils de BI, tels que Tableau, PowerBI, Qlik, Excel et autres.

Outre les fonctionnalités d'analyse, plusieurs fonctionnalités de ML et d'IA sont également disponibles.

Integrated ML vous permet d'écrire des modèles de type apprentissage automatique (ML) à l'aide de SQL. Il vous suffit d'écrire une commande SQL, puis de créer, d'entraîner, de valider et de pronostiquer à l'aide du modèle. Les résultats peuvent être directement utilisés dans SQL. Ainsi, les développeurs familiarisés avec SQL peuvent utiliser les pronostics ML dans leurs applications.

Python est intégré directement dans le noyau de la plate-forme de données, ce qui lui permet de fonctionner directement avec les données et d'offrir des performances optimales. Vous n'avez pas besoin de transférer les modèles créés dans un environnement de développement ou de lab vers un environnement de production où vous les exécutez. Vous pouvez créer et exécuter vos modèles dans le même cluster, ce qui vous garantit que les données utilisées sont identiques et cohérentes. Les projets de science des données sont simples et rapides.

Les fonctionnalités de recherche vectorielle intégrée d'InterSystems IRIS vous permettent d'effectuer des recherches dans des données non structurées et semi-structurées. Les données sont converties en vecteurs (ou intégrations), puis stockées et indexées dans InterSystems IRIS pour la recherche sémantique, la génération augmentée par la récupération (RAG), l'analyse de texte, les moteurs de recommandation et d'autres cas d'utilisation.

Ces couches (le moteur de données central, la couche ECP pour étendre l'interopérabilité et nos fonctionnalités d'analyse) font partie de notre capacité unique à alimenter une architecture de données intelligentes Smart Data Fabric. La structure de données est un modèle architectural qui fournit une gouvernance commune à une grande variété de données et de sources de données. Un modèle courant pour une structure de données consiste à importer des données provenant de plusieurs sources, à les normaliser, à les dédupliquer, à les corréler de manière croisée et à les améliorer, puis à les mettre à la disposition d'une variété d'applications différentes:

La plupart des structures de données offrent plusieurs fonctionnalités, notamment l'ingestion, le pipelining, les métadonnées, etc. L'approche d'InterSystems se distingue par l'intégration de l'analyse et de l'IA au cœur de la structure de données:

L'un des principes clés de la technologie InterSystems est "connecter ou collecter". Certaines fonctionnalités d'InterSystems IRIS, telles que les tables étrangères ou fédérées, vous permettent de travailler ou de "vous connecter" aux données là où elles se trouvent. Vous pouvez également choisir de collecter ces données. 

InterSystems IRIS est indépendant des fournisseurs de cloud et fonctionne sur site, dans le cloud de votre choix, dans des scénarios hétérogènes et hybrides, ou dans des environnements multicloud. La partie de nos activités qui connaît la croissance la plus rapide est celle des services cloud, disponibles sur plusieurs clouds. Il est essentiel de pouvoir exécuter les applications où vous le souhaitez. C'est ce qui distingue InterSystems IRIS, par exemple, des installations fournies par les fournisseurs de cloud eux-mêmes ou de nombreuses options actuelles pour les magasins de données. Vous pouvez exécuter InterSystems IRIS et les applications créées avec ce produit où vous le souhaitez. Bien entendu, InterSystems IRIS est également disponible en tant que service géré dans le cloud.

Articles supplémentaires à ce sujet:

Source: Plateforme de données InterSystems IRIS: Guide d'architecture

0
0 44
Article Corentin Blondeau · Avr 28, 2025 5m read

Bonjour à tous,
Cet article fait suite à la question que j'avais posée à la communauté L'adaptateur UDP ne fonctionne pas
Dans cet article, je vais vous présenter les points suivants
1) Qu'est-ce que "UDP"?
2) L'état actuel d'Iris avec UDP
3) Ma solution avec l'adaptateur UDP


1) Qu'est-ce que "UDP"?

L'acronyme UDP signifie User Datagram Protocol (protocole de datagramme utilisateur). Il s'agit de l'un des principaux protocoles composant la suite IP (Internet Protocol), utilisé pour la transmission de données sur un réseau. Voici quelques fonctionnalités clés de l'UDP:

  1. Sans connexion : L'UDP n'établit pas de connexion avant d'envoyer des données, ce qui signifie qu'il peut envoyer des messages (datagrammes) sans échange préalable.
  2. Peu fiable : Il n'y a aucune garantie que les messages envoyés via l'UDP arriveront à destination. Il n'y a pas de récupération des erreurs ni de retransmission des paquets perdus.
  3. Vitesse : Étant donné que l'UDP est sans connexion et qu'il ne nécessite pas de vérification ou de récuperation des erreurs, il est généralement plus rapide que le TCP (Transmission Control Protocol), ce qui le rend approprié pour les applications où la vitesse est cruciale.
  4. Constrruit autour des datagrammes : L'UDP envoie des messages sous forme de paquets discrets, qui peuvent être de longueur variable. Chaque paquet est traité indépendamment.
  5. Cas d'utilisation : L'UDP est couramment utilisé dans les applications où la vitesse est plus importante que la fiabilité, telles que la diffusion vidéo en continu, les jeux en ligne, la voix sur IP (VoIP) et les communications en temps réel.

En général, l'UDP est un protocole léger qui est utile pour des applications spécifiques où une faible latence est essentielle.


2) L'état actuel d'Iris avec UDP

Bien entendu, InterSystems IRIS permet d'utiliser ce protocole pour envoyer et recevoir des données.
En tant que protocole REST, il y a deux façons de le faire :
- avec ##class(%Net.UDP).%New().
- avec EnsLib.UDP.OutboundAdapter et EnsLib.UDP.InboundAdapter

##class(%Net.UDP).%New()

Même si la documentation de la classe et très détaillée, voici le lien de la documentation d'InterSystems sur la façon de l'utiliser.
Pour envoyer/recevoir des données, il faut utiliser une instance de class(%Net.UDP).%New() et une méthode associée.
En résumé, pour envoyer des données (sur localhost avec le port 3001) :

SET client = ##class(%Net.UDP).%New()
SET addrbin = ##class(%Net.UDP).GetHostAddr("127.0.0.1")
Set status = client.Send("message text", addrbin, 3001)

Pour recevoir des données (sur localhost avec le port 3001) :

Set sobj = ##class(%Net.UDP).%New(3001,"127.0.0.1")
Set data = sobj.Recv()

 

EnsLib.UDP.OutboundAdapter and EnsLib.UDP.InboundAdapter

Ce dernier est plus simple : c'est un adaptateur.
La documentation : EnsLib.UDP.OutboundAdapter et EnsLib.UDP.InboundAdapter
Pour envoyer des données :

Set status = ..Adapter.SendStream(stream)

Pour obtenir des données :

Set status = ..Adapter.Receive(stream)


Cependant, cela ne fonctionne pas. J'ai posé ma question à la communauté "L'adaptateur UDP ne fonctionne pas" et j'ai créé un ticket pour le WRC.
La réponse a été formulée comme suit :

Cet exécutable sous-jacent n'est plus installé dans le produit depuis Ensemble 2018.1.

J'ai vérifié au niveau interne et le JIRA DP-437486 a été soumis pour mettre à jour ces adaptateurs afin d'utiliser la classe %Net.UDP, mais cela sera soumis à l'approbation de la gestion des produits et aux ressources de développement disponibles.

Malheureusement, la seule option possible actuellement est de créer votre propre adaptateur personnalisé en utilisant la classe %Net.UDP.

Voici les deux principales différences entre la classe (%Net.UDP) et l'adaptateur EnsLib.UDP.OutboundAdapter 

  • La classe %Net.UDP utilise la classe système $System.UDP, elle utilise donc le code du noyau Cache/IRIS pour envoyer/recevoir les messages UDP, alors que l'adaptateur UDP utilise un tuyau de commande pour appeler des exécutables externes afin d'envoyer/recevoir le message UDP.
  • La classe %Net.UDP envoie/lit une chaîne de caractères alors que l'adaptateur UDP utilise un flux pour envoyer/lire les messages.

3) Ma solution avec l'adaptateur UDP

J'ai donc écrit ma propre méthode (approuvée par le service d'assistance) pour envoyer des données :
 

/// Adaptateur pour l'envoi de données avec une connexion UDPClass USER.UDP.OutboundAdapter Extends Ens.Adapter
{

/// Hôte du serveur UDPProperty Host As%String [ Required ];/// Port du serveur UDPProperty Port As%Integer [ Required ];/// si 1, le texte qui sera envoyé est affichéProperty UDPTrace As%Integer(VALUELIST = ",0,1") [ InitialExpression = 0, Required ];Parameter SETTINGS = "Host:Basic,Port:Basic,UDPTrace:Basic";/// Envoi de "texte" par le biais de la connexion UDP Method SendDataText(text As%String) As%Status { Try { Set status = $$$OKIf..UDPTrace=1 { Do..ShowText(text) }

    <span class="hljs-keyword">Set</span> udpClient = <span class="hljs-keyword">##class</span>(<span class="hljs-built_in">%Net.UDP</span>).<span class="hljs-built_in">%New</span>()
    <span class="hljs-keyword">Set</span> addrbin = <span class="hljs-keyword">##class</span>(<span class="hljs-built_in">%Net.UDP</span>).GetHostAddr(<span class="hljs-built_in">..Host</span>)

    <span class="hljs-keyword">Set</span> sentBytes = udpClient.Send(text, addrbin, <span class="hljs-built_in">..Port</span>)
}
<span class="hljs-keyword">Catch</span> exception {
    <span class="hljs-keyword">Set</span> status = exception.AsStatus()
}    
<span class="hljs-keyword">Return</span> status

}

/// Conversion du "stream" en texte et son envoi via la connexion UDP Method SendDataStream(stream As%Stream.Object) As%Status { Try { Do stream.Rewind() Set text = ""While 'stream.AtEnd{ Set text = text _ stream.Read() }

    <span class="hljs-keyword">Set</span> status = <span class="hljs-built_in">..SendDataText</span>(text)
}
<span class="hljs-keyword">Catch</span> exception {
    <span class="hljs-keyword">Set</span> status = exception.AsStatus()
}    
<span class="hljs-keyword">Return</span> status

}

/// Conversion de l'"objet" en json et son envoi via la connexion UDP Method SendDataJSONObject(object As%RegisteredObject, format As%String = "iw") As%Status { Try { Set status = ##class(%ZEN.Auxiliary.jsonProvider).%WriteJSONStreamFromObject(.stream,object,,,,format) $$$ThrowOnError(status)

    <span class="hljs-keyword">Set</span> status = <span class="hljs-built_in">..SendDataStream</span>(stream)
}
<span class="hljs-keyword">Catch</span> exception {
    <span class="hljs-keyword">Set</span> status = exception.AsStatus()
}    
<span class="hljs-keyword">Return</span> status

}

/// Un texte est pris en entrée,/// Les traces de l'objet associé sont affichées Method ShowText(text As%String) { Set nbParty = $SYSTEM.SQL.CEILING($LENGTH(text)/1100) For ii=1:1:nbParty { $$$TRACE($EXTRACT(text,ii,ii+1100)) } }

}

J'espère que cet article a été, sinon utile, du moins intéressant.


Je n'ai pas testé EnsLib.UDP.InboundAdapter, donc n'hésitez pas à ajouter plus d'informations à la discussion.
Corentin

2
0 39
Article Iryna Mykhailova · Mai 2, 2025 3m read

Qui n'a jamais développé un bel exemple avec une image IRIS Docker et vu la génération de l'image échouer dans le Dockerfile parce que la licence sous laquelle l'image a été créée ne comportait pas certains privilèges ?

Dans mon cas, je déployais dans Docker une petite application utilisant le type de données Vector. Avec la version Community, ce n'est pas un problème, car elle inclut déjà la recherche et le stockage vectoriels. Cependant, lorsque j'ai remplacé l'image IRIS par une image IRIS classique (latest-cd), j'ai constaté que la compilation de l'image, y compris des classes générées, renvoyait l'erreur suivante :

0
0 24
Article Lorenzo Scalese · Avr 30, 2025 5m read

Après tant d'années d'attente, nous avons enfin un pilote officiel disponible sur Pypi

De plus, j'ai découvert que le pilote JDBC était enfin disponible sur Maven depuis déjà 3 mois,  et le pilote .Net driver - surNuget depuis plus d'un mois.

 La mise en œuvre de la DB-API et que les fonctions devraient au moins être définies par cette norme. La seule différence devrait se situer au niveau de SQL.

Et ce qui est intéressant dans l'utilisation de bibliothèques existantes, c'est qu'elles ont déjà mis en œuvre d'autres bases de données en utilisant le standard DB-API, et que ces bibliothèques s'attendent déjà à ce que le pilote fonctionne.

J'ai décidé de tester le pilote officiel d'InterSystems en mettant en œuvre son support dans la bibliothèque SQLAlchemy-iris.

executemany

Préparez une opération de base de données (requête ou commande) et exécutez-la en fonction de toutes les séquences de paramètres ou de mappages trouvées dans la séquence seq_of_parameters.

Cette fonction très utile permet d'insérer plusieurs lignes à la fois. Commençons par un exemple simple

import iris

host = "localhost" port = 1972 namespace = "USER" username = "_SYSTEM" password = "SYS" conn = iris.connect( host, port, namespace, username, password, )

with conn.cursor() as cursor: cursor = conn.cursor()

res = cursor.execute(<span class="hljs-string">"DROP TABLE IF EXISTS test"</span>)
res = cursor.execute(
    <span class="hljs-string">"""
CREATE TABLE test (
        id IDENTITY NOT NULL,
        value VARCHAR(50)
) WITH %CLASSPARAMETER ALLOWIDENTITYINSERT = 1
"""</span>
)

cursor = conn.cursor()
res = cursor.executemany(
    <span class="hljs-string">"INSERT INTO test (id, value) VALUES (?, ?)"</span>, [
        (<span class="hljs-number">1</span>, <span class="hljs-string">'val1'</span>),
        (<span class="hljs-number">2</span>, <span class="hljs-string">'val2'</span>),
        (<span class="hljs-number">3</span>, <span class="hljs-string">'val3'</span>),
        (<span class="hljs-number">4</span>, <span class="hljs-string">'val4'</span>),
    ]
)</code></pre>

Cela fonctionne bien, mais que se passe-t-il s'il faut insérer une seule valeur par ligne.

    res = cursor.executemany(
        "INSERT INTO test (value) VALUES (?)", [
            ('val1', ),
            ('val2', ),
            ('val3', ),
            ('val4', ),
        ]
    )

Cela conduit malheureusement à une exception inattendue

RuntimeError: Cannot use list/tuple for single values (Impossible d'utiliser une liste/tuple pour des valeurs uniques)

Pour certaines raisons, une seule valeur par ligne est autorisée, et InterSystems demande d'utiliser une méthode différente

    res = cursor.executemany(
        "INSERT INTO test (value) VALUES (?)", [
            'val1',
            'val2',
            'val3',
            'val4',
        ]
    )

De cette façon, cela fonctionne bien

fetchone

Récupère la ligne suivante d'un ensemble de résultats de requête, en renvoyant une seule séquence, ou None lorsqu'il n'y a plus de données disponibles.

Un exemple simple sur sqlite

import sqlite3
con = sqlite3.connect(":memory:")

cur = con.cursor() cur.execute("SELECT 1 one, 2 two") onerow = cur.fetchone() print('onerow', type(onerow), onerow) cur.execute("SELECT 1 one, 2 two union all select '01' as one, '02' as two") allrows = cur.fetchall() print('allrows', type(allrows), allrows)

fournit

onerow <class 'tuple'> (1, 2)
allrows <class 'list'> [(1, 2), ('01', '02')]

Et avec le pilote InterSystems

import iris

con = iris.connect( hostname="localhost", port=1972, namespace="USER", username="_SYSTEM", password="SYS", )

cur = con.cursor() cur.execute("SELECT 1 one, 2 two") onerow = cur.fetchone() print("onerow", type(onerow), onerow) cur.execute("SELECT 1 one, 2 two union all select '01' as one, '02' as two") allrows = cur.fetchall() print("allrows", type(allrows), allrows)

par certaines raisons fournit

onerow <class 'iris.dbapi.DataRow'> <iris.dbapi.DataRow object at 0x104ca4e10>
allrows <class 'tuple'> ((1, 2), ('01', '02'))

Qu'est-ce que DataRow, et pourquoi ne pas utiliser un tuple ou au moins une liste

Exceptions

SLa norme décrit une variété de classes d'exceptions que le pilote est censé utiliser, au cas où quelque chose ne fonctionnerait pas. Or, le pilote InterSystems ne les utilise pas du tout, se contentant de déclencher une erreur RunTime pour toute raison, ce qui, de toute façon, est contraire à la norme.

L'application peut s'appuyer sur le type d'exception qui se produit et se comporter en conséquence. Mais le pilote InterSystems ne fournit aucune différence. Par ailleurs, SQLCODE serait utile, mais il doit être extrait du message d'erreur

Conclusion

Au cours des tests, j'ai donc trouvé plusieurs bogues

  • Erreurs aléatoires survenant à tout moment <LIST ERROR> Format de liste incorrect, type non supporté pour IRISList; Détails : type détecté : 32
    • fonctionnent correctement, si vous réessayez juste après l'erreur
  • Des erreurs de segmentation ont été détectées, je ne sais même pas comment cela se produit
  • Résultat inattendu de la fonction fetchone
  • Fonctionnement inattendu de la fonction executemany, pour une seule ligne de valeur
  • Les exceptions ne sont pas du tout implémentées, des exceptions différentes devraient être générées en cas d'erreurs différentes, et les applications s'appuient sur ces exceptions
  • Python intégré peut être interrompu en cas d'installation à côté d'IRIS
    • en raison du même nom utilisé par Python intégré et ce pilote, il remplace ce qui est déjà installé avec IRIS et peut l'interrompre

SQLAlchemy-iris supporte maintenant le pilote officiel d'InterSystems, mais ceci en raison d'une incompatibilité avec Python intégré et de plusieurs bogues découverts lors des tests. Installation à l'aide de cette commande, avec l'option définie

pip install sqlalchemy-iris[intersystems]

Et pour une utilisation simple, l'URL devrait être iris+intersystems://

from sqlalchemy import Column, MetaData, Table
from sqlalchemy.sql.sqltypes import Integer, VARCHAR
from sqlalchemy import create_engine
from sqlalchemy.orm import DeclarativeBase

DATABASE_URL = "iris+intersystems://_SYSTEM:SYS@localhost:1972/USER" engine = create_engine(DATABASE_URL, echo=True)

# Create a table metadata metadata = MetaData()

classBase(DeclarativeBase):passdefmain(): demo_table = Table( "demo_table", metadata, Column("id", Integer, primary_key=True, autoincrement=True), Column("value", VARCHAR(50)), )

demo_table.drop(engine, checkfirst=<span class="hljs-keyword">True</span>)
demo_table.create(engine, checkfirst=<span class="hljs-keyword">True</span>)
<span class="hljs-keyword">with</span> engine.connect() <span class="hljs-keyword">as</span> conn:
    conn.execute(
        demo_table.insert(),
        [
            {<span class="hljs-string">"id"</span>: <span class="hljs-number">1</span>, <span class="hljs-string">"value"</span>: <span class="hljs-string">"Test"</span>},
            {<span class="hljs-string">"id"</span>: <span class="hljs-number">2</span>, <span class="hljs-string">"value"</span>: <span class="hljs-string">"More"</span>},
        ],
    )
    conn.commit()
    result = conn.execute(demo_table.select()).fetchall()
    print(<span class="hljs-string">"result"</span>, result)

main()

En raison de bogues dans le pilote InterSystems, certaines fonctionnalités peuvent ne pas fonctionner comme prévu. J'espère que cela sera corrigé à l'avenir

0
0 27
Article Sylvain Guilbaud · Avr 25, 2025 22m read

TLS, qu'est-ce que c'est ?

La TLS (Transport Layer Security ou "Sécurité de la couche de transport"), qui succède à SSL (Secure Sockets Layer ou "Couche de sockets sécurisée"), fournit de la sécurité (c'est-à-dire le chiffrement et l'authentification) sur une connexion TCP/IP. Si vous avez déjà remarqué le "s" sur les URLs "https" vous avez reconnu une connexion HTTP "sécurisée" par SSL/TLS. Dans le passé, seules les pages de connexion/autorisation sur le web utilisaient TLS, mais dans l'environnement hostile d'Internet d'aujourd'hui, les meilleures pratiques indiquent que nous devrions sécuriser toutes les connexions avec TLS.

Pourquoi utiliser TLS?

Alors, pourquoi mettre en œuvre TLS pour les connexions HL7 ? Alors que les violations de données, les rançongiciels et les vulnérabilités sont de plus en plus fréquents, chaque mesure que vous prenez pour renforcer la sécurité de ces précieuses sources de données devient plus cruciale. La TLS est une méthode éprouvée et bien comprise pour protéger les données en transit.

TLS fournit deux fonctionnalités principales qui nous sont bénéfiques : 1) le chiffrement et 2) l'authentification.

Chiffrement

Le chiffrement transforme les données en cours de transfert de sorte que seules les deux parties engagées dans la communication peuvent lire/comprendre les informations échangées. Dans la plupart des cas, seules les applications impliquées dans la connexion TLS peuvent interpréter les données transférées. Cela signifie que les acteurs malveillants opérant sur les serveurs ou réseaux de communication ne pourront pas lire les données, même s'ils parviennent à capturer les paquets TCP bruts à l'aide d'un renifleur de paquets (wiretap, wireshark, tcpdump, etc.).

Without TLS

Authentification

L'authentification garantit que chaque partie communique avec la partie prévue et non avec un imposteur. En s'appuyant sur l'échange de certificats (et la vérification de la preuve de propriété associée qui s'est produite lors d'un handshake TLS), lorsque vous utilisez TLS, vous pouvez être sûr que vous échangez des données avec une partie de confiance. Plusieurs attaques consistent à tromper un serveur pour qu'il communique avec un acteur malveillant en redirigeant le trafic vers le mauvais serveur (par exemple, l'emploi de DNS et d'ARP poisoning) Lorsque TLS est impliqué, les imposteurs doivent non seulement rediriger le trafic, mais aussi voler les certificats et les clés appartenant à la partie de confiance.

L'authentification protège non seulement contre les attaques intentionnelles de pirates informatiques ou de acteurs malveillants, mais aussi contre les erreurs de configuration accidentelles qui pourraient envoyer des données vers le ou les mauvais systèmes. Par exemple, si vous attribuez accidentellement l'adresse IP d'une connexion HL7 à un serveur qui n'utilise pas le certificat attendu, la vérification de la négociation TLS échouera avant l'envoi de données vers ce mauvais serveur.

Vérification d'hôte

Lors de la vérification, les clients ont la possibilité d'effectuer une vérification d'hôte. Cette vérification compare l'adresse IP ou le nom d'hôte utilisé dans la connexion avec les adresses IP et les noms d'hôte intégrés dans le certificat. Si cette vérification est activée et que l'adresse IP/l'hôte de la connexion ne correspond pas à une adresse IP/un hôte figurant dans le certificat, le handshake TLS échouera. Vous trouverez les adresses IP et les noms d'hôte dans les champs X.509 « Subject » et « Subject Alternative Name » présentés ci-dessous.

Preuve de la propriété d'un certificat avec une clé privée

Pour prouver la propriété des certificats échangés avec TLS, vous devez également avoir accès à la clé privée liée à la clé publique intégrée au certificat. Nous ne discuterons pas de la cryptographie employée pour la preuve de propriété avec une clé privée, mais vous devez savoir que l'accès à la clé privée de votre certificat est nécessaire pendant le handshake TLS.

TLS mutuel

Pour la plupart des connexions https établies par votre navigateur web, seul le certificat d'authenticité du serveur web est vérifié. Normalement, les serveurs web n'authentifient pas le client avec des certificats. Au lieu de cela, la plupart des serveurs web s'appuient sur l'authentification du client au niveau de l'application (formulaires de connexion, cookies, mots de passe, etc.).

Avec HL7, il est préférable que les deux côtés de la connexion soient authentifiés. Lorsque les deux côtés sont authentifiés, on parle de «TLS mutuel». Avec le TLS mutuel, le serveur et le client échangent leurs certificats et l'autre côté vérifie les certificats fournis avant de poursuivre la connexion et l'échange de données.

X.509 Certificats

X.509 Champs du certificat

Pour fournir le cryptage et l'authentification, les informations sur la clé publique et l'identité de chaque partie sont échangées dans des certificats [X.509] (https://en.wikipedia.org/wiki/X.509). Vous trouverez ci-dessous certains champs courants d'un certificat X.509 qui nous intéresseront:

  • Serial Number: numéro unique à un CA qui identifie ce certificat spécifique
  • Subject Public Key Info: clé publique du propriétaire
  • Subject: nom distinctif (DN) du serveur/service représenté par ce certificat
    • Ce champ peut être vide si des "Subject Alternative Names" (noms alternatifs du sujet) sont fournis.
  • Issuer: nom distinctif (DN) du CA qui a émis/signé ce certifica
  • Validity Not Before: date de mise en vigueur de ce certificat
  • Validity Not After: date d'expiration de ce certificat
  • Basic Constraints: indique s'il s'agit d'un CA ou non
  • Key Usage: l'utilisation prévue de la clé publique fournie par ce certificat
    • Valeurs d'exemple: digitalSignature, contentCommitment, keyEncipherment, dataEncipherment, keyAgreement, keyCertSign, cRLSign, encipherOnly, decipherOnly
  • Extended Key Usage: utilisations supplémentaires prévues de la clé publique fournie par ce certificat
    • Valeurs d'exemple: serverAuth, clientAuth, codeSigning, emailProtection, timeStamping, OCSPSigning, ipsecIKE, msCodeInd, msCodeCom, msCTLSign, msEFS
    • Pour les connexions TLS mutuelles, les deux modes d'utilisation serverAuth et clientAuth sont nécessaires.
  • Subject Key Identifier: identifie la clé publique du sujet fournie par ce certificat
  • Authority Key Identifier: identifie la clé publique du fournisseur utilisée pour vérifier ce certificat
  • Subject Alternative Name: contient un ou plusieurs noms alternatifs pour ce sujet
    • Les noms DNS et les adresses IP sont des noms alternatifs fréquemment fournis dans ce champ.
    • Subject Alternative Name est parfois abrégé en SAN.
    • Le nom DNS ou l'adresse IP utilisés dans la connexion doivent figurer dans cette liste ou dans le Common Name du Subject pour que la vérification de l'hôte soit réussie.

Noms distingués

Les champs Subject (Sujet) et Issuer (Émetteur) d'un certificat X.509 sont définis comme des Distinguished Names (DN, Noms Distingués). Les noms distingués sont constitués de plusieurs attributs, chaque attribut ayant le format <attr>=<value>. Voici une liste non exhaustive des attributs courants que l'on trouve dans les champs Subject et Issuer

AbréviationNomExempleRemarques
CNNom communCN=server1.domain.comLe nom de domaine complet (FQDN) d'un serveur/service
CPaysC=USCode pays à deux caractères
STÉtat (ou province)ST=MassachusettsNom complet de l'état/province
LLocalitéL=CambridgeVille, région, etc.
OOrganisationO=Best CorporationNom de l'organisation
OUUnité opérationnelleOU=FinanceDépartment, division, etc.

Selon les exemples du tableau ci-dessus, le DN complet pour cet exemple serait C=US, ST=Massachusetts, L=Cambridge, O=Best Corporation, OU=Finance, CN=server1.domain.com

Notez que le Common Name (nom commun) trouvé dans le Subject (sujet) est utilisé lors de la vérification de l'hôte et correspond normalement au nom de domaine complet (FQDN) du serveur ou du service associé au certificat. Les Subject Alternative Names (noms alternatifs du sujet) du certificat peuvent également être utilisés lors de la vérification de l'hôte.

Expiration du certificat

Les champs Validity Not Before (Validité avant la date) et Validity Not After (Validité après la date) du certificat fournissent une plage de dates entre lesquelles le certificat est valide

Normalement, les certificats feuille ont une validité d'un ou deux ans (bien que les sites Web soient encouragés à réduire leurs délais d'expiration à des périodes beaucoup plus courtes). Les autorités de certification ont généralement un délai d'expiration de plusieurs années.

L'expiration des certificats est une fonctionnalité TLS nécessaire mais peu pratique. Avant d'ajouter TLS à vos connexions HL7, assurez-vous d'avoir un plan pour remplacer les certificats avant leur expiration. Une fois qu'un certificat expire, vous ne pourrez plus établir de connexion TLS à l'aide de celui-ci.

Formats de certificat X.509

Les champs de ces certificats X.509 (ainsi que d'autres) sont structurés suivant le format ASN.1 et généralement enregistrés dans l'un des formats de fichier suivants :

Exemple d'encodage PEM d'un certificat X.509:

-----BEGIN CERTIFICATE-----
MIIEVTCCAz2gAwIBAgIQMm4hDSrdNjwKZtu3NtAA9DANBgkqhkiG9w0BAQsFADA7
MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZpY2VzMQww
CgYDVQQDEwNXUjIwHhcNMjUwMTIwMDgzNzU0WhcNMjUwNDE0MDgzNzUzWjAZMRcw
FQYDVQQDEw53d3cuZ29vZ2xlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA
BDx/pIz8HwLWsWg16BG6YqeIYBGof9fn6z6QwQ2v6skSaJ9+0UaduP4J3K61Vn2v
US108M0Uo1R1PGkTvVlo+C+jggJAMIICPDAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0l
BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU3rId2EvtObeF
NL+Beadr56BlVZYwHwYDVR0jBBgwFoAU3hse7XkV1D43JMMhu+w0OW1CsjAwWAYI
KwYBBQUHAQEETDBKMCEGCCsGAQUFBzABhhVodHRwOi8vby5wa2kuZ29vZy93cjIw
JQYIKwYBBQUHMAKGGWh0dHA6Ly9pLnBraS5nb29nL3dyMi5jcnQwGQYDVR0RBBIw
EIIOd3d3Lmdvb2dsZS5jb20wEwYDVR0gBAwwCjAIBgZngQwBAgEwNgYDVR0fBC8w
LTAroCmgJ4YlaHR0cDovL2MucGtpLmdvb2cvd3IyLzlVVmJOMHc1RTZZLmNybDCC
AQMGCisGAQQB1nkCBAIEgfQEgfEA7wB2AE51oydcmhDDOFts1N8/Uusd8OCOG41p
wLH6ZLFimjnfAAABlIMTadcAAAQDAEcwRQIgf6SEH+xVO+nGDd0wHlOyVTbmCwUH
ADj7BJaSQDR1imsCIQDjJjt0NunwXS4IVp8BP0+1sx1BH6vaxgMFOATepoVlCwB1
AObSMWNAd4zBEEEG13G5zsHSQPaWhIb7uocyHf0eN45QAAABlIMTaeUAAAQDAEYw
RAIgBNtbWviWZQGIXLj6AIEoFKYQW4pmwjEfkQfB1txFV20CIHeouBJ1pYp6HY/n
3FqtzC34hFbgdMhhzosXRC8+9qfGMA0GCSqGSIb3DQEBCwUAA4IBAQCHB09Uz2gM
A/gRNfsyUYvFJ9J2lHCaUg/FT0OncW1WYqfnYjCxTlS6agVUPV7oIsLal52ZfYZU
lNZPu3r012S9C/gIAfdmnnpJEG7QmbDQZyjF7L59nEoJ80c/D3Rdk9iH45sFIdYK
USAO1VeH6O+kAtFN5/UYxyHJB5sDJ9Cl0Y1t91O1vZ4/PFdMv0HvlTA2nyCsGHu9
9PKS0tM1+uAT6/9abtqCBgojVp6/1jpx3sx3FqMtBSiB8QhsIiMa3X0Pu4t0HZ5j
YcAkxtIVpNJ8h50L/52PySJhW4gKm77xNCnAhAYCdX0sx76eKBxB4NqMdCR945HW
tDUHX+LWiuJX
-----END CERTIFICATE-----

Comme vous pouvez le voir, l'encodage PEM ajoute -----BEGIN CERTIFICATE----- et -----END CERTIFICATE----- aux données ASN.1 du certificat encodées en base64.

Établir la confiance avec les autorités de certification

Sur l'Internet ouvert, il serait impossible pour votre navigateur Web de connaître et de faire confiance au certificat de chaque site Web. Il y en a tout simplement trop! Pour contourner ce problème, votre navigateur Web délègue la confiance à un ensemble prédéterminé d'autorités de certification (AC). Les autorités de certification sont des entités qui vérifient qu'une personne demandant un certificat pour un site Web ou un domaine est bien propriétaire et responsable du serveur, du domaine ou des activités commerciales associés à la demande de certificat. Une fois que l'autorité de certification a vérifié un propriétaire, elle est en mesure d'émettre le certificat demandé.

Chaque autorité de certification est représentée par un ou plusieurs certificats X.509. Ces certificats CA sont utilisés pour signer tous les certificats émis par la CA. Si vous regardez dans le champ Issuer (Émetteur) d'un certificat X.509, vous trouverez une référence au certificat CA qui a créé et signé ce certificat.

Si un certificat est créé sans autorité de certification, il est appelé certificat auto-signé. Vous savez qu'un certificat est auto-signé si les champs Subject (Sujet) et Issuer (Émetteur) du certificat sont identiques.

En général, la CA crée un certificat root (racine) auto-signé avec une longue fenêtre d'expiration. Ce certificat racine est ensuite utilisé pour générer quelques autorités de certification intermédiaires, qui ont une fenêtre d'expiration légèrement plus courte. La CA racine sera sécurisée et rarement utilisée après la création des CA intermédiaires. Les CA intermédiaires seront utilisées pour émettre et signer les certificats leaf (feuille) au quotidien.

Les CA intermédiaires sont créées au lieu d'utiliser directement la CA racine afin de minimiser l'impact en cas de violation ou de mauvaise gestion d'un certificat. Si une seule CA intermédiaire est compromise, l'entreprise aura toujours les autres CA disponibles pour continuer à fournir le service.

Chaînes de certificats

Un certificat de connexion et tous les certificats CA impliqués dans l'émission et la signature de ce certificat peuvent être organisés en une structure appelée chaîne de certificats. Cette chaîne de certificats (décrite ci-dessous) sera utilisée pour vérifier et approuver le certificat de connexion.

Si vous suivez le certificat feuille d'une connexion jusqu'à la CA émettrice (en utilisant le champ Issuer) puis, à partir de cette CA, jusqu'à son émetteur (et ainsi de suite, jusqu'à ce que vous atteigniez un certificat racine auto-signé), vous aurez parcouru la chaîne de certificats.

Construction d'une chaîne de certificats

Faire confiance à un certificat

Votre navigateur Web et votre système d'exploitation conservent généralement une liste d'autorités de certification approuvées. Lors de la configuration d'une interface HL7 ou d'une autre application, vous dirigerez probablement votre interface vers un fichier CA-bundle contenant une liste de CA approuvées. Ce fichier contiendra généralement une liste d'un ou plusieurs certificats CA encodés au format PEM. Par exemple:

# Probablement, une CA intermédiaire
-----BEGIN CERTIFICATE-----
MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF
...
rqXRfboQnoZsG4q5WTP468SQvvG5
-----END CERTIFICATE-----

# Probablement, une CA racine
-----BEGIN CERTIFICATE-----
MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV
...
WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
-----END CERTIFICATE-----

Lorsque votre navigateur Web (ou l'interface HL7) tente d'établir une connexion TLS, il utilise cette liste de certificats CA de confiance pour déterminer s'il fait confiance au certificat échangé lors du handshake TLS.

Le processus commence par le certificat racine et traverse la chaîne de certificats jusqu'au certificat CA suivant. Si le certificat CA n'est pas trouvé dans le magasin de confiance ou le fichier CA-bundle, le certificat racine n'est pas considéré comme fiable et la connexion TLS échoue.

Si le certificat CA ou le fichier CA-bundle est trouvé dans le magasin de confiance, le processus continue en remontant la chaîne de certificats, en vérifiant que chaque CA se trouvant sur le chemin est dans le magasin de confiance. Une fois que le certificat CA racine au sommet de la chaîne est vérifié (ainsi que tous les certificats CA intermédiaires se trouvant sur le chemin), le processus peut approuver le certificat feuille du serveur.

Détermination de la confiance

Le handshake TLS

Pour ajouter TLS à une connexion TCP/IP (comme un flux HL7), le client et le serveur doivent effectuer un handshake TLS après que la connexion TCP/IP a été établie. Ce handshake implique de s'accorder sur les chiffrements/méthodes de chiffrement, de s'accorder sur la version TLS, d'échanger des certificats X.509, de prouver la propriété de ces certificats et de valider que chaque partie fait confiance à l'autre.

Les étapes principales d'un handshake TLS sont les suivantes:

  1. Le client établit une connexion TCP/IP avec le serveur.
  2. Le client lance le handshake TLS.
  3. Le serveur envoie son certificat (et la preuve de sa propriété) au client.
  4. Le client vérifie le certificat du serveur.
  5. En cas de TLS mutuel, le client envoie son certificat (et la preuve de sa propriété) au serveur.
  6. En cas de TLS mutuel, le serveur vérifie le certificat du client.
  7. Le client et le serveur s'échangent des données encryptées.

Handshake TLS

1. Le client établit une connexion TCP/IP avec le serveur.

À l'étape n° 1, le client et le serveur effectuent un handshake TCP à la procédure de base « ternaire » [TCP 3-way handshake] (https://en.wikipedia.org/wiki/Transmission_Control_Protocol#Connection_establishment) pour établir une connexion TCP/IP entre eux. Dans un handshake à la procédure de base ternaire:

  1. Le client envoie un paquet SYN.
  2. Le serveur envoie un paquet SYN-ACK.
  3. Le client envoie un paquet ACK.

Une fois ce handshake terminé, la connexion TCP/IP est établie. L'étape suivante consiste à lancer le handshake TLS.

2. Le client lance le handshake TLS.

Une fois la connexion TCP établie, l'une des parties doit agir en tant que client et lancer le handshake TLS. Généralement, le processus qui a initié la connexion TCP est également responsable du lancement du handshake TLS, mais cela peut être inversé dans de rares cas.

Pour lancer le handshake TLS, le client envoie un message ClientHello au serveur. Ce message contient diverses options utilisées pour négocier les paramètres de sécurité de la connexion avec le serveur.

3. Le serveur envoie son certificat (et la preuve de sa propriété) au client.

Après avoir reçu le message ClientHello du client, le serveur répond à son tour par un message ServerHello. Celui-ci inclut les paramètres de sécurité négociés.

Après le message ServerHello, le serveur envoie également un message Certificate et CertificateVerify au client. Cela permet de partager la chaîne de certificats X.509 avec le client et de fournir la preuve de propriété de la clé privée associée au certificat.

4. Le client vérifie le certificat du serveur.

Une fois que le client a reçu les messages ServerHello, Certificate et CertificateVerify, il vérifie que le certificat est valide et approuvé (en comparant les CAs aux fichiers CA-bundle approuvés, au magasin de certificats du système opérationnel ou au magasin de certificats du navigateur web). Le client effectue également toute vérification de l'hôte (voir ci-dessus) pour s'assurer que l'adresse de connexion correspond aux adresses/IP du certificat.

5. S'il s'agit d'une connexion TLS mutuelle, le client envoie son certificat (et la preuve de propriété) au serveur.

S'il s'agit d'une connexion TLS mutuelle (déterminée par l'envoi d'un message CertificateRequest par le serveur), le client enverra un message Certificate incluant sa chaîne de certificats, puis un message CertificateVerify pour prouver qu'il est le propriétaire de la clé privée associée.

6. S'il s'agit d'une connexion TLS mutuelle, le serveur vérifie le certificat client.

Là encore, s'il s'agit d'une connexion TLS mutuelle, le serveur vérifie que la chaîne de certificats envoyée par le client est valide et approuvée.

7. Le client et le serveur s'échangent des données encryptées.

Si la négociation TLS se déroule sans erreur, le client et le serveur s'échangent des messages Finished (Terminé) pour achever la négociation. Après cela, les données encryptées peuvent être échangées entre le client et le serveur.

Configuration de TLS sur les interfaces HL7

Félicitations d'être arrivé jusqu'ici ! Maintenant que vous savez en quoi consiste TLS, comment procéderiez-vous pour mettre en œuvre le protocole TLS sur vos connexions HL7 ? De manière générale, voici les étapes à suivre pour configurer TLS sur vos connexions HL7.

  1. Choisissez une autorité de certification.
  2. Créez une clé et une demande de signature de certificat.
  3. Obtenez votre certificat auprès de votre CA.
  4. Obtenez la chaîne de certificats pour votre pair.
  5. Créez une configuration SSL pour la connexion.
  6. Ajoutez la configuration SSL à l'interface, faites rebondir l'interface et vérifiez le flux de messages.

1. Choisissez une autorité de certification.

La procédure que vous utiliserez pour obtenir un certificat et une clé pour votre serveur dépendra largement des politiques de sécurité de votre entreprise. Dans la plupart des cas, votre certificat sera signé par l'une des autorités de certification suivantes:

  1. Votre certificat sera signé par une CA interne à l'entreprise.
  • C'est mon option préférée, car votre entreprise dispose déjà de l'infrastructure nécessaire pour gérer les certificats et les CAs. Il vous suffit de travailler avec l'équipe qui possède cette infrastructure pour obtenir votre propre certificat pour vos interfaces HL7.
  1. Votre certificat sera signé par une CA publique.
  • Cette option est intéressante dans le sens où la CA publique dispose également de toute l'infrastructure nécessaire pour maintenir les certificats et les CAs. Cette option est sans doute exagérée pour la plupart des interfaces HL7, car les CA publiques fournissent généralement des certificats pour l'Internet ouvert ; les interfaces HL7 ont tendance à se connecter via un intranet privé, et non via l'Internet public.
  • L'obtention de certificats auprès d'une CA publique peut également entraîner des frai.
  1. Votre certificat sera signé par une CA que vous créerez et maintiendrezvous-même.
  • Cette option peut vous convenir, mais malheureusement, cela signifie que vous supportez la charge de la maintenance et de la sécurisation de votre configuration CA et de votre logiciel.
  • Vous l'utilisez à vos risques et périls!
  • Cette option est la plus complexe. Préparez-vous à une courbe d'apprentissage abrupte.
  • Vous pouvez utiliser des progiciels open source éprouvés pour gérer votre CA et vos certificats. La suite OpenSSL est une excellente option. Les autres options sont EJBCA, step-ca et cfssl.

2. Créez une clé et une demande de signature de certificat.

Après avoir choisi votre CA, l'étape suivante consiste à créer une clé privée et une demande de signature de certificat (CSR) . La manière dont vous générez la clé et la CSR dépendra de la politique de votre entreprise et de la CA choisie. Pour l'instant, nous allons simplement parler des étapes de manière générale.

Lors de la génération d'une clé privée, la clé publique associée est également générée. La clé publique sera intégrée à votre CSR et à votre certificat signé. Ces deux clés seront utilisées pour prouver la propriété de votre certificat signé lors de l'établissement d'une connexion TLS.

ATTENTION! Veillez à enregistrer votre clé privée dans un endroit sûr (de préférence dans un format protégé par un mot de passe). Si vous perdez cette clé, votre certificat ne sera plus utilisable. Si quelqu'un d'autre accède à cette clé, il pourra se faire passer pour votre serveur.

La demande de signature de certificat inclura des informations sur votre serveur, votre entreprise, votre clé publique, la manière d'utiliser le certificat, etc. Elle inclura également la preuve que vous possédez la clé privée associée. Cette CSR sera ensuite fournie à votre CA pour générer et signer votre certificat.

REMARQUE: lors de la création de la CSR, assurez-vous de demander une Extended Key Usage (utilisation étendue de la clé) à la fois pour serverAuth et clientAuth, si vous utilisez le TLS mutuel. La plupart des CA sont habituées à signer des certificats avec uniquement la clé serverAuth. Malheureusement, cela signifie que le certificat ne peut pas être utilisé comme certificat client dans une connexion TLS mutuelle.

3. Obtenez votre certificat auprès de votre CA.

Après avoir créé votre clé et votre CSR, soumettez la CSR à votre autorité de certification. Après avoir effectué plusieurs vérifications, votre CA devrait être en mesure de vous fournir un certificat signé et la chaîne de certificats associée. Ce certificat et cette chaîne doivent être enregistrés au format PEM. Si la CA a fourni votre certificat dans un format différent, vous devrez le convertir à l'aide d'un outil tel qu'OpenSSL.

4. Obtenez la chaîne de certificats pour votre homologue.

Les étapes précédentes étaient axées sur l'obtention d'un certificat pour votre serveur. Vous devriez pouvoir utiliser ce certificat (et la clé associée) avec chaque connexion HL7 vers/depuis ce serveur. Vous devrez également obtenir les chaînes de certificats pour chacun des systèmes/homologues auxquels vous vous connecterez.

Les chaînes de certificats de chaque homologue devront être enregistrées dans un fichier au format PEM. Ce CA-bundle n'aura pas besoin de contenir les certificats feuille ; il doit uniquement contenir les certificats CA intermédiaires et racine.

Veillez à fournir à votre homologue un CA-bundle contenant vos CA intermédiaires et racine. Cela lui permettra de faire confiance à votre certificat lorsque vous établirez une connexion.

5. Créez une configuration SSL pour la connexion.

Dans Health Connect d'InterSystems, il vous faudra créer des configurations SSL client et serveur pour chaque système auquel votre serveur se connectera. Ces configurations SSL dirigeront vers le fichier CA-bundle du système associé et vers les fichiers clé et de certificat de votre serveur.

Les configurations SSL client sont utilisées lors des opérations pour lancer le handshake TLS. Les configurations SSL serveur sont utilisées sur les services pour répondre aux handshakes TLS. Si un système dispose à la fois de services entrants et de services sortants, il faudra configurer à la fois une configuration SSL client et une configuration SSL serveur pour ce système.

Pour créer une configuration SSL client:

  1. Accédez à System Administration > Security > SSL/TLS Configurations (Administration système > Sécurité > Configurations SSL/TLS).
  2. Appuyeze sur Create New Configuration (Créer une nouvelle configuration).
  3. Donnez un Configuration Name (Nom de configuration) et une Description (Description) à votre configuration SSL.
  4. Assurez-vous que votre configuration SSL est Enabled (Activée).
  5. Choisissez Client comme Type.
  6. Choisissez Require (Obligatoire) pour le champ Server certificate verification (Vérification du certificat serveur). Cela effectue une vérification de l'hôte sur la connexion.
  7. Dirigez le champ File (Fichier) contenant le(s) certificat(s) CA de confiance vers le fichier CA-bundle contenant les CA intermédiaires et racines (au format PEM) du système auquel vous vous connectez.
  8. Dirigez le champ File (Fichier) contenant le certificat de ce client vers le fichier contenant le certificat X.509 de votre serveur au format PEM.
  9. Dirigez le champ File (Fichier) contenant la clé privée associée vers le fichier contenant la clé privée de votre certificat.
  10. Le Private key type (type de clé privée) sera très probablement RSA (chiffrement RSA). Cela devrait correspondre au type de votre clé privée.
  11. Si votre clé privée est protégée par un mot de passe (comme cela devrait être le cas), saisissez le mot de passe dans les champs Private key password (mot de passe de la clé privée) et Private key password (confirm) (confirmer le mot de passe de la clé privée).
  12. Vous pouvez probablement laisser les autres champs à leurs valeurs par défaut.

Pour créer une configuration de serveur SSL:

  1. Go to System Administration > Security > SSL/TLS Configurations.
  2. Appuyeze sur Create New Configuration (Créer une nouvelle configuration).
  3. Donnez un Configuration Name (Nom de configuration) et une Description (Description) à votre configuration SSL.
  4. Assurez-vous que votre configuration SSL est Enabled (Activée).
  5. Choisissez Server comme Type.
  6. Choisissez Require (Obligatoire) pour le champ Client certificate verification (Vérification du certificat client). Cela permettra de s'assurer que le TLS mutuel est exécuté.
  7. Dirigez File containing trusted Certificate Authority certificate(s) (Fichier contenant le(s) certificat(s) de l'autorité de certification de confiance) vers le fichier CA-bundle contenant les CA intermédiaires et racines (au format PEM) du système auquel vous vous connectez.
  8. Dirigez File containing this server's certificate (Fichier contenant le certificat de ce serveur) vers le fichier contenant le certificat X.509 de votre serveur au format PEM.
  9. Dirigez File containing associated private key (Fichier contenant la clé privée associée) vers le fichier contenant la clé privée de votre certificat.
  10. Le Private key type (type de clé privée) sera très probablement RSA (chiffrement RSA). Cela devrait correspondre au type de votre clé privée.
  11. Si votre clé privée est protégée par un mot de passe (comme cela devrait être le cas), saisissez le mot de passe dans les champs Private key password (mot de passe de la clé privée) et Private key password (confirm) (confirmer le mot de passe de la clé privée).
  12. Vous pouvez probablement laisser les autres champs à leurs valeurs par défaut.

configuration de configuration SSL

6. Ajoutez la configuration SSL à l'interface, relancez l'interface et vérifiez le flux de messages.

Une fois que vous avez créé les configurations SSL client et serveur, vous êtes prêt à activer TLS sur les interfaces. Pour chaque service ou opération, choisissez la configuration SSL associée dans le menu déroulant Connection Settings > SSL Configuration (Paramètres de connexion > Configuration SSL) qui se trouve dans l'onglet Settings (Paramètres) de l'interface.

Après avoir relancé l'interface, vous verrez la connexion se rétablir. Lorsqu'un nouveau message est transféré, un statut Completed (Terminé) indique que TLS fonctionne. Si TLS ne fonctionne pas, la connexion sera interrompue à chaque tentative de message.

Pour vous aider à déboguer les problèmes avec TLS, il se peut que vous ayez besoin d'utiliser des outils tels que tcpdump, Wireshark ou l'utilitaire s_client d'OpenSSL.

Conclusion

Nous avons fait une analyse très approfondie du sujet SSL/TLS. Il y a tellement d'autres informations qui n'ont pas été incluses dans cet article. J'espère que cet article vous a fourni un aperçu suffisant du fonctionnement de TLS pour que vous puissiez rechercher les détails et obtenir plus d'informations si nécessaire.

Si vous recherchez une ressource approfondie sur TLS, consultez le site Web d'Ivan Ristić, fiestyduck.com et son livre, Bulletproof TLS and PKI. J'ai trouvé que ce livre était une excellente ressource pour en savoir plus sur l'utilisation de TLS.

0
0 48
Annonce Adeline Icard · Avr 24, 2025

InterSystems IRIS 2025.2.0 introduit plusieurs fonctionnalités pour améliorer l'expérience utilisateur lors de la configuration d'OAuth2.

- OAuth2 est désormais un type d'authentification natif et peut être facilement activé pour vos services et applications web. Auparavant, OAuth2 était un type d'authentification déléguée.

- Vous pouvez désormais créer des serveurs de ressources avec la nouvelle classe OAuth2.ResourceServer, qui simplifie considérablement la configuration des serveurs de ressources. Auparavant, les serveurs de ressources étaient des instances d'OAuth2.Client.

0
0 23
InterSystems officiel Adeline Icard · Avr 23, 2025

Les versions de maintenance 2024.1.4 et 2023.1.6 de la plateforme de données InterSystems IRIS®, d'InterSystems IRIS® for HealthTMet de HealthShare® Health Connect sont désormais disponibles en disponibilité générale (GA). Ces versions incluent les correctifs pour l'alerte suivante récemment émise : Alerte : Requêtes SQL renvoyant des résultats erronés | InterSystems. N'hésitez pas à partager vos commentaires via la Communauté des développeurs afin que nous puissions développer ensemble un meilleur produit.

Documentation

0
0 52
Article Sylvain Guilbaud · Avr 22, 2025 3m read

Rubrique FAQ InterSystems

Les variables globales temporaires stockées dans les bases de données IRISTEMP/CACHETEMP sont utilisées lorsqu'un processus n'a pas besoin de stocker des données indéfiniment, mais requiert les performances élevées des variables globales. Les bases de données IRISTEMP/CACHETEMP ne sont pas journalisées ; leur utilisation ne crée donc pas de fichiers journaux.

Le système utilise les bases de données IRISTEMP/CACHETEMP pour le stockage temporaire et les utilisateurs peuvent y accéder à cette fin.

0
0 30
Article Iryna Mykhailova · Avr 18, 2025 9m read

IRIS propose une fonctionnalité dédiée à la gestion des documents JSON, appelée DocDB.

Plateforme de données DocDB d'InterSystems IRIS® est une fonctionnalité permettant de stocker et de récupérer des données de base de données. Elle est compatible avec le stockage et la récupération de données de tables et de champs SQL traditionnels (classe et propriété), mais en est distincte. Elle est basée sur JSON (JavaScript Object Notation) qui prend en charge l'échange de données sur le Web. InterSystems IRIS prend en charge le développement de bases de données et d'applications DocDB en REST et en ObjectScript, ainsi que le support SQL pour la création ou l'interrogation de données DocDB.

De par sa nature, la base de données documentaire InterSystems IRIS est une structure de données sans schéma. Cela signifie que chaque document a sa propre structure, qui peut différer de celle des autres documents de la même base de données. Cela présente plusieurs avantages par rapport au SQL, qui nécessite une structure de données prédéfinie.

Le mot « document » est utilisé ici comme un terme technique spécifique à l'industrie, en tant que structure de stockage de données dynamique. Le « document », tel qu'utilisé dans DocDB, ne doit pas être confondu avec un document textuel ou avec la documentation.

Voyons comment DocDB peut permettre de stocker JSON dans la base de données et de l'intégrer dans des projets qui reposent uniquement sur des protocoles xDBC.

Commençons!

DocDB définit deux composants clés:

  • %DocDB.Database - Bien qu'il s'attende à la création d'une "base de données", ce qui peut prêter à confusion puisque nous avons déjà une base de données en termes SQL, il s'agit essentiellement d'une classe en ObjectScript. Pour ceux qui sont plus familiers avec SQL, elle fonctionne comme une table.
  • %DocDB.Document - Classe de base pour une 'base de données' qui étend la classe %Persistent et introduit des propriétés spécifiques à DocDB:
    • %DocumentId - IdKey
    • %Doc As %DynamicAbstractObject - Le stockage actuel du document JSON
    • %LastModified - Un horodatage mis à jour automatiquement pour chaque insertion et mise à jour

Création d'une table (base de données)

Passons maintenant à la création de notre première table, ou plutôt de notre première « base de données ». Il semble que l'on ne s'attendait pas à la création d'une base de données DocDB.Database uniquement à l'aide de SQL. Par conséquent, il n'est pas possible de créer une nouvelle « base de données » en utilisant uniquement SQL. Pour le vérifier, nous allons utiliser une approche ObjectScript classique. Voici un exemple de définition d'une classe qui étend %DocDB.Document:

Class User.docdb Extends%DocDB.Document [ DdlAllowed ]
{

}

La vérification de la table nouvellement créée à l'aide de SQL permet de s'assurer de son bon fonctionnement.

Il est temps de faire un premier essai et d'insérer quelques données

Nous pouvons insérer n'importe quelles données sans validation, ce qui signifie qu'il n'y a aucune restriction sur ce qui peut être inséré dans %Doc. La mise en place d'une validation serait bénéfique.

Extraction de valeurs d'un document

La base de données %DocDB.Database permet d'extraire des propriétés des documents et de les rendre disponibles sous forme de colonnes dédiées. Cela permet également d'effectuer une indexation sur ces propriétés.

Il faudrait d'abord obtenir la base de données.

USER>set docdb=##class(%DocDB.Database).%GetDatabase("User.docdb")

<THROW>%GetDatabase+5^%DocDB.Database.1 *%Exception.StatusException ERROR #25351: DocDB Database 'User.docdb' does not exist.

USER 2e1>w $SYSTEM.DocDB.Exists("User.docdb") 0

Euh, la base de données "n'existe pas", d'accord, créons-la alors

USER>set docdb=##class(%DocDB.Database).%CreateDatabase("User.docdb")

<THROW>%CreateDatabase+13^%DocDB.Database.1 *%Exception.StatusException ERROR #25070: The generated class name for the database 'User.docdb' conflicts with another class: User.docdb USER 2e1>

Ainsi, une simple définition de classe ne suffit pas. Il faut utiliser %DocDB.Database dès le début, ce qui n'est pas pratique, surtout lors de l'utilisation du contrôle de code source.

Pour résoudre ce problème, nous supprimons la classe existante et créons correctement la base de données:

USER>do $system.OBJ.Delete("User.docdb")

Deleting class User.docdb USER>set docdb=##class(%DocDB.Database).%CreateDatabase("User.docdb")

USER>zwrite docdb docdb=6@%DocDB.Database ; <OREF,refs=1> +----------------- general information --------------- | oref value: 6 | class name: %DocDB.Database | %%OID: $lb("3","%DocDB.Database") | reference count: 1 +----------------- attribute values ------------------ | %Concurrency = 1 <Set> | ClassName = "User.docdb" | DocumentType = "" | Name = "User.docdb" | Resource = "" | SqlNameQualified = "SQLUser.docdb" +-----------------------------------------------------

Cette fois, cela fonctionne et les données précédemment insérées restent intactes.

Supposons que nous ayons un document comme celui-ci

{"name":"test", "some_value":12345}

Extrayons ces deux champs à l'aide de la méthode %CreateProperty

USER>do docdb.%CreateProperty("name","%String","$.name",0)

USER>do docdb.%CreateProperty("someValue","%String","$.some_value",0)

Et vérifions la table

En vérifiant cette table, nous constatons que deux nouvelles colonnes ont été ajoutées, mais que celles-ci contiennent des valeurs nulles. Il semble que ces propriétés ne s'appliquent pas rétroactivement aux données existantes. Si un développeur ajoute ultérieurement des propriétés et des index à des fins d'optimisation, les données existantes ne refléteront pas automatiquement ces modifications.

Mettez à jour en utilisant la même valeur et vérifiez si %doc est json. Et nous obtenons notre valeur.

Jetons maintenant un coup d'œil à la classe, qui est entièrement créée et mise à jour par %DocDB.Database

Class User.docdb Extends%DocDB.Document [ Owner = {irisowner}, ProcedureBlock ]
{

Property name As%String [ SqlComputeCode = { set {}=$$%EvaluatePathOne^%DocDB.Document({%Doc},"$.name") }, SqlComputed, SqlComputeOnChange = %Doc ];Property someValue As%String [ SqlComputeCode = { set {}=$$%EvaluatePathOne^%DocDB.Document({%Doc},"$.some_value") }, SqlComputed, SqlComputeOnChange = %Doc ]; Index name On name; Index someValue On someValue; }

Ainsi, les propriétés créées contiennent un code pour extraire la valeur de %Doc, et oui, elles ne sont remplies que lorsque %Doc est modifié. Et des index ont été créés pour les deux champs, sans que personne ne le demande. Le fait d'avoir de nombreuses valeurs extraites augmentera l'utilisation des variables globales simplement par le nombre d'index.

Il sera possible de mettre à jour ces propriétés créées, sans nuire au %Doc original, mais les valeurs deviendront inutiles.

 
Insertion de données non valides
Insert NULL

Chaîne vide ou tout texte non-json.

Réponse franchement moche, rien à ajouter, la validation des tentatives d'insertion de quelque chose d'illégal dans une table semble raisonnable, donc, le message d'erreur serait au moins quelque chose de significatif. 

La base de données %DocDB.Database avec une méthode %GetProperty

USER>zw docdb.%GetPropertyDefinition("someValue")

{"Name":"someValue","Type":"%Library.String"}  ; <DYNAMIC OBJECT> USER>zw docdb.%GetPropertyDefinition("name")

{"Name":"name","Type":"%Library.String"}  ; <DYNAMIC OBJECT>

Le chemin d'accès à la valeur qui a été utilisé dans %CreateProperty a disparu, il n'y a aucun moyen de le valider. Si le chemin d'accès est incorrect, pour le mettre à jour, il faut d'abord appeler %DropProperty puis à nouveau %CreateProperty.

%FindDocuments

%%DocDB.Database vous permet de rechercher des documents

Pour trouver un ou plusieurs documents dans une base de données et renvoyer ceux-ci au format JSON, appelez la méthode %FindDocuments(). Cette méthode accepte n'importe quelle combinaison de trois prédicats positionnels facultatifs : une matrice de restriction, une matrice de projection et une paire clé/valeur limite.

Plus important encore, %FindDocuments ne se soucie pas de %Doc lui-même, il ne fonctionne que sur les propriétés. Assez fragile, il lève des exceptions sur tout ce qui ne correspond pas à ce qui est attendu. En fait, il construit simplement une requête SQL et l'exécute.

USER>do docdb.%FindDocuments(["firstName","B","%STARTSWITH"]).%ToJSON() 

<THROW>%FindDocuments+37^%DocDB.Database.1 *%Exception.StatusException ERROR #25541: DocDB Property 'firstName' does not exist in 'User.docdb'

USER>do docdb.%FindDocuments(["name","test","in"],["name"]).%ToJSON()

{"sqlcode":100,"message":null,"content":[{"name":"test"}]} USER>do docdb.%FindDocuments(["name","","in"],["name"]).%ToJSON()

<THROW>%FindDocuments+37^%DocDB.Database.1 *%Exception.SQL -12 -12   A term expected, beginning with either of:  identifier, constant, aggregate, $$, (, :, +, -, %ALPHAUP, %EXACT, %MVR %SQLSTRING, %SQLUPPER, %STRING, %TRUNCATE, or %UPPER^ SELECT name FROM SQLUser . docdb WHERE name IN ( )

USER>do docdb.%FindDocuments(["name","test","="]).%ToJSON()

{"sqlcode":100,"message":null,"content":[{"%Doc":"{"name":"test", "some_value":12345}","%DocumentId":"1","%LastModified":"2025-02-05 12:25:02.405"}]} USER 2e1>do docdb.%FindDocuments(["Name","test","="]).%ToJSON()

<THROW>%FindDocuments+37^%DocDB.Database.1 *%Exception.StatusException ERROR #25541: DocDB Property 'Name' does not exist in 'User.docdb'

USER>do docdb.%FindDocuments(["%Doc","JSON","IS"]).%ToJSON()

<THROW>%FindDocuments+37^%DocDB.Database.1 *%Exception.StatusException ERROR #25540: DocDB Comparison operator is not valid: 'IS' USER 2e1>do docdb.%FindDocuments(["%Doc","","IS JSON"]).%ToJSON()

<THROW>%FindDocuments+37^%DocDB.Database.1 *%Exception.StatusException ERROR #25540: DocDB Comparison operator is not valid: 'IS JSON'

L'utilisation de SQL simple serait bien plus fiable 

Enregistrement

Un autre aspect très intéressant est l'efficacité avec laquelle JSON est enregistré dans la base de données.

^poCN.bvx3.1(1)=$lb("","2025-02-05 12:25:02.405","test",12345)
^poCN.bvx3.1(1,"%Doc")="{""name"":""test"", ""some_value"":12345}"
^poCN.bvx3.1(2)=$lb("","2025-02-05 12:25:02.405")
^poCN.bvx3.1(2,"%Doc")="[1,2,3]"
^poCN.bvx3.1(3)=$lb("","2025-02-05 12:01:18.542")
^poCN.bvx3.1(3,"%Doc")="test"
^poCN.bvx3.1(4)=$lb("","2025-02-05 12:01:19.445")
^poCN.bvx3.1(4,"%Doc")=$c(0)
^poCN.bvx3.1(5)=$lb("","2025-02-05 12:01:20.794")

Le JSON est stocké sous forme de texte brut, tandis que d'autres bases de données utilisent des formats binaires pour un enregistrement et une recherche plus efficaces. La base de données DocDB d'IRIS ne prend pas en charge la recherche directe dans le contenu des documents, sauf si JSON_TABLE est utilisé, ce qui nécessite tout de même l'analyse du JSON dans un format binaire interne.

Dans la version 2025.1, %DynamicAbstractObject introduit les méthodes %ToPVA et %FromPVA, ce qui semble enregistrer le JSON dans un format binaire.

USER>do ({"name":"value"}).%ToPVA($name(^JSON.Data(1))) 

USER>zw ^JSON.Data ^JSON.Data(1,0,0)="PVA1"$c(134,0,6,0,2,0,0,0,0,0,14,0,15,0,2,0,21,9,6,136,0,1,6,0,1,0,2,1,137,0,1,5,8,1,6)"value"$c(6,0,6)"name"_$c(5)

USER>zw {}.%FromPVA($name(^JSON.Data(1)))

{"name":"value"}  ; <DYNAMIC OBJECT,refs=1>

Cependant, le traitement de certaines structures présente des incohérences.

USER>do ({}).%ToPVA($name(^JSON.Data(1)))

<SYSTEM>%ToPVA+1^%Library.DynamicAbstractObject.1

USER>do ({"name":{}}).%ToPVA($name(^JSON.Data(1)))

<SYSTEM>%ToPVA+1^%Library.DynamicAbstractObject.1

Conclusion

Actuellement, %DocDB n'est vraiment pratique qu'avec ObjectScript et a des limites en SQL. Des problèmes de performances apparaissent lorsqu'il s'agit de traiter de grands ensembles de données. Tout ce que %DocDB offre peut être réalisé en utilisant du SQL de base tout en conservant un support SQL complet. Compte tenu de l'implémentation actuelle, il y a peu d'intérêt à utiliser DocDB plutôt que des approches SQL de base.

0
0 46
Annonce Irène Mykhailova · Avr 17, 2025

Bonjour la Communauté !

Nous savons que chaque développeur a de petits projets annexes : des applications qui lui permettent d’expérimenter de nouvelles technologies, de tester des idées avant de les implémenter dans des solutions plus vastes, ou simplement de créer quelque chose d’amusant par curiosité. Et si l’un de ces projets pouvait vous mener jusqu’à l’InterSystems READY 2025 ?

Nous vous proposons une opportunité unique : partagez votre créativité et votre passion pour IRIS et gagnez un pass gratuit pour l’InterSystems READY + hébergement !

Le règlement est simple : publiez votre projet annexe basé sur IRIS sur Open Exchange et enregistrez une courte vidéo inspirante expliquant pourquoi vous devriez être celui qui obtiendra l’entrée pour l’événement de l’année et gagner !

Durée : du 21 avril au 4 mai 2025

Prix : hébergement et entrées gratuites pour l’InterSystems READY 2025 !

0
0 36
Article Lorenzo Scalese · Avr 16, 2025 7m read

Qu'est-ce que JWT ??

JWT (JSON Web Token) est un standard ouvert (RFC 7519) qui offre une méthode légère, compacte et autonome pour transmettre en toute sécurité des renseignements entre deux parties. Il est couramment utilisé dans les applications web pour l'authentification, l'autorisation et l'échange d'informations.

Un JWT est généralement composé de trois parties:

1. En-tête JOSE (JSON Object Signing and Encryption)
2. Payload
3. Signature

Ces parties sont encodées au format Base64Url et concaténées avec des points (.) qui les séparent.

Structure d'un JWT

En-tête

{ "alg": "HS256", "typ": "JWT"}

Payload

{"sub": "1234567890", "name": "John Doe", "iat": 1516239022}

Signature:
La signature permet de vérifier que l'expéditeur du JWT est bien celui qu'il prétend être et de s'assurer que le message n'a pas été falsifié.

Pour créer la signature:

1. base64 En-tête et payload encodés en base64.
2. Application de l'algorithme de signature (par exemple, HMAC SHA256 ou RSA) avec une clé secrète (pour les algorithmes symétriques tels que HMAC) ou une clé privée (pour les algorithmes asymétriques tels que RSA).
3. Codage Base64Url du résultat pour obtenir la signature.

Exemple de JWT. Consultez le contenu du JWT 

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Création de JWT dans IRIS

Remarque : Avant 2024, la classe %OAuth2.JWT était utilisée pour générer des JWT dans IRIS. La classe %Net.JSON.JWT est désormais la classe principale pour la création de JWT, et j'utiliserai cette classe dans l'exemple de code.

JWK overview

Les JWK représentent une clé cryptographique, en particulier pour la signature et la vérification des JWT. Les JWK permettent de représenter les clés publiques (pour la vérification) et les clés privées (pour la signature) dans un format normalisé qui peut être facilement échangé entre les systèmes. Les JWKS contiennent plusieurs JWKs

Flux de travail JWT

1. Construisez votre en-tête en tant que %DynamicObject et ajoutez des en-têtes personnalisés si nécessaire.

2. Construisez le corps/les revendications directement en tant que %DynamicObject

3. Appelez la méthode Create de la classe %Net.JSON.JWT.

Set sc = ##Class(%Net.JSON.JWT).Create(header, , claims, jwks, , .JWT)

Création de JWK

Set sc = ##Class(%Net.JSON.JWK).Create("HS256","1212ASD!@#!#@$@#@$$#SDFDGD#%+_)(*@$SFFS",.privateJWK,.publicJWK)

Cela renverra la clé privée

{"kty":"oct","k":"MTIxMkFTRCFAIyEjQCRAI0AkJCNTREZER0QjJStfKSgqQCRTRkZT","alg":"HS256"

Quelques propriétés importantes de JWK

"kty": "oct" - représente l'algorithme symétrique
"kty": "RSA" / "kty": "EC" - represente l'algorithme asymétrique

Une fois que le JWK est créé, il peut être ajouté aux JWKS.

Créons des JWKS dans IRIS

Set sc = ##class(%Net.JSON.JWKS).PutJWK(jwk,.JWKS)

Cette méthode renvoie le JWKS

Génération du JWT dans IRIS

Vous pouvez créer des JWT à clé symétrique ou asymétrique dans IRIS. La classe %Net.JSON.JWK est essentiellement utilisée pour générer le JWT. Avant d'appeler la méthode, assurez-vous de créer et d'envoyer les JWKS pour le chiffrement symétrique et asymétrique lors de la génération du JWT.

Encryptage symétrique

Les algorithmes symétriques utilisent une clé secrète partagée, où l'expéditeur et le destinataire utilisent la même clé pour signer et vérifier le JWT. Ces algorithmes, tels que HMAC (HS256, HS512, HS384), génèrent un hachage (signature) pour le payload du JWT. Cette approche n'est pas recommandée pour les systèmes de haute sécurité, car la signature et la vérification sont exposées, ce qui pose des risques potentiels pour la sécurité.

La méthode Create de la classe %Net.JSON.JWK est utilisée pour générer le JWK. Elle accepte deux paramètres d'entrée et renvoie deux paramètres de sortie:

1. algorithm - l'algorithme pour lequel le JWK doit être créé.
2. secert - la clé utilisée pour signer et vérifier le JWT
3. privateJWK - la clé Web JSON privée qui est créée.
4. publicJWK - la clé Web JSON publique qui est créée.

Pour les algorithmes à clé symétrique, vous obtiendrez privateJWK

Pour les algorithmes à clé asymétrique, vous obtiendrez privateJWK et publicJWK

 
SymmetricKeyJWT

Le résultat 

LEARNING>d ##class(Learning.JWT.NetJWT).SymmetricKeyJWT()
privateJWK={"kty":"oct","k":"MTIxMkFTRCFAIyEjQCRAI0AkJCNTREZER0QjJStfKSgqQCRTRkZT","alg":"HS256"}  ; <DYNAMIC OBJECT>
privateJWKS="{""keys"":[{""kty"":""oct"",""k"":""MTIxMkFTRCFAIyEjQCRAI0AkJCNTREZER0QjJStfKSgqQCRTRkZT"",""alg"":""HS256""}]}"
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsIngtYyI6InRlIn0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.PcCs_I8AVy5HsLu-s6kQYWaGvuwqwPAElIad11NpM_E

Encryptage asymétrique

L'encryptage asymétrique fait référence à l'utilisation d'une paire de clés : une clé pour signer le jeton (clé privée) et l'autre pour le vérifier (clé publique). Il diffère de l'encryptage symétrique

Clé privée : cette clé est utilisée pour signer le jeton JWT. Elle est gardée secrète et ne doit jamais être exposée.
Clé publique : Cette clé est utilisée pour vérifier l'authenticité du JWT. Elle peut être partagée et distribuée en toute sécurité car elle ne peut pas être utilisée pour signer de nouveaux jetons.

Vous pouvez générer l'encryptage asymétrique JWT avec une clé/un certificat privé via %SYS.X509Credentials. Vous devez donc stocker votre certificat dans cette classe persistante.

 
AsymmetricWithx509

JWT dans les applications Web.

À partir de la version de 2023 , IRIS inclut par défaut la création de JWT intégrée pour les applications Web. Assurez-vous que l'authentification JWT est activée lors de la configuration de votre application Web

J'ai ajouté une brève explication  sur la configuration

1. Activez l' Authentication JWTdans votre application Web
2. Créez une classe REST si vous ne l'avez pas déjà fait
3. La ressource endpoint par défaut « /login » est incluse. Effectuez un appel API REST en utilisant l'authentification de base avec le payload comme {"user": "_SYSTEM", "password": "SYS"}.
4. La réponse sera un JSON contenant le "access_token," "refresh_token," et d'autres détails pertinents.
5. Utilisez le token d'accès pour l'autorisation.

0
1 42