0 Abonnés · 33 Publications

L'interface de programmation d'applications (API) est un ensemble de définitions de sous-programmes, de protocoles et d'outils permettant de concevoir des logiciels d'application. En termes généraux, il s'agit d'un ensemble de méthodes de communication clairement définies entre divers composants logiciels.

En savoir plus.

Article Guillaume Rongier · Sept 16, 2025 18m read

img

Dans cette section, nous allons découvrir comment utiliser Python comme langage principal dans IRIS, ce qui vous permettra d'écrire la logique de votre application en Python tout en profitant de la puissance d'IRIS.

Utilisation (irispython)

Tout d'abord, nous allons commencer par la méthode officielle, qui consiste à la mise en œuvre de l'interpréteur irispython.

Vous pouvez utiliser l'interpréteur irispython pour exécuter du code Python directement dans IRIS. Cela vous permet d'écrire du code Python et de l'exécuter dans le contexte de votre application IRIS.

Qu'est-ce qu'irispython?

irispython est un interpréteur Python qui se trouve dans le répertoire d'installation d'IRIS (<installation_directory>/bin/irispython) et qui sert à exécuter du code Python dans le contexte d'IRIS.

Cela vous permettra :

  • De configurer sys.path pour inclure les bibliothèques et les modules Python IRIS.
    • Cela est réalisé par le fichier site.py, qui se trouve dans <installation_directory>/lib/python/iris_site.py.
    • Pour plus d'informations, consultez l'article sur les modules Introduction aux modules Python.
  • Vous pourrez ainsi importer les modules iris, qui sont des modules spéciaux permettant d'accéder aux fonctionnalités IRIS, telles que la conversion de n'importe quelle classe ObjectScript vers Python, et réciproquement.
  • Vous pourrez corriger les problèmes d'autorisations et le chargement dynamique des bibliothèques du noyau iris.

Exemple d'utilisation d'irispython

Vous pouvez exécuter l'interpréteur irispython à partir de la ligne de commande:

<installation_directory>/bin/irispython

Prenons un exemple simple:

# src/python/article/irispython_example.py
import requests
import iris

def run():
    response = requests.get("https://2eb86668f7ab407989787c97ec6b24ba.api.mockbin.io/")

    my_dict = response.json()

    for key, value in my_dict.items():
        print(f"{key}: {value}")  # print message: Hello World

    return my_dict

if __name__ == "__main__":
    print(f"Iris version: {iris.cls('%SYSTEM.Version').GetVersion()}")
    run()

Vous pouvez lancer ce script à l'aide de l'interpréteur irispython:

<installation_directory>/bin/irispython src/python/article/irispython_example.py

Vous verrez le résultat:

Iris version: IRIS for UNIX (Ubuntu Server LTS for x86-64 Containers) 2025.1 (Build 223U) Tue Mar 11 2025 18:23:31 EDT
message: Hello World

Il est présenté ici comment utiliser l'interpréteur irispython pour exécuter du code Python dans le contexte d'IRIS.

Avantages

  • Python d'abord : vous pouvez écrire la logique de votre application en Python, ce qui vous permet de profiter des fonctionnalités et des bibliothèques de Python.
  • Intégration IRIS : vous pouvez facilement intégrer votre code Python aux fonctionnalités et aux caractéristiques d'IRIS.

Inconvénients

  • Débogage limité : le débogage du code Python dans irispython n'est pas aussi simple que dans un environnement Python dédié.
    • Cela ne signifie pas que c'est impossible, mais ce n'est pas aussi facile que dans un environnement Python dédié.
    • Consultez la Section supoplémentaire for more details.
  • Environnement virtuel : il est difficile de configurer un environnement virtuel pour votre code Python dans irispython.
    • Cela ne signifie pas que c'est impossible, mais c'est difficile à réaliser à cause de l'environnement virtuel qui recherche par défaut un interpréteur appelé python ou python3, ce qui n'est pas le cas dans IRIS.
    • Consultez la Section supoplémentaire for more details.

Conclusion

En conclusion, en utilisant irispython, vous pouvez écrire la logique de votre application en Python tout en profitant de la puissance d'IRIS. Cependant, cet outil présente certaines limites en matière de débogage et de configuration de l'environnement virtuel.

Utilisation de WSGI

Dans cette section, nous allons découvrir comment utiliser WSGI (Interface de passerelle serveur Web) pour exécuter des applications Web Python dans IRIS.

WSGI est une interface standard entre les serveurs Web et les applications ou frameworks Web Python. Elle vous permet d'exécuter des applications Web Python dans un environnement de serveur Web.

IRIS prend en charge WSGI, ce qui signifie que vous pouvez exécuter des applications Web Python dans IRIS à l'aide du serveur WSGI intégré.

Utilisation

Pour utiliser WSGI dans IRIS, vous devez créer une application WSGI et l'enregistrer auprès du serveur web IRIS.

Pour plus de détails, consultez la documentation officielle.

Exemple d'utilisation de WSGI

Vous trouverez un template complet ici iris-flask-example.

Avantages

  • Frameworks Web Python : Pour créer vos applications Web, vous pouvez utiliser des frameworks Web Python populaires tels que Flask ou Django.
  • Intégration IRIS : Vous pouvez intégrer vos applications Web Python aux fonctionnalités IRIS en toute simplicité.

Inconvénients

  • Complexité : la configuration d'une application WSGI peut s'avérer plus complexe en comparaison avec une simple utilisation de uvicorn ou gunicorn avec un framework web Python.

Conclusion

En conclusion, l'utilisation de WSGI dans IRIS vous permet de créer des applications web puissantes à l'aide de Python tout en profitant des fonctionnalités et des capacités d'IRIS.

DB-API

Dans cette section, nous allons découvrir comment utiliser l'API Python DB pour interagir avec les bases de données IRIS.

L'API Python DB est une interface standard pour se connecter à des bases de données en Python. Elle vous permet d'exécuter des requêtes SQL et de récupérer les résultats dans la base de données.

Utilisation

Vous pouvez l'installer en utilisant pip:

pip install intersystems-irispython

Ensuite, vous pouvez utiliser l'API DB pour la connexion à une base de données IRIS et exécuter des requêtes SQL.

Exemple d'utilisation de DB-API

Vous l'utilisez comme n'importe quelle autre API Python DB. Voici un exemple:

# src/python/article/dbapi_example.py
import iris

def run():
    # Connexion à la base de données IRIS
# Ouverture d'une connexion au serveur
    args = {
        'hostname':'127.0.0.1', 
        'port': 1972,
        'namespace':'USER', 
        'username':'SuperUser', 
        'password':'SYS'
    }
    conn = iris.connect(**args)

    # Création d'un curseur
    cursor = conn.cursor()

    # Exécution d'une requête
    cursor.execute("SELECT 1")

    # Récupération de tous les résultats
    results = cursor.fetchall()

    for row in results:
        print(row)

    # Fermeture du curseur et de la connexion
    cursor.close()
    conn.close()
if __name__ == "__main__":
    run()

Ce script peut être exécuté à l'aide de n'importe quel interpréteur Python:

python3 /irisdev/app/src/python/article/dbapi_example.py

Vous verrez le résultat:

(1,)

Avantages

  • Interface standard : l'API DB fournit une interface standard pour se connecter aux bases de données, ce qui facilite le passage d'une base de données à l'autre.
  • Requêtes SQL : vous pouvez exécuter des requêtes SQL et récupérer les résultats de la base de données à l'aide de Python.
  • Accès à distance : vous pouvez vous connecter à des bases de données IRIS distantes à l'aide de l'API DB.

Inconvénients

  • Fonctionnalités limitées : l'API DB fournit uniquement un accès SQL à la base de données. Vous ne pourrez donc pas utiliser les fonctionnalités avancées d'IRIS telles que l'exécution de code ObjectScript ou Python.

Alternatives

Il existe également une édition communautaire de la DB-API, disponible ici : intersystems-irispython-community.

Elle offre une meilleure prise en charge de SQLAlchemy, Django, langchain et d'autres bibliothèques Python qui utilisent la DB-API.

Pour plus de détail, consultez la Section supplémentaire.

Conclusion

En conclusion, l'utilisation de l'API Python DB avec IRIS vous permet de créer des applications puissantes capables d'interagir de manière transparente avec votre base de données.

Notebook

Après avoir vu comment utiliser Python dans IRIS, nous allons découvrir comment utiliser Jupyter Notebooks avec IRIS.

Jupyter Notebooks est un excellent moyen d'écrire et d'exécuter du code Python de manière interactive. Il peut être utilisé avec IRIS pour profiter de ses fonctionnalités.

Utilisation

Pour utiliser Jupyter Notebooks avec IRIS, vous devez installer les packages notebook et ipykernel:

pip install notebook ipykernel

Ensuite, vous pouvez créer un nouveau Jupyter Notebook et sélectionner le noyau Python 3.

Exemple d'utilisation de Notebook

Vous pouvez créer un nouveau Jupyter Notebook et écrire le code suivant:

# src/python/article/my_notebook.ipynb
# Importation des modules nécessaires
import iris
# La magie
iris.system.Version.GetVersion()

Vous pouvez exécuter ce notebook à l'aide de Jupyter Notebook:

jupyter notebook src/python/article/my_notebook.ipynb

Avantages

  • Développement interactif : les notebooks Jupyter vous permettent d'écrire et d'exécuter du code Python de manière interactive, ce qui est idéal pour l'analyse et l'exploration de données.
  • Résulltat riche : vous pouvez afficher des résultats riches, tels que des graphiques et des tableaux, directement dans le notebook.
  • Documentation : vous pouvez ajouter de la documentation et des explications à côté de votre code, ce qui rend

Inconvénients

  • Configuration délicate : la configuration des notebooks Jupyter avec IRIS peut s'avérer délicate, en particulier au niveau de la configuration du noyau.

Conclusion

Pour conclure, l'utilisation des notebooks Jupyter avec IRIS vous permet d'écrire et d'exécuter du code Python de manière interactive tout en profitant des fonctionnalités d'IRIS. Cependant, la configuration peut s'avérer délicate, en particulier au niveau du noyau.

Section supplémentaire

À partir de cette section, nous aborderons certains sujets avancés liés à Python dans IRIS, tels que le débogage à distance du code Python ou encore l'utilisation d'environnements virtuels.

La plupart de ces sujets ne sont pas officiellement pris en charge par InterSystems, mais il est utile de les aborder si vous souhaitez utiliser Python dans IRIS.

Utilisation d'un interpréteur natif (sans irispython)

Dans cette section, nous allons voir comment utiliser un interpréteur Python natif au lieu de l'interpréteur irispython.

Cela vous permet d'utiliser des environnements virtuels prêts à l'emploi et d'utiliser l'interpréteur Python auquel vous êtes habitué.

Utilisation

Pour utiliser un interpréteur Python natif, vous devez installer IRIS localement sur votre machine et disposer du package iris-embedded-python-wrapper installé.

Vous pouvez l'installer avec pip:

pip install iris-embedded-python-wrapper

Ensuite, vous devez configurer certaines variables d'environnement pour faire référence à votre installation IRIS:

export IRISINSTALLDIR=<installation_directory>
export IRISUSERNAME=<username>
export IRISPASSWORD=<password>
export IRISNAMESPACE=<namespace>

Ensuite, vous pouvez exécuter votre code Python à l'aide de votre interpréteur Python natif:

python3 src/python/article/irispython_example.py
# src/python/article/irispython_example.py
import requests
import iris

def run():
    response = requests.get("https://2eb86668f7ab407989787c97ec6b24ba.api.mockbin.io/")

    my_dict = response.json()

    for key, value in my_dict.items():
        print(f"{key}: {value}")  # message d'impression: Hello World

    return my_dict

if __name__ == "__main__":
    print(f"Iris version: {iris.cls('%SYSTEM.Version').GetVersion()}")
    run()

Pour plus de détails; consultez iris-embedded-python-wrapper documentation.

Avantages

  • Environnements virtuels : vous pouvez utiliser des environnements virtuels avec votre interpréteur Python natif, ce qui vous permet de gérer plus facilement les dépendances.
  • Workflow familier : vous pouvez utiliser votre interpréteur Python habituel, ce qui facilite l'intégration avec vos flux de travail existants.
  • Débogage : vous pouvez utiliser vos outils de débogage Python préférés, tels que pdb ou ipdb, pour déboguer votre code Python dans IRIS.

Inconvénients

  • Complexité de la configuration : la configuration des variables d'environnement et du package iris-embedded-python-wrapper peut s'avérer complexe, en particulier pour les débutants.
  • Non pris en charge officiellement : cette approche n'est pas prise en charge officiellement par InterSystems. Vous risquez donc de rencontrer des problèmes qui ne sont pas documentés ni pris en charge.

Edition communautaire de DB-API

Dans cette section, nous allons explorer l'édition communautaire de l'API DB, disponible sur GitHub.

Utilisation

Vous pouvez l'installer avec pip:

pip install sqlalchemy-iris

Cette option installe l'édition communautaire de DB-API.

Ou avec une version spécifique:

pip install https://github.com/intersystems-community/intersystems-irispython/releases/download/3.9.3/intersystems_iris-3.9.3-py3-none-any.whl

Ensuite, vous pouvez utiliser l'API DB pour vous connecter à une base de données IRIS et exécuter des requêtes SQL ou tout autre code Python qui utilise l'API DB, comme SQLAlchemy, Django, langchain, pandas, etc.

Exemple d'utilisation de DB-API

Vous pouvez l'utiliser comme n'importe quelle autre API Python DB. Exemple:

# src/python/article/dbapi_community_example.py
import intersystems_iris.dbapi._DBAPI as dbapi

config = {
    "hostname": "localhost",
    "port": 1972,
    "namespace": "USER",
    "username": "_SYSTEM",
    "password": "SYS",
}

with dbapi.connect(**config) as conn:
    with conn.cursor() as cursor:
        cursor.execute("select ? as one, 2 as two", 1)   # le deuxième argument est la valeur du paramètre
        for row in cursor:
            one, two = row
            print(f"one: {one}")
            print(f"two: {two}")

Vous pouvez exécuter ce script à l'aide de n'importe quel interpréteur Python:

python3 /irisdev/app/src/python/article/dbapi_community_example.py

Ou à l'aide de sqlalchemy:

from sqlalchemy import create_engine, text

COMMUNITY_DRIVER_URL = "iris://_SYSTEM:SYS@localhost:1972/USER"
OFFICIAL_DRIVER_URL = "iris+intersystems://_SYSTEM:SYS@localhost:1972/USER"
EMBEDDED_PYTHON_DRIVER_URL = "iris+emb:///USER"

def run(driver):
    # Création d'un moteur à l'aide du pilote officiel
    engine = create_engine(driver)

    with engine.connect() as connection:
        # Exécution d'une requête
        result = connection.execute(text("SELECT 1 AS one, 2 AS two"))

        for row in result:
            print(f"one: {row.one}, two: {row.two}")

if __name__ == "__main__":
    run(OFFICIAL_DRIVER_URL)
    run(COMMUNITY_DRIVER_URL)
    run(EMBEDDED_PYTHON_DRIVER_URL)

Vous pouvez exécuter ce script à l'aide de n'importe quel interpréteur Python:

python3 /irisdev/app/src/python/article/dbapi_sqlalchemy_example.py

Vous verrez le résultat:

one: 1, two: 2
one: 1, two: 2
one: 1, two: 2

Avantages

  • Meilleur prise en charge : il offre une meilleure prise en charge de SQLAlchemy, Django, langchain et d'autres bibliothèques Python qui utilisent l'API DB.
  • Développé par la communauté : il est maintenu par la communauté, ce qui signifie qu'il est susceptible d'être mis à jour et amélioré au fil du temps.
  • Compatibilité : il est compatible avec l'API DB officielle d'InterSystems, vous pouvez donc passer facilement de l'édition officielle à l'édition communautaire.

Inconvénients

  • Vitesse : la version communautaire n'est peut-être pas aussi optimisée que la version officielle, ce qui peut entraîner des performances plus lentes dans certains cas.

Débogage de code Python dans IRIS

Dans cette section, nous allons voir comment déboguer du code Python dans IRIS.

Par défaut, le débogage du code Python dans IRIS (dans objectscript avec la balise de langage ou %SYS.Python) n'est pas possible, mais la communauté a trouvé une solution pour vous permettre de déboguer le code Python dans IRIS.

Utilisation

Installez d'abord IoP Interopérabilité en Python:

pip install iris-pex-embedded-python
iop --init

Cela installera IoP et les nouvelles classes ObjectScript qui vous permettront de déboguer le code Python dans IRIS.

Ensuite, vous pouvez utiliser la classe IOP.Wrapper pour encapsuler votre code Python et activer le débogage.

Class Article.DebuggingExample Extends %RegisteredObject
{
ClassMethod Run() As %Status
{
    set myScript = ##class(IOP.Wrapper).Import("my_script", "/irisdev/app/src/python/article/", 55550) // Ajustez le chemin d'accès à votre module
    Do myScript.run()
    Quit $$$OK
}
}

Configurez ensuite VsCode pour utiliser le débogueur IoP en ajoutant la configuration suivante à votre fichier launch.json:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python in IRIS",
            "type": "python",
            "request": "attach",
            "port": 55550,
            "host": "localhost",
            "pathMappings": [
                {
                    "localRoot": "${workspaceFolder}/src/python/article",
                    "remoteRoot": "/irisdev/app/src/python/article"
                }
            ]
        }
    ]
}

Vous pouvez désormais exécuter votre code ObjectScript qui importe le module Python, puis connecter le débogueur dans VsCode au port 55550.

Vous pouvez exécuter ce script à l'aide de la commande suivante:

iris session iris -U IRISAPP '##class(Article.DebuggingExample).Run()'

Vous pouvez ensuite définir des points d'arrêt dans votre code Python, et le débogueur s'arrêtera à ces points d'arrêt, ce qui vous permettra d'inspecter les variables et de parcourir le code.

Vidéo de débogage à distance en action (pour IoP, mais le concept est le même):

Et vous disposez également de tracebacks dans votre code Python, ce qui est très utile pour le débogage.

Avec les tracebacks activés:

Traceback enabled

Avec les tracebacks désactivés:

Traceback disabled

Avantages

  • Débogage à distance : vous pouvez déboguer à distance le code Python exécuté dans IRIS, ce qui, à mon avis, change la donne.
  • Fonctionnalités de débogage Python : vous pouvez utiliser toutes les fonctionnalités de débogage Python, telles que les points d'arrêt, l'inspection des variables et l'exécution du code pas à pas.
  • Tracebacks : vous pouvez voir le traceback complet des erreurs dans votre code Python, ce qui est très utile pour le débogage.

Inconvénients

  • Complexité de la configuration : La configuration de l'IoP et du débogueur peut s'avérer complexe, en particulier pour les débutants.
  • Solution communautaire : Il s'agit d'une solution communautaire, qui peut donc être moins stable ou moins bien documentée que les solutions officielles.

Conclusion

En conclusion, le débogage de code Python dans IRIS est possible grâce à la solution communautaire IoP, qui vous permet d'utiliser le débogueur Python pour déboguer votre code Python exécuté dans IRIS. Cependant, cela nécessite une certaine configuration et peut ne pas être aussi stable que les solutions officielles.

IoP (Interopérabilité en Python)

Dans cette section, nous allons explorer la solution IoP (Interopérabilité en Python), qui vous permet d'exécuter du code Python dans IRIS dans une approche "Python d'abord".

Je développe cette solution depuis un certain temps déjà, c'est mon bébé, elle essaie de résoudre ou d'améliorer tous les points précédents que nous avons vus dans cette série d'articles.

Points clés de l'IoP:

  • Python d'abord : vous pouvez écrire la logique de votre application en Python, ce qui vous permet de profiter des fonctionnalités et des bibliothèques de Python.
  • Intégration IRIS : vous pouvez facilement intégrer votre code Python aux fonctionnalités et aux caractéristiques d'IRIS.
  • Débogage à distance : vous pouvez déboguer à distance votre code Python exécuté dans IRIS.
  • Tracebacks : vous pouvez voir le traceback complet des erreurs dans votre code Python, ce qui est très utile pour le débogage.
  • Environnements virtuels : vous bénéficiez d'une prise en charge des environnements virtuels, ce qui vous permet de gérer plus facilement les dépendances.

Pour en savoir plus sur IoP, vous pouvez consulter la documentation officielle.

Vous pouvez ensuite lire les articles suivants pour en savoir plus sur IoP:

🐍❤️ Comme vous pouvez le constater, IoP offre un moyen puissant d'intégrer Python à IRIS, ce qui facilite le développement et le débogage de vos applications.

Vous n'avez plus besoin d'utiliser irispython, vous n'avez plus à définir manuellement votre sys.path, vous pouvez utiliser des environnements virtuels et vous pouvez déboguer votre code Python exécuté dans IRIS.

Conclusion

J'espère que vous avez apprécié cette série d'articles sur Python dans IRIS.

N'hésitez pas à me contacter si vous avez des questions ou des commentaires à propos de cette série d'articles.

Bonne chance, amusez-vous avec Python dans IRIS!

0
0 25
Article Guillaume Rongier · Sept 11, 2025 6m read

img

Connaissant désormais bien Python et ses fonctionnalités, voyons comment nous pouvons tirer parti de Python dans IRIS.

Balise de langue

La balise de langue est une fonctionnalité d'IRIS qui vous permet d'écrire du code Python directement dans vos classes ObjectScript.

Cette fonctionnalité est utile pour le prototypage rapide ou lorsque vous souhaitez utiliser les fonctionnalités de Python sans créer de script Python séparé.

Utilisation

Pour utiliser la balise de langue, il faut définir une méthode de classe avec l'attribut Language = python. Exemple:

Class Article.LanguageTagExample Extends %RegisteredObject
{

ClassMethod Run() [ Language = python ]
{
        import requests

        response = requests.get("https://2eb86668f7ab407989787c97ec6b24ba.api.mockbin.io/")

        my_dict = response.json()

        for key, value in my_dict.items():
            print(f"{key}: {value}") # print message: Hello World
}

}

Quels sont donc les avantages et les inconvénients de l'utilisation de la balise de langue?

Avantages

  • Simplicité : vous pouvez écrire du code Python directement dans vos classes ObjectScript sans avoir à créer de fichiers Python séparés.
  • Prototypage rapide : idéal pour le prototypage rapide ou le test de petits fragments de code Python.
  • Intégration : vous pouvez facilement intégrer du code Python à votre code ObjectScript.

Inconvénients

  • Code mixte : le mixage de code Python et ObjectScript peut rendre votre code plus difficile à lire et à maintenir.
  • Débogage : vous ne pouvez pas déboguer à distance le code Python écrit dans la balise de langage, ce qui peut constituer une limitation pour les applications complexes.
  • Tracebacks : les tracebacks Python ne s'affichent pas, vous ne voyez qu'un message d'erreur ObjectScript, ce qui peut rendre le débogage plus difficile.

Conclusion

La balise de langue est une fonctionnalité puissante qui vous permet d'écrire du code Python directement dans vos classes ObjectScript. Cependant, elle a ses limitations et il est important de l'utiliser de manière raisonnable. Pour les projets plus importants ou lorsque vous devez déboguer votre code Python, il est préférable de créer des scripts Python séparés et de les importer dans vos classes ObjectScript.

Importation de modules Python (modules pypi)

Maintenant que nous avons une bonne compréhension de la balise de langue, voyons comment importer des modules Python et les utiliser dans ObjectScript.

Tout d'abord, nous allons nous limiter aux modules intégrés et aux modules tiers provenant de PyPI, tels que module de demande requests, module numpy, etc.

Utilisation

Ici, nous allons faire la même chose, mais en utilisant uniquement le module de demande de PyPI.

Class Article.RequestsExample Extends %RegisteredObject
{

ClassMethod Run() As %Status
{
    set builtins = ##class(%SYS.Python).Import("builtins")
    Set requests = ##class(%SYS.Python).Import("requests")

    Set response = requests.get("https://2eb86668f7ab407989787c97ec6b24ba.api.mockbin.io/")
    Set myDict = response.json()

    for i=0:1:builtins.len(myDict)-1 {
        set key = builtins.list(myDict.keys())."__getitem__"(i)
        set value = builtins.list(myDict.values())."__getitem__"(i)
        write key, ": ", value, !
    }
}

}

Exécutons-le:

iris session iris -U IRISAPP '##class(Article.RequestsExample).Run()'

Vous verrez le résultat:

message: Hello World

Avantages

  • Accès aux bibliothèques Python : vous pouvez utiliser toutes les bibliothèques Python disponibles sur PyPI, ce qui vous donne accès à un vaste écosystème de bibliothèques et d'outils.
  • Un seul type de code : vous n'écrivez que du code ObjectScript, ce qui facilite la lecture et la maintenance.
  • Débogage : vous pouvez déboguer votre code ObjectScript comme s'il s'agissait uniquement de code ObjectScript, ce qui est le cas :)

Inconvénients

  • Bonne connaissance de Python : vous devez avoir une bonne compréhension de Python pour utiliser efficacement ses bibliothèques.
  • Consultez des exemples dans les articles sur les méthodes dunder.
  • Pas d'écriture de code Python : vous n'écrivez pas de code Python, mais du code ObjectScript qui appelle du code Python, ce qui évite le sucre syntaxique de Python.

Conclusion

En conclusion, l'importation de modules Python dans ObjectScript peut considérablement améliorer les capacités de votre application en tirant parti du vaste écosystème de bibliothèques Python. Cependant, il est essentiel de comprendre les compromis impliqués, tels que la nécessité d'une solide maîtrise de Python.

Importation de modules Python (modules personnalisés)

Continuons avec le même exemple, mais cette fois-ci, nous allons créer un module Python personnalisé et l'importer dans ObjectScript.

Cette fois-ci, nous utiliserons Python autant que possible, et ObjectScript ne sera utilisé que pour appeler le code Python.

Utilisation

Créons un module Python personnalisé dénommé my_script.py avec le contenu suivant:

import requests

def run():
    response = requests.get("https://2eb86668f7ab407989787c97ec6b24ba.api.mockbin.io/")

    my_dict = response.json()

    for key, value in my_dict.items():
        print(f"{key}: {value}") # print message: Hello World

Maintenant, nous allons créer une classe ObjectScript pour importer et exécuter ce module Python:

Class Article.MyScriptExample Extends %RegisteredObject
{
    ClassMethod Run() As %Status
    {
        set sys = ##class(%SYS.Python).Import("sys")
        do sys.path.append("/irisdev/app/src/python/article")  // Adjust the path to your module

        Set myScript = ##class(%SYS.Python).Import("my_script")

        Do myScript.run()

        Quit $$$OK
    }
}

Maintenant, exécutons-le:

iris session iris -U IRISAPP '##class(Article.MyScriptExample).Run()'

⚠️ N'oubliez pas de modifier votre session iris afin de vous assurer que vous disposez de la dernière version du code. Pour plus d'informations, consultez le premier article. Vous verrez le résultat:

message: Hello World

Voici une démonstration de l'importation d'un module Python personnalisé dans ObjectScript et de l'exécution de son code.

Avantages

  • Modularité : vous pouvez organiser votre code Python en modules, ce qui facilite sa gestion et sa maintenance.
  • Syntaxe Python : vous pouvez écrire du code Python en utilisant sa syntaxe et ses fonctionnalités.
  • Débogage : cette fonctionnalité n'est pas disponible pour le moment, mais dans le prochain article, nous verrons comment déboguer du code Python dans IRIS.

Inconvénients

  • Gestion des chemins : vous devez gérer le chemin d'accès à votre module Python. Pour plus d'informations, consultez l'article [https://community.intersystems.com/post/introduction-python-modules] sur sys.path.
  • Connaissances Python : vous devez toujours avoir une bonne compréhension de Python pour écrire et maintenir vos modules.
  • Connaissances ObjectScript : vous devez savoir comment utiliser ObjectScript pour importer et appeler vos modules Python.

Conclusion

En conclusion, l'importation de modules Python dans ObjectScript peut considérablement améliorer les capacités de votre application en tirant parti du vaste écosystème de bibliothèques Python. Cependant, il est essentiel de comprendre les compromis impliqués, tels que la nécessité d'une solide maîtrise de Python.

0
0 21
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 · 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 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
Article Stav Bendarsky · Mars 4, 2025 6m read

La surveillance de votre déploiement IRIS est cruciale. Avec l'obsolescence de System Alert and Monitoring (SAM), une solution moderne et scalable est nécessaire pour obtenir des informations en temps réel, détecter précocement les problèmes et améliorer l'efficacité opérationnelle. Ce guide explique comment configurer Prometheus et Grafana dans Kubernetes pour surveiller efficacement InterSystems IRIS.

Ce guide suppose que vous avez déjà déployé un cluster IRIS en utilisant l'InterSystems Kubernetes Operator (IKO), qui simplifie le déploiement, l'intégration et la gestion.

 

0
0 65
Question Anthony Decorte · Fév 5, 2025

Bonjour, j'ai un problème avec un appel et j'aurais besoin d'aide.

Lorsque j'appelle une API avec la méthode SendFormDataArray de l'adaptateur EnsLib.HTTP.OutboundAdapter, je lui passe un objet %Net.HttpRequest et je reçois l'erreur suivante :

ERROR #5002: ObjectScript error: <SUBSCRIPT>MatchSuffix+1^%Net.HttpRequest.1 ^%qPublicSuffix("")

J'ai correctement saisi l'url dans mon business operation et je la passe dans le dernier paramètre de la méthode SendFormDataArray. Avez-vous une idée, s'il vous plaît ?

0
0 46
Article Lorenzo Scalese · Jan 22, 2025 5m read

Mise en œuvre de l'idée DPI-I-456

Idée

Le rôle de cet échantillon

Cet exemple a été cloné à partir de la version iris-interoperability-template. J'ai reconfiguré la production d' interopérabilité Production avec un adaptateur Inbound HTTP Adapter qui est utilisé par un service métier HTTP Business Service. Les détails de la configuration du service métier sont spécifiés dans la rubrique des paramètres par défaut du système System Default Settings. J'ai configuré le paramètre de l'intervalle d'appel pour appeler le serveur HTTPS une fois par heure. Vous pouvez modifier l'URL et la fréquence dans les paramètres du service. Screenshot

À l'origine, le service HTTP avait deux cibles. Le corps de réponse de chaque appel était envoyé en tant que message générique HTTP à un processus métier BPL et à une opération de fichier qui sauvegardait les données dans un dossier iris-http-calls.

Le service HTTP envoie un message générique HTTP à une opération de fichier. Ensuite, un service de fichiers envoie le fichier à un processus métier BPL.

Conditions préalables

Assurez-vous d'avoir installé git et Docker desktop.

Installation: ZPM

Ouverture de l'espace de noms IRIS avec l'interopérabilité activée. Ouvrez le terminal et appelez: USER>zpm "install iris-http-calls"

Installation: Docker

Clone/git extrait le référentiel dans n'importe quel répertoire local.

git clone https://github.com/oliverwilms/iris-http-calls.git

Ouvrez le terminal dans ce répertoire et lancez:

docker-compose build
  1. Lancez le conteneur IRIS avec votre projet:
docker-compose up -d

Comment exécuter l'échantillon

Ouvrez la production et lancez-la si elle n'est pas déjà en cours d'exécution. Il effectue des appels HTTP vers le serveur HTTPS à l'aide d'une URL.

Comment modifier le modèle

Ce référentiel est prêt à être codé dans VSCode avec le plugin ObjectScript. Installez VSCode, Docker et le pluginObjectScript et ouvrez le dossier dans VSCode.

Utilisez le menu pratique VSCode pour accéder à l'éditeur de règles de production et de règles métier et lancez un terminal: Screenshot 2020-10-29 at 20 15 56

utilisation des variables d'environnement

Cet exemple montre la façon dont vous pouvez introduire des variables env dans votre environnement dev. Supposons que vous ayez besoin de configurer la production avec un jeton secret pour accéder à une API à accès limité. Bien sûr, vous ne voulez pas exposer le secret à GitHub. Dans ce cas, le mécanisme des variables Env peut être utile. Tout d'abord, introduisez le fichier .env et configurez .gitignore pour filtrer .env à partir de git.

Ajoutez ensuite le jeton secret dans .env sous la forme ENV_VARIABLE="TOKEN VALUE"

L'introduction suivante consiste à faire importer les variables d'environnement dans dockerfile. Pour que cela fonctionne, ajoutez la section environnement dans [docker-compose.yml] (https://github.com/intersystems-community/iris-interoperability-template/blob/d2d7114de7c551e308e742359babebff5d535821/docker-compose.yml), par exemple:

environnement:
      - SAMPLE_TOKEN=${SAMPLE_TOKEN}

Ensuite, vous pourrez initialiser le conteneur en cours d'exécution avec les données des variables env, par exemple avec l'appel suivant, qui utilise la valeur du fichier .env comme paramètre de la production:

USER> d ##class(dc.Demo.Setup).Init($system.Util.GetEnviron("SAMPLE_TOKEN"))

paramètres de production du gestionnaire de paquets

Les utilisateurs de ce module peuvent utiliser des paramètres pour transmettre des données au module lors de l'installation et personnaliser le chemin d'accès au fichier pour l'opération de fichier et le service de fichier, ainsi que modifier l'URL. Il peut être utile lorsque les paramètres de configuration sont des jetons secrets permettant d'accéder à une API particulière. En tant que spécialiste, vous pouvez fournir de tels paramètres avec une balise par défaut dans module.xml.

<Default Name="FilePath" Value="iris_http_calls" />
<Default Name="UrlModify" Value="/Patient?_id=egqBHVfQlt4Bw3XGXoxVxHg3" />

Ces paramètres par défaut permettent aux utilisateurs d'appeler l'installation du paquet avec la possibilité de transmettre des paramètres. Par exemple, l'appel à l'installation peut être exécuté sous la forme suivante:

zpm "install iris-http-calls -D FilePath=iris_http_calls -D UrlModify=/MedicationStatement?patient=egqBHVfQlt4Bw3XGXoxVxHg3"
USER>zpm "install iris-http-calls -D FilePath=iris_http_calls -D UrlModify=/MedicationStatement?patient=egqBHVfQlt4Bw3XGXoxVxHg3"

[USER|iris-http-calls]        Reload START (/usr/irissys/mgr/.modules/USER/iris-http-calls/0.3.37/)
[USER|iris-http-calls]        Reload SUCCESS
[iris-http-calls]       Module object refreshed.
[USER|iris-http-calls]        Validate START
[USER|iris-http-calls]        Validate SUCCESS
[USER|iris-http-calls]        Compile START
[USER|iris-http-calls]        Compile SUCCESS
[USER|iris-http-calls]        Activate START
[USER|iris-http-calls]        Configure START
[USER|iris-http-calls]        Configure SUCCESS
[USER|iris-http-calls]        Activate SUCCESS

Les paramètres par défaut sont utilisés pour configurer la production dans l'appel suivant:

<Invoke Class="dc.Demo.Setup" Method="Init" >
  <Arg>${FilePath}</Arg>
  <Arg>${UrlModify}</Arg>
</Invoke>

La méthode Init de la classe dc.Demo.Setup configure le service et l'opération de fichier à l'aide du paramètre FilePath. Le paramètre UrlModify est utilisé pour modifier l'URL du service HTTP.

La production appelle le serveur HTTPS à l'aide de l'URL modifiée selon CallInterval. Le corps de réponse est envoyé dans un StreamContainer à une FileOperation. Un service de fichiers lit le fichier et transmet un conteneur de flux à un processus BPL.

0
0 34
Article Iryna Mykhailova · Oct 9, 2024 4m read

L'accès à un stockage cloud Azure pour charger/télécharger des blobs est assez simple à l'aide des méthodes API de classe %Net.Cloud.Storage.Client désignées ou des adaptateurs entrants/sortants EnsLib.CloudStorage.*.

Notez que vous devez avoir le serveur de %JavaServer External Language opérationnel pour utiliser l'API ou les adaptateurs de stockage cloud, car ils utilisent tous deux le framework PEX à l'aide du serveur Java.

Voici un bref résumé :

L'accès à Azure Blob Storage s'effectue à l'aide d'une chaîne de connexion qui ressemble à celle-ci :

0
0 91
Article Guillaume Rongier · Oct 6, 2024 21m read

Cela fait maintenant plus de 2 ans que j'utilise quotidiennement Embedded Python. Il est peut-être temps de partager un retour d'expérience sur ce parcours.

Pourquoi écrire ce commentaire de retour d'expérience? Parce que, je suppose, je suis comme la plupart de mes collègues ici, un développeur ObjectScript, et je pense que la communauté bénéficierait de ce retour d'expérience et pourrait mieux comprendre les avantages et les inconvénients du choix de Embedded Python pour développer quelque chose dans IRIS. Et aussi éviter certains pièges.

image

Introduction

Je suis développeur depuis 2010, et j'ai travaillé avec ObjectScript depuis 2013.

Donc, c'est à peu près 10 ans d'expérience avec ObjectScript.

Depuis 2021, et la sortie de Embedded Python dans IRIS, je me suis lancé un défi :

  • Apprendre Python
  • Faire autant que possible tout ce qui est en Python.

Quand j'ai commencé ce parcours, je n'avais aucune idée de ce qu'était Python. J'ai donc commencé par les bases, et je continue d'apprendre chaque jour.

Débuter avec Python

L'avantage de Python est sa facilité d'apprentissage. C'est encore plus facile quand on connaît déjà ObjectScript.

Pourquoi ? Ils ont beaucoup de choses en commun.

ObjectScriptPython
Non typéNon typé
Langage de scriptLangage de script
Orienté objetOrienté objet
InterprétéInterprété
Intégration simple du CIntégration simple du C

Donc, si vous connaissez ObjectScript, vous en savez déjà beaucoup sur Python.

Mais il y a quelques différences, et certaines d'entre elles ne sont pas faciles à comprendre.

Python n'est pas ObjectScript

Mais il y a quelques différences, et certaines d'entre elles ne sont pas faciles à comprendre.

Pour moi il y a principalement 3 différences :

  • Pep8
  • Modules
  • Dunders

Pep8

Mais qu'est-ce que Pep8 ?

Il s'agit d'un ensemble de règles pour écrire du code Python.

pep8.org

Quelques-unes d'entre elles sont :

  • convention de nommage
  • noms de variables
    • snake_case
  • noms de classes
    • CamelCase
  • indentation
  • longueur de ligne
  • etc.

Pourquoi est-ce important ?

Parce que c'est la façon d'écrire du code Python. Et si vous ne suivez pas ces règles, vous aurez du mal à lire le code écrit par d'autres personnes, et elles auront du mal à lire le vôtre.

En tant que développeurs ObjectScript, nous avons aussi quelques règles à suivre, mais elles ne sont pas aussi strictes que Pep8.

J'ai appris Pep8 à la dure.

Je voudrais vous raconter petite histoire, je suis ingénieur commercial chez InterSystems et je fais beaucoup de démonstrations. Et un jour, que je faisais une démo de Embedded Python à un client, et ce client était un développeur Python, la conversation a tourné court lorsqu'il a vu mon code. Il m'a dit que mon code n'était pas du tout Python (il avait raison), je codais en Python comme je codais en ObjectScript. Et à cause de cela, il m'a dit qu'il n'était plus intéressé par Embedded Python. J'ai été choqué, et j'ai décidé d'apprendre Python de la bonne manière.

Donc, si vous voulez apprendre Python, apprenez d'abord Pep8.

Modules

Les modules sont quelque chose que nous n'avons pas en ObjectScript.

Habituellement, dans les langages orientés objet, vous avez des classes et des paquetages. En Python, vous avez des classes, des paquetages et des modules.

Qu'est-ce qu'un module ?

C'est un fichier avec une extension .py. Et c'est la façon d'organiser votre code.

Vous n'avez pas compris? Moi non plus au début. Prenons un exemple.

Habituellement, quand on veut créer une classe en ObjectScript, on crée un fichier .cls, et on y met sa classe. Et si vous voulez créer une autre classe, vous créez un autre fichier .cls. Et si vous voulez créer un paquetage, vous créez un dossier et vous y placez vos fichiers .cls.

En Python, c'est la même chose, mais Python apporte la possibilité d'avoir plusieurs classes dans un seul fichier. Ce fichier s'appelle un module. Pour information, c'est Pythonic quand il y a plusieurs classes dans un seul fichier.

Prévoyez donc comment vous allez organiser votre code, et comment vous allez nommer vos modules pour ne pas vous retrouver comme moi avec un tas de modules portant le même nom que vos classes.

Un mauvais exemple :

MyClass.py

class MyClass:
    def __init__(self):
        pass

    def my_method(self):
        pass

Pour instancier cette classe, vous allez faire :

import MyClass.MyClass # weird right ?

my_class = MyClass()

Bizarre, hein ?

Dunders

Les dunders sont des méthodes spéciales en Python. Elles sont appelées dunder parce qu'elles commencent et se terminent par un double soulignement.

Ce sont en quelque sorte nos méthodes % en ObjectScript.

Elles sont utilisées pour ce qui suit :

  • constructeur
  • surcharge d'opérateur
  • représentation d'objet
  • etc.

Exemple :

class MyClass:
    def __init__(self):
        pass

    def __repr__(self):
        return "MyClass"

    def __add__(self, other):
        return self + other

Ici, nous avons 3 méthodes de dunder :

  • __init__ : constructeur
  • __repr__ : représentation d'objet
  • __add__ : surcharge d'opérateur

Les méthodes Dunders sont partout en Python. C'est une partie importante de la langue, mais ne vous inquiétez pas, vous les apprendrez rapidement.

Conclusion

Python n'est pas ObjectScript, et vous devrez l'apprendre. Mais ce n'est pas si difficile, et vous l'apprendrez rapidement. Gardez simplement à l'esprit qu'il vous faudra apprendre Pep8, et comment organiser votre code avec des modules et des méthodes dunder.

De bons sites pour apprendre Python :


Embedded Python

Maintenant que vous en savez un peu plus sur Python, parlons de Embedded Python.

Qu'est-ce que Embedded Python ?

Embedded Python est un moyen d'exécuter du code Python dans IRIS. C'est une nouvelle fonctionnalité d' IRIS 2021.2+. Cela signifie que votre code Python sera exécuté dans le même processus qu'IRIS. Par ailleurs, chaque classe ObjectScript est une classe Python, de même pour les méthodes et les attributs et vice versa. 🥳 C'est génial !

Comment utiliser Embedded Python ?

Il y a 3 façons principales d'utiliser Embedded Python :

  • Utilisation la balise de langue dans ObjectScript
    • Méthode Foo() As %String [ Language = python ]
  • Utilisation de la fonction ##class(%SYS.Python).Import()
  • Utilisation de l'interpréteur python
    • python3 -c "import iris; print(iris.system.Version.GetVersion())"

Mais si vous voulez vous intéresser sérieusement à Embedded Python, vous aurez à éviter d'utiliser la balise de langue.

image

Pourquoi ?

  • Parce que ce n'est pas Pythonic
  • Parce que ce n'est pas ObjectScript non plus
  • Parce que vous n'avez pas de débogueur
  • Parce que vous n'avez pas de linter
  • Parce que vous n'avez pas de formateur
  • Parce que vous n'avez pas de cadre de test
  • Parce que vous n'avez pas de gestionnaire de paquets
  • Parce que vous mélangez 2 langues dans le même fichier
  • Parce que lorsque votre processus plante, vous n'avez pas de trace de pile
  • Parce que vous ne pouvez pas utiliser d'environnements virtuels ou d'environnements conda
  • ...

Ne vous méprenez pas, ça marche, ça peut être utile, si vous voulez tester quelque chose rapidement, mais à mon avis, ce n'est pas une bonne pratique.

Alors, qu'est-ce que j'ai appris de ces 2 années de Embedded Python, et comment l'utiliser de la bonne manière ?

Comment j'utilise Embedded Python

Je crois que vous avez deux options :

  • Utiliser les bibliothèques Python comme s'il s'agissait de classes ObjectScript
    • withqvec ##class(%SYS.Python).Import() function
  • Utiliser une première approche en python

Utilisation des bibliothèques et le code Python comme s'il s'agissait de classes ObjectScript

Vous voulez toujours utiliser Python dans votre code ObjectScript, mais vous ne voulez pas utiliser la balise de langue. Alors, que pouvez-vous faire ?

"Tout simplement" utilisez les bibliothèques et le code Python comme s'il s'agissait de classes ObjectScript. Prenons un exemplee :

Vous voulez utiliser la bibliothèque 'requests' ( c'est une bibliothèque pour faire des requêtes HTTP ) dans votre code ObjectScript.

Avec la balise de langue

ClassMethod Get() As %Status [ Language = python ]
{
	import requests

	url = "https://httpbin.org/get"
	# faire une requête d'obtention
	response = requests.get(url)
	# récupérer les données json de la réponse
	data = response.json()
	# itérer sur les données et imprimer les paires clé-valeur
	for key, value in data.items():
		print(key, ":", value)
}

Pourquoi je pense que ce n'est pas une bonne idée ?

Parce que vous mélangez 2 langues dans le même fichier, et que vous n'avez pas de débogueur, de linter, de formateur, etc. Si ce code plante, vous aurez du mal à le déboguer. Vous n'avez pas de trace de pile, et vous ne savez pas d'où vient l'erreur. Et vous n'avez pas d'auto-complétion.

Sans de balise de langue

ClassMethod Get() As %Status
{
	set status = $$$OK
    set url = "https://httpbin.org/get"
    // Importation du module Python "requests" en tant que classe ObjectScript
    set request = ##class(%SYS.Python).Import("requests")
    // Appel de la méthode get de la classe de requête
    set response = request.get(url)
    // Appel de la méthode json de la classe de réponse
	set data = response.json()
    // Ici, les données sont un dictionnaire Python
    // Pour parcourir un dictionnaire Python, vous devez utiliser la méthode dunder et items()
	// Importation du module Embedded Python
	set builtins = ##class(%SYS.Python).Import("builtins")
    // Ici, nous utilisons len du module intégré pour obtenir la longueur du dictionnaire
    For i = 0:1:builtins.len(data)-1 {
        // Maintenant, nous convertissons les éléments du dictionnaire en une liste, et nous obtenons la clé et la valeur en utilisant la méthode dunder __getitem__
		Write builtins.list(data.items())."__getitem__"(i)."__getitem__"(0),": ",builtins.list(data.items())."__getitem__"(i)."__getitem__"(1),!
	}
	quit status
}

Pourquoi je pense que c'est une bonne idée ?

Parce que vous utilisez Python comme s'il s'agissait d'ObjectScript. Vous importez la bibliothèque de requêtes comme une classe ObjectScript et vous l'utilisez comme une classe ObjectScript. Toute la logique est en ObjectScript, et vous utilisez Python comme une bibliothèque. Même pour la maintenance, c'est plus facile à lire et à comprendre, n'importe quel développeur ObjectScript peut comprendre ce code. L'inconvénient est que vous avez à savoir comment utiliser les méthodes de duners, et comment utiliser Python comme s'il s'agissait d'ObjectScript.

Conclusion

Croyez-moi, de cette manière vous obtiendrez un code plus robuste, et vous pourrez le déboguer facilement. Au début, cela semble difficile, mais vous découvrirez les avantages de l'apprentissage de Python plus rapidement que vous ne le pensez.

Utilisation de première approche en python

C'est la façon dont je préfère utiliser Embedded Python.

J'ai construit beaucoup d'outils en utilisant cette approche, et j'en suis très satisfait.

Quelques exemples :

Qu'est-ce qu'une première approche python ?

TIl n'y a qu'une seule règle : Le code Python doit être dans des fichiers .py, le code ObjectScript doit être dans des fichiers .cls

Comment y parvenir ?

L'idée est de créer des classes de wrappers ObjectScript pour appeler le code Python.


Prenons l'exemple de iris-fhir-python-strategy :

Exemple : iris-fhir-python-strategy

Tout d'abord, nous avons à comprendre comment fonctionne le serveur IRIS FHIR.

Chaque serveur IRIS FHIR met en œuvre une Stratégie.

Une Stratégie est un ensemble de deux classes :

SuperclassParamètres de sous-classe
HS.FHIRServer.API.InteractionsStrategyStrategyKey — Spécifie un identifiant unique pour la stratégie InteractionsStrategy.
InteractionsClass — Spécifie le nom de votre sous-classe Interactions.
HS.FHIRServer.API.RepoManagerStrategyClass — Spécifie le nom de votre sous-classe InteractionsStrategy.
StrategyKey — Spécifie un identifiant unique pour la stratégie InteractionsStrategy. Ceci doit correspondre au paramètre StrategyKey dans la sous-classe InteractionsStrategy.

Ces deux classes sont des classes abstraites Abtract Abstract.

  • HS.FHIRServer.API.InteractionsStrategy est une classe Abstract qui doit être mise en œuvre pour personnaliser le comportement du serveur FHIR.
  • HS.FHIRServer.API.RepoManager est une classe Abstract qui doit être mise en œuvre pour personnaliser le stockage du serveur FHIR.

Remarques

Pour notre exemple, nous nous concentrerons uniquement sur la classe HS.FHIRServer.API.InteractionsStrategy même si la classe HS.FHIRServer.API.RepoManager est également implémentée et obligatoire pour personnaliser le serveur FHIR. La classe HS.FHIRServer.API.RepoManager est mise en œuvre par HS.FHIRServer.Storage.Json.RepoManager qui est la mise en œuvre par défaut du serveur FHIR.

Où trouver le code

Tout le code source peut être trouvé dans le référentiel : iris-fhir-python-strategy Le dossier src contient les dossiers suivants :

  • python : contient le code python
  • cls : contient le code ObjectScript utilisé pour appeler le code python

Comment mettre en œuvre une Stratégie

Dans cette démonstration de faisabilité, nous nous intéresserons uniquement à la manière d'implémenter une Strategie en Python, et non à la manière de mettre en œuvre un RepoManager.

Pour mettre en œuvre une Strategie vous devez créer au moins deux classes :

  • Une classe qui hérite de la classe HS.FHIRServer.API.InteractionsStrategy
  • Une classe qui hérite de la classe HS.FHIRServer.API.Interactions

Mise en œuvre d'InteractionsStrategy

La classe HS.FHIRServer.API.InteractionsStrategy vise à personnaliser le comportement du serveur FHIR en remplaçant les méthodes suivantes :

  • GetMetadataResource : appelé pour récupérer les métadonnées du serveur FHIR
    • C'est la seule méthode que nous remplacerons dans cette preuve de concept

HS.FHIRServer.API.InteractionsStrategy a également deux paramètres :

  • StrategyKey : un identifiant unique pour la stratégie InteractionsStrategy
  • InteractionsClass : le nom de votre sous-classe Interactions

Mise en œuvre des Interactions

La classe HS.FHIRServer.API.Interactions vise à personnaliser le comportement du serveur FHIR en remplaçant les méthodes suivantes :

  • OnBeforeRequest : appelée avant l'envoi de la requête au serveur
  • OnAfterRequest : appelée après l'envoi de la requête au serveur
  • PostProcessRead : appelée une fois l'opération de lecture terminée
  • PostProcessSearch : appelée une fois l'opération de recherche terminée
  • Read : appelée pour lire une ressource
  • Add : appelée pour ajouter une ressource
  • Update : appelée pour mettre à jour une ressource
  • Delete : appelée pour supprimer une ressource
  • et bien d'autres...

Nous mettons en œuvre la classe HS.FHIRServer.API.Interactions dans la classe src/cls/FHIR/Python/Interactions.cls.

 
Spoiler
Class FHIR.Python.Interactions Extends (HS.FHIRServer.Storage.Json.Interactions, FHIR.Python.Helper)
{

Parameter OAuth2TokenHandlerClass As%String = "FHIR.Python.OAuth2Token";

Method %OnNew(pStrategy As HS.FHIRServer.Storage.Json.InteractionsStrategy) As%Status { // %OnNew est appelé lors de la création de l'objet.// Le paramètre pStrategy est l'objet de stratégie qui a créé cet objet.// La mise en œuvre par défaut ne fait rien// D'abord, le chemin d'accès à python est défini à partir d'une variable d'environnementset..PythonPath = $system.Util.GetEnviron("INTERACTION_PATH") // Définissez ensuite le nom de la classe python à partir de la variable d'environnementset..PythonClassname = $system.Util.GetEnviron("INTERACTION_CLASS") // Puis définissez le nom du module python à partir de la variable d'environnementset..PythonModule = $system.Util.GetEnviron("INTERACTION_MODULE")

<span class="hljs-keyword">if</span> (<span class="hljs-built_in">..PythonPath</span> = <span class="hljs-string">""</span>) || (<span class="hljs-built_in">..PythonClassname</span> = <span class="hljs-string">""</span>) || (<span class="hljs-built_in">..PythonModule</span> = <span class="hljs-string">""</span>) {
	<span class="hljs-comment">//quit ##super(pStrategy)</span>
	<span class="hljs-keyword">set</span> <span class="hljs-built_in">..PythonPath</span> = <span class="hljs-string">"/irisdev/app/src/python/"</span>
	<span class="hljs-keyword">set</span> <span class="hljs-built_in">..PythonClassname</span> = <span class="hljs-string">"CustomInteraction"</span>
	<span class="hljs-keyword">set</span> <span class="hljs-built_in">..PythonModule</span> = <span class="hljs-string">"custom"</span>
}


<span class="hljs-comment">// Définissez ensuite la classe python</span>
<span class="hljs-keyword">do</span> <span class="hljs-built_in">..SetPythonPath</span>(<span class="hljs-built_in">..PythonPath</span>)
<span class="hljs-keyword">set</span> <span class="hljs-built_in">..PythonClass</span> = <span class="hljs-keyword">##class</span>(FHIR.Python.Interactions).GetPythonInstance(<span class="hljs-built_in">..PythonModule</span>, <span class="hljs-built_in">..PythonClassname</span>)

<span class="hljs-keyword">quit</span> <span class="hljs-keyword">##super</span>(pStrategy)

}

Method OnBeforeRequest( pFHIRService As HS.FHIRServer.API.Service, pFHIRRequest As HS.FHIRServer.API.Data.Request, pTimeout As%Integer) { // OnBeforeRequest est appelée avant le traitement de chaque demande.if$ISOBJECT(..PythonClass) { set body = ##class(%SYS.Python).None() if pFHIRRequest.Json '= "" { set jsonLib = ##class(%SYS.Python).Import("json") set body = jsonLib.loads(pFHIRRequest.Json.%ToJSON()) } do..PythonClass."on_before_request"(pFHIRService, pFHIRRequest, body, pTimeout) } }

Method OnAfterRequest( pFHIRService As HS.FHIRServer.API.Service, pFHIRRequest As HS.FHIRServer.API.Data.Request, pFHIRResponse As HS.FHIRServer.API.Data.Response) { // OnAfterRequest est appelée après le traitement de chaque demande.if$ISOBJECT(..PythonClass) { set body = ##class(%SYS.Python).None() if pFHIRResponse.Json '= "" { set jsonLib = ##class(%SYS.Python).Import("json") set body = jsonLib.loads(pFHIRResponse.Json.%ToJSON()) } do..PythonClass."on_after_request"(pFHIRService, pFHIRRequest, pFHIRResponse, body) } }

Method PostProcessRead(pResourceObject As%DynamicObject) As%Boolean { // PostProcessRead est appelée après la lecture d'une ressource dans la base de données.// Renvoyez 1 pour indiquer que la ressource doit être incluse dans la réponse.// Renvoyez 0 pour indiquer que la ressource doit être exclue de la réponse.if$ISOBJECT(..PythonClass) { if pResourceObject '= "" { set jsonLib = ##class(%SYS.Python).Import("json") set body = jsonLib.loads(pResourceObject.%ToJSON()) } return..PythonClass."post_process_read"(body) } quit1 }

Method PostProcessSearch( pRS As HS.FHIRServer.Util.SearchResult, pResourceType As%String) As%Status { // PostProcessSearch est appelée après l'exécution d'une recherche.// Renvoyez $$$OK pour indiquer que la recherche a abouti.// Renvoyez un code d'erreur pour indiquer que la recherche a échoué.if$ISOBJECT(..PythonClass) { return..PythonClass."post_process_search"(pRS, pResourceType) } quit$$$OK }

Method Read( pResourceType As%String, pResourceId As%String, pVersionId As%String = "") As%DynamicObject { return##super(pResourceType, pResourceId, pVersionId) }

Method Add( pResourceObj As%DynamicObject, pResourceIdToAssign As%String = "", pHttpMethod = "POST") As%String { return##super(pResourceObj, pResourceIdToAssign, pHttpMethod) }

/// Renvoie de VersionId pour la version "supprimée" Method Delete( pResourceType As%String, pResourceId As%String) As%String { return##super(pResourceType, pResourceId) }

Method Update(pResourceObj As%DynamicObject) As%String { return##super(pResourceObj) }

}

La classe FHIR.Python.Interactions hérite de la classe HS.FHIRServer.Storage.Json.Interactions et de la classe FHIR.Python.Helper

La classe HS.FHIRServer.Storage.Json.Interactions est la mise en œuvre par défaut du serveur FHIR.

La classe FHIR.Python.Helper vise à aider à appeler du code Python à partir d'ObjectScript.

La classe FHIR.Python.Interactions remplacent les méthodes suivantes :

  • %OnNew : appelée lors de la création de l'objet
    • nous utilisons cette méthode pour définir le chemin python, le nom de la classe python et le nom du module python à partir des variables d'environnement
    • si les variables d'environnement ne sont pas définies, nous utilisons les valeurs par défaut
    • nous définissons également la classe python
    • nous appelons la méthode %OnNew de la classe parente
Method %OnNew(pStrategy As HS.FHIRServer.Storage.Json.InteractionsStrategy) As %Status
{
	// Définissez d'abord le chemin python à partir d'une variable d'environnement
	set ..PythonPath = $system.Util.GetEnviron("INTERACTION_PATH")
	// Puis définissez le nom de la classe python à partir de la variable d'environnement
	set ..PythonClassname = $system.Util.GetEnviron("INTERACTION_CLASS")
	// Puis définissez le nom du module python à partir de la variable d'environnement
	set ..PythonModule = $system.Util.GetEnviron("INTERACTION_MODULE")

	if (..PythonPath = "") || (..PythonClassname = "") || (..PythonModule = "") {
		// utilisez les valeurs par défaut
		set ..PythonPath = "/irisdev/app/src/python/"
		set ..PythonClassname = "CustomInteraction"
		set ..PythonModule = "custom"
	}

	// Ensuite, définissez la classe python
	do ..SetPythonPath(..PythonPath)
	set ..PythonClass = ..GetPythonInstance(..PythonModule, ..PythonClassname)

	quit ##super(pStrategy)
}
  • OnBeforeRequest : appelée avant l'envoi de la requête au serveur
    • nous appelons la méthode on_before_request de la classe python
    • nous passons l'objet HS.FHIRServer.API.Service, l'objet HS.FHIRServer.API.Data.Request, le corps de la requête et le timeout
Method OnBeforeRequest(
	pFHIRService As HS.FHIRServer.API.Service,
	pFHIRRequest As HS.FHIRServer.API.Data.Request,
	pTimeout As %Integer)
{
	// OnBeforeRequest est appelée avant le traitement de chaque requête.
	if $ISOBJECT(..PythonClass) {
		set body = ##class(%SYS.Python).None()
		if pFHIRRequest.Json '= "" {
			set jsonLib = ##class(%SYS.Python).Import("json")
			set body = jsonLib.loads(pFHIRRequest.Json.%ToJSON())
		}
		do ..PythonClass."on_before_request"(pFHIRService, pFHIRRequest, body, pTimeout)
	}
}
  • OnAfterRequest : appelée après l'envoi de la requête au serveur
    • nous appelons la méthode on_after_request de la classe python
    • nous passons l'objet HS.FHIRServer.API.Service, l'objet HS.FHIRServer.API.Data.Request, l'objet HS.FHIRServer.API.Data.Response et le corps de la réponse
Method OnAfterRequest(
	pFHIRService As HS.FHIRServer.API.Service,
	pFHIRRequest As HS.FHIRServer.API.Data.Request,
	pFHIRResponse As HS.FHIRServer.API.Data.Response)
{
	// OnAfterRequest est appelée après le traitement de chaque requête.
	if $ISOBJECT(..PythonClass) {
		set body = ##class(%SYS.Python).None()
		if pFHIRResponse.Json '= "" {
			set jsonLib = ##class(%SYS.Python).Import("json")
			set body = jsonLib.loads(pFHIRResponse.Json.%ToJSON())
		}
		do ..PythonClass."on_after_request"(pFHIRService, pFHIRRequest, pFHIRResponse, body)
	}
}
  • Et ainsi de suite...

Interactions en Python

La classeFHIR.Python.Interactions appelle les méthodes on_before_request, on_after_request, ... de la classe python.

Voici la classe python abstraite :

import abc
import iris

class Interaction(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def on_before_request(self, 
                          fhir_service:'iris.HS.FHIRServer.API.Service',
                          fhir_request:'iris.HS.FHIRServer.API.Data.Request',
                          body:dict,
                          timeout:int):
        """
        on_before_request is called before the request is sent to the server.
        param fhir_service: the fhir service object iris.HS.FHIRServer.API.Service
        param fhir_request: the fhir request object iris.FHIRServer.API.Data.Request
        param timeout: the timeout in seconds
        return: None
        """
        

    @abc.abstractmethod
    def on_after_request(self,
                         fhir_service:'iris.HS.FHIRServer.API.Service',
                         fhir_request:'iris.HS.FHIRServer.API.Data.Request',
                         fhir_response:'iris.HS.FHIRServer.API.Data.Response',
                         body:dict):
        """
        on_after_request is called after the request is sent to the server.
        param fhir_service: the fhir service object iris.HS.FHIRServer.API.Service
        param fhir_request: the fhir request object iris.FHIRServer.API.Data.Request
        param fhir_response: the fhir response object iris.FHIRServer.API.Data.Response
        return: None
        """
        

    @abc.abstractmethod
    def post_process_read(self,
                          fhir_object:dict) -> bool:
        """
        post_process_read is called after the read operation is done.
        param fhir_object: the fhir object
        return: True the resource should be returned to the client, False otherwise
        """
        

    @abc.abstractmethod
    def post_process_search(self,
                            rs:'iris.HS.FHIRServer.Util.SearchResult',
                            resource_type:str):
        """
        post_process_search is called after the search operation is done.
        param rs: the search result iris.HS.FHIRServer.Util.SearchResult
        param resource_type: the resource type
        return: None
        """

Mise en œuvre de la classe abstraite python

from FhirInteraction import Interaction

class CustomInteraction(Interaction):

    def on_before_request(self, fhir_service, fhir_request, body, timeout):
        #Extract the user and roles for this request
        #so consent can be evaluated.
        self.requesting_user = fhir_request.Username
        self.requesting_roles = fhir_request.Roles

    def on_after_request(self, fhir_service, fhir_request, fhir_response, body):
        #Clear the user and roles between requests.
        self.requesting_user = ""
        self.requesting_roles = ""

    def post_process_read(self, fhir_object):
        #Evaluate consent based on the resource and user/roles.
        #Returning 0 indicates this resource shouldn't be displayed - a 404 Not Found
        #will be returned to the user.
        return self.consent(fhir_object['resourceType'],
                        self.requesting_user,
                        self.requesting_roles)

    def post_process_search(self, rs, resource_type):
        #Iterate through each resource in the search set and evaluate
        #consent based on the resource and user/roles.
        #Each row marked as deleted and saved will be excluded from the Bundle.
        rs._SetIterator(0)
        while rs._Next():
            if not self.consent(rs.ResourceType,
                            self.requesting_user,
                            self.requesting_roles):
                #Mark the row as deleted and save it.
                rs.MarkAsDeleted()
                rs._SaveRow()

    def consent(self, resource_type, user, roles):
        #Example consent logic - only allow users with the role '%All' to see
        #Observation resources.
        if resource_type == 'Observation':
            if '%All' in roles:
                return True
            else:
                return False
        else:
            return True

Trop long, faisons un résumé

La classeFHIR.Python.Interactions est un wrapper pour appeler la classe python.

Les classes abstraites IRIS sont implémentées pour envelopper les classes abstraites python 🥳.

Cela nous aide à séparer le code python et le code ObjectScript et à bénéficier ainsi du meilleur des deux mondes.

0
0 69
Article Sylvain Guilbaud · Mars 22, 2024 5m read

L'invention et la vulgarisation des grands modèles de langage (tels que GPT-4 d'OpenAI) ont lancé une vague de solutions innovantes capables d'exploiter de grands volumes de données non structurées qui étaient peu pratiques, voire impossibles, à traiter manuellement jusqu'à récemment. Ces applications peuvent inclure la récupération de données (voir le cours ML301 de Don Woodlock pour une excellente introduction à Retrieval Augmented Generation), l'analyse des sentiments, et même des agents d'IA entièrement autonomes, pour n'en nommer que quelques-uns !

0
0 112
Article Sylvain Guilbaud · Fév 23, 2024 5m read

Dans cet article, je partagerai le thème que nous avons présenté lors du Global Summit 2023, dans la salle Tech Exchange. Moi et @Rochael Ribeiro

Lors de cette présentation, nous abordons les sujets suivants :

  • Outils Open Exchange pour des API rapides
  • Spécification de l'Open API
  • Développement d'API traditionnel ou Fast
  • API composite (interopérabilité)
  • Approche Spec-First ou Api-First
  • Gouvernance et surveillance des API
  • Démo (vidéo)

Outils Exchange ouverts pour des API Fast

0
2 113
Article Sylvain Guilbaud · Fév 23, 2024 3m read

Bonjour la communauté !

Nous avons publié une nouvelle version d'IrisApiTesterIl intègre plusieurs nouveautés telles que :

  • Dépôts externes : nous avons ajouté la possibilité d'utiliser des collections d'un référentiel (GitHub ou Bitbucket) au lieu de faire glisser manuellement les fichiers de la collection vers votre page Web.
  • Pull and Run : nous avons créé un nouveau point de terminaison qui extrait automatiquement les modifications du référentiel et exécute des tests.
  • Tests unitaires/d'intégration : ajout d'exemples d'utilisation d'IrisApiTester dans les tests unitaires et d'intégration.
  • CI/CD : nous avons ajouté de nouveaux points de terminaison pour les flux de travail tels que GitHub afin d'extraire automatiquement les modifications du référentiel de collection à chaque validation terminée, d'exécuter des tests et d'envoyer les résultats à Google Chat.

 

0
0 42
Article Sylvain Guilbaud · Fév 15, 2024 6m read

Dans cet article, nous allons voir comment utiliser le service de messagerie instantanée WhatsApp depuis InterSystems IRIS pour envoyer des messages à différents destinataires. Pour ce faire, nous devons créer et configurer un compte dans Meta et configurer une opération métier pour envoyer les messages que nous souhaitons.

Examinons chacune de ces étapes plus en détail.

Créer un compte sur Meta

C'est peut-être le point le plus compliqué de toute la configuration, puisque nous devrons configurer une série de comptes jusqu'à ce que nous puissions avoir la fonctionnalité de messagerie.

0
0 107
Question Pierre LaFay · Fév 13, 2024

Bonjour à tous,

Nous développons une application avec FrontEnd (angular) et BackEnd (objectscript Iris), nous utilisons l'identification intégrée grâce à la route /login fournie par %CSP.REST. Nous n'utilisons pas IAM, nous attaquons l'API directement.

Nous avons besoin de générer un traitement suite à un login qu'il soit réussi ou non (enregistrement dans une log applicative).

Nous avons essayé de créer une méthode Login dans notre classe d'API, avec un appel à super(), mais cela ne fonctionne pas car notre méthode n'est pas appelée par la route, qui appele Login de %CSP.Rest.

0
0 52
Article Pierre LaFay · Jan 6, 2024 23m read

Jusqu'à présent, nous avons expliqué comment utiliser ObjectScript pour gérer les utilisateurs, les rôles, les ressources et les applications. Il existe quelques autres classes dans ce package qui fonctionnent de manière similaire à celles mentionnées ci-dessus. Cependant, ces quatre classes sont celles que chacun devra utiliser pour gérer la sécurité de ses applications. Supposons que vous souhaitiez créer votre propre portail de gestion de la sécurité pour ce package. Il y aurait des problèmes spécifiques à prendre en compte pour une API. Étant donné que les classes utilisent des méthodes

1
0 64
Question Cyril Grosjean · Nov 15, 2023

Bonjour,

Dans le besoin de notre service infrastructure de notre entreprise, j'ai créé une petite API qui fait des requêtes SNMP sur InterSystems afin de visualiser les données intéressantes à récupérer lorsque l'infra mettra en place le monitoring.

Cependant, j'ai un timeout lorsque j'essaye de collecter des informations via un walk. Voici le code du service SNMP de mon API:

7
0 111
Article Sylvain Guilbaud · Mai 15, 2023 5m read

Aperçu général

En passant d'IRIS objectScript à Python, on s'aperçoit qu'il existe des différences syntaxiques fascinantes.

L'une d'entre elles concerne la manière dont Python renvoie des tuples à partir d'une méthode à décompression automatique.

En fait, il s'agit d'une méthode qui renvoie plusieurs valeurs. Quelle invention géniale :)

out1, out2 = some_function(in1, in2)

ObjectScript a une autre approche avec les paramètres ByRef et Output.

Do ##class(some_class).SomeMethod(.inAndOut1, in2, .out2)

Où:

  • inAndOut1 représente ByRef
  • out2 représente Output

Le point initiale (".") devant le nom de la variable passe ByRef et pour Output.

Le but de cet article est de décrire comment l'utilitaire communautaire PyHelper a été amélioré pour donner une façon pythonique de tirer parti des paramètres ByRef et Output. Il donne accès à %objlasterror et a une approche pour la gestion des types Python None.
 

Exemple ByRef

L'invocation normale pour python intégré serait :

oHL7=iris.cls("EnsLib.HL7.Message")._OpenId('er12345')

Lorsque cette méthode ne parvient pas à s'ouvrir, la variable "oHL7" est une chaîne vide.
Dans la signature de cette méthode, il y a un paramètre d'état qui est disponible pour le script de l'objet qui donne une explication du problème exact.
Par exemple :

  • L'enregistrement peut ne pas exister
  • L'enregistrement ne peut être ouvert dans le mode d'accès simultané exclusif par défaut ("1"), pendant un timeout.
ClassMethod %OpenId(id As %String = "", concurrency As %Integer = -1, ByRef sc As %Status = {$$$OK}) As %ObjectHandle

La méthode TupleOut peut aider à renvoyer la valeur de l'argument sc dans un contexte python.
 

> oHL7,tsc=iris.cls("alwo.PyHelper").TupleOut("EnsLib.HL7.Message","%OpenId",['sc'],1,'er145999', 0)
> oHL7
''
> iris.cls("%SYSTEM.Status").DisplayError(tsc)
ERROR #5809: Objet à charger introuvable, classe 'EnsLib.HL7.Message', ID 'er145999'1
```

La liste ['sc'] contient un seul élément dans ce cas. Elle peut retourner plusieurs valeurs ByRef, et dans l'ordre spécifié. Ce qui est utile pour décompresser automatiquement vers les variables python prévues.

La gestion des paramètres de sortie (Output) en cas d'exemple

Code Python :

> oHL7=iris.cls("EnsLib.HL7.Message")._OpenId('145')
> oHL7.GetValueAt('&lt;%MSH:9.1')
''

La chaîne renvoyée est vide, mais est-ce parce que l'élément est effectivement vide OU parce que quelque chose s'est mal passé ?
Dans le script objet, il existe également un paramètre de sortie d'état (pStatus) auquel il est possible d'accéder pour déterminer cette condition.

Code script objet :

> write oHL7.GetValueAt("&lt;%MSH:9.1",,.pStatus)
''
> Do $System.Status.DisplayError(pStatus)
ERROR &lt;Ens>ErrGeneral: Aucun segment n'a été trouvé lors du trajet '&lt;%MSH'

Avec TupleOut, la fonctionnalité équivalente peut être atteinte en renvoyant et en décompressant à la fois la valeur de retour de la méthode ET le paramètre de sortie d'état.

Code Python :

> hl7=iris.cls("EnsLib.HL7.Message")._OpenId(145,0)
> val, status = iris.cls("alwo.PyHelper").TupleOut(hl7,"GetValueAt",['pStatus'],1,"&lt;&$BadMSH:9.1")
> val==''
True
> iris.cls("%SYSTEM.Status").IsError(status)
1
> iris.cls("%SYSTEM.Status").DisplayError(status)
ERROR &lt;Ens>ErrGeneral: Aucun segment n'a été trouvé lors du trajet '&lt;&$BadMSH'1

Variable spéciale %objlasterror

Dans ObjectScript, il est possible d'accéder à des variables de pourcentage dans le cadre d'une méthode.
Dans certains cas, il est utile de détecter la variable spéciale %objlasterror ou d'y accéder après avoir appelé une API CORE ou une API de tiers.
La méthode TupleOut permet d'accéder à %objlasterror, comme si elle avait été définie en tant que paramètre de sortie, lors de l'invocation de méthodes à partir de Python.

> del _objlasterror

> out,_objlasterror=iris.cls("alwo.PyHelper").TupleOut("EnsLib.HL7.Message","%OpenId",['%objlasterror'],1,'er145999', 0)

> iris.cls("%SYSTEM.Status").DisplayError(_objlasterror)
ERROR #5809: Objet à charger introuvable, classe 'EnsLib.HL7.Message', ID 'er145999'1

Quand "None" n'est pas une chaîne

TupleOut traite les références python "None" comme objectscript "undefined". Cela permet aux paramètres d'être définis par défaut et aux méthodes de se comporter de manière cohérente.
C'est important, par exemple, dans le cas de %Persistent::%OnNew, où la méthode %OnNew n'est pas déclenchée lorsque "None" est fourni comme valeur initiale "initvalue", alors qu'elle serait déclenchée si une chaîne vide était fournie.

En objectscript, l'implémentation pourrait être la suivante :

do oHL7.myMethod("val1",,,"val2")

Notez l'absence de variables entre les virgules.

TupleOut facilite le même comportement avec :

Python:

iris.cls("alwo.PyHelper").TupleOut(oHL7,"myMethod",[],0,"val1",None,None,"val2")

Une autre façon d'envisager la question est d'avoir une implémentation du code d'invocation en une seule ligne, qui se comporte de manière flexible en fonction de la configuration préalable des variables :

Object Script:

set arg1="val1"
kill arg2
kill arg3
set arg4="val2"
do oHL7.myMethod(.arg1, .arg2, .arg3, .arg4)

TupleOut facilite le même comportement avec :

Python:

arg1="val1"
arg2=None
arg3=None
arg4="val2"
iris.cls("alwo.PyHelper").TupleOut(oHL7,"myMethod",[],0,arg1,arg2,arg3,arg4)

Liste et dictionnaires

Lors de la gestion des paramètres d'entrée, de ByRef et Output, TupleOut utilise la correspondance automatique de PyHelper entre: l les listes IRIS et les listes Python
les tableaux IRIS et les tableaux Python
Il prend soin de toujours utiliser des chaînes pour représenter les clés du dictionnaire lorsqu'il passe des tableaux IRIS aux types Dict de Python.

Conclusion

J'espère que cet article contribuera à inspirer de nouvelles idées et discussions sur les idées et suggestions relatives à Python intégré.

J'espère aussi qu'il encouragera à explorer la flexibilité d'IRIS, qui peut facilement s'adapter à de nouveaux défis.

0
0 80
Article Lucas Enard · Avr 3, 2023 10m read

Sur GitHub, vous trouverez toutes les informations sur l'utilisation d'un modèle d'apprentissage automatique "HuggingFace" / modèle d'IA sur le cadre IRIS à l'aide de Python.

1. iris-huggingface

Utilisation de modèles d'apprentissage automatique dans IRIS à l'aide de Python ; pour les modèles texte-texte, texte-image ou image-image.

Les modèles suivants servent d'exemple :

2. Installation

2.1. Lancement de la production

Dans le dossier iris-local-ml, ouvrez un terminal et saisisse :

docker-compose up

La première fois, cela peut prendre quelques minutes pour construire l'image de manière correcte et installer tous les modules nécessaires à Python.

2.2. Accès à la production

En suivant ce lien, vous accédez à la production : Access the Production

2.3. Clôture de la production

docker-compose down

Comment ça marche

Pour l'instant, certains modèles peuvent ne pas fonctionner avec cette implémentation car tout est fait automatiquement, ce qui veut dire que, quel que soit le modèle que vous saisissez, nous essaierons de le faire fonctionner grâce à la bibliothèque transformerspipeline.

Pipeline est un outil puissant de l'équipe HuggingFace qui va scanner le dossier dans lequel nous avons téléchargé le modèle, puis il va déterminer quelle bibliothèque il doit utiliser entre PyTorch, Keras, Tensorflow ou JAX pour ensuite charger ce modèle en utilisant AutoModel.
À partir de ce point, en saisissant la tâche, le pipeline sait ce qu'il doit faire avec le modèle, l'analyseur lexical ou même l'extracteur de caractéristiques dans ce dossier, et gère automatiquement votre entrée, l'analyse et la traite, la transmet au modèle, puis restitue la sortie sous une forme décodée directement utilisable par nous.

3. API HuggingFace

Vous devez d'abord démarrer la démo, en utilisant le bouton vert Start ou Stop et Start à nouveau pour appliquer vos changements de configuration.

Ensuite, en cliquant sur l'opération Python.HFOperation de votre choix, et en sélectionnant dans l'onglet de droite action, vous pouvez tester la démo.

Dans cette fenêtre test, sélectionnez :

Type de demande : Grongier.PEX.Message

Pour le classname vous devez saisir :

msg.HFRequest

Et pour le json, voici un exemple d'appel à GPT2 :

{
    "api_url":"https://api-inference.huggingface.co/models/gpt2",
    "payload":"Veuillez nous donner plus de détails sur votre ",
    "api_key":"----------------------"
}

Vous pouvez maintenant cliquer sur le bouton Visual Trace (Trace visuelle) pour voir en détail ce qui s'est passé et consulter les journaux.

REMARQUE : vous devez avoir une clé API de HuggingFace avant d'utiliser cette opération (les clés API sont gratuites, il suffit de s'enregistrer auprès de HF).

REMARQUE : vous pouvez changer l'url pour essayer n'importe quel autre modèle de HuggingFace, mais vous devrez peut-être changer le payload.

Par exemple :
sending hf reqhf reqhf resp

4. Utilisation de n'importe quel modèle sur le web

Dans cette section, nous vous apprendrons à utiliser presque tous les modèles disponibles sur l'internet, qu'il s'agisse de HuggingFace ou non.

4.1. PREMIER CAS : VOUS AVEZ VOTRE PROPRE MODÈLE

Dans ce cas, vous devez copier-coller votre modèle, avec la configuration, l'outil tokenizer.json etc. dans un dossier à l'intérieur du dossier model.
Chemin d'accès : src/model/yourmodelname/

A partir de là, vous devez aller dans les paramètres de Python.MLOperation.
Cliquez sur Python.MLOperation puis rendez-vous dans settings dans l'onglet de droite, puis dans la partie Python, puis dans la partie %settings. Ici, vous pouvez saisir ou modifier n'importe quel paramètre (n'oubliez pas d'appuyer sur apply une fois que vous avez terminé).
Voici la configuration par défaut pour ce cas :
%settings

name=yourmodelname
task=text-generation

REMARQUE : tous les paramètres qui ne sont pas name ou model_url sont placés dans les paramètres de PIPELINE.

NMaintenant vous pouvez double-cliquer sur l'opération Python.MLOperation et la démarrer. Vous devez voir dans la partie Log le démarrage de votre modèle.

A partir de là, nous créons une PIPELINE en utilisant des transformateurs qui utilisent votre fichier de configuration situé dans le dossier comme nous l'avons vu précédemment.

Pour appeler ce pipeline, cliquez sur l'opération Python.MLOperation , et sélectionnez dans l'onglet de droite action, vous pouvez tester la démo.

Dans cette fenêtre test, sélectionnez :

Type de demande : Grongier.PEX.Message

Pour le classname (nom de classe), vous devez saisir :

msg.MLRequest

Et pour le json, vous devez saisissez tous les arguments nécessaires à votre modèle. Voici un exemple d'appel à GPT2 :

{
    "text_inputs":"Malheureusement, le résultat",
    "max_length":100,
    "num_return_sequences":3
}

Cliquez sur Invoke Testing Service (Invoquer le service de test) et attendez que le modèle fonctionne.

Voir par exemple :
sending ml req

Vous pouvez maintenant cliquer sur Visual Trace (Trace visuelle) pour voir en détail ce qui s'est passé et consulter les journaux.

Voir par exemple :
ml req

ml resp

4.2. DEUXIÈME CAS : VOUS VOULEZ TÉLÉCHARGER UN MODÈLE À PARTIR DE HUGGINGFACE

Dans ce cas, vous devez trouver l'URL du modèle sur HuggingFace ;

4.2.1. Paramètres

À partir de là, vous devez accéder aux paramètres de la Python.MLOperation.
Cliquez sur Python.MLOperation puis allez dans des paramètres settings dans l'onglet de droite, puis dans la partie Python, puis dans la partie %settings. Ici, vous pouvez saisir ou modifier n'importe quel paramètre (n'oubliez pas d'appuyer sur apply (appliquer) une fois que vous avez terminé).
Voici quelques exemples de configuration pour certains modèles que nous avons trouvés sur HuggingFace :

%settings pour gpt2

model_url=https://huggingface.co/gpt2
name=gpt2
task=text-generation

%settings pour camembert-ner

name=camembert-ner
model_url=https://huggingface.co/Jean-Baptiste/camembert-ner
task=ner
aggregation_strategy=simple

%settings pour bert-base-uncased

name=bert-base-uncased
model_url=https://huggingface.co/bert-base-uncased
task=fill-mask

%settings pour detr-resnet-50

name=detr-resnet-50
model_url=https://huggingface.co/facebook/detr-resnet-50
task=object-detection

%settings pour detr-resnet-50-protnic

name=detr-resnet-50-panoptic
model_url=https://huggingface.co/facebook/detr-resnet-50-panoptic
task=image-segmentation

REMARQUE : tous les paramètres qui ne sont pas name ou model_url iront dans les paramètres du PIPELINE, donc dans notre second exemple, le pipeline camembert-ner requiert une stratégie aggregation_strategy et une tâche task qui sont spécifiées ici alors que le pipeline gpt2 ne requiert qu'une tâche task.

Voir par exemple :
settings ml ope2

Vous pouvez maintenant double-cliquer sur l'opération Python.MLOperation et la démarrer.
Vous devez voir dans la partie Log le démarrage de votre modèle et le téléchargement.
REMARQUE : Vous pouvez actualiser ces journaux toutes les x secondes pour voir l'évolution des téléchargements. dl en temps réel

A partir de là, nous créons une PIPELINE en utilisant des transformateurs qui utilisent votre fichier de configuration qui se trouve dans le dossier comme nous l'avons vu précédemment.

4.2.2. Tests

Pour appeler ce pipeline, cliquez sur l'opération Python.MLOperation , et sélectionnez dans l'onglet de droite action, vous pouvez tester la démo.

Dans cette fenêtre test, sélectionnez :

Type de demande : Grongier.PEX.Message

Pour le classname (nom de classe), vous devez saisir :

msg.MLRequest

Et pour le json, vous devez saisir tous les arguments nécessaires à votre modèle. Voici un exemple d'appel à GPT2 ( Python.MLOperation ) :

{
    "text_inputs":"George Washington a vécu",
    "max_length":30,
    "num_return_sequences":3
}

Voici un exemple d'appel à Camembert-ner ( Python.MLOperation2 ) :

{
    "inputs":"George Washington a vécu à Washington"
}

Voici un exemple d'appel à bert-base-uncased ( Python.MLOperation3 ) :

{
    "inputs":"George Washington a vécu à [MASQUE]."
}

Voici un exemple d'appel à detr-resnet-50 à l'aide d'une url en ligne ( Python.MLOperationDETRRESNET ) :

{
    "url":"http://images.cocodataset.org/val2017/000000039769.jpg"
}

Voici un exemple d'appel à detr-resnet-50-panoptic utilisant l'url comme chemin d'accès( Python.MLOperationDetrPanoptic ) :

{
    "url":"/irisdev/app/misc/000000039769.jpg"
}

Cliquez sur Invoke Testing Service et attendez que le modèle fonctionne.
Vous pouvez maintenant cliquer sur Visual Trace pour voir en détail ce qui s'est passé et consulter les journaux.

REMARQUE : Lorsque le modèle a été téléchargé pour la première fois, la production ne le téléchargera pas à nouveau mais récupérera les fichiers mis en cache dans src/model/TheModelName/.
Si certains fichiers sont manquants, la production les téléchargera à nouveau.

Voir par exemple :
sending ml reqml reqml resp

Voir par exemple :
sending ml reqml resp

5. Dépannage

Si vous avez des problèmes, la lecture est le premier conseil que nous pouvons vous donner, la plupart des erreurs sont facilement compréhensibles simplement en lisant les journaux car presque toutes les erreurs seront capturées par un try / catch et enregistrées.

Si vous avez besoin d'installer un nouveau module, ou une dépendance Python, ouvrez un terminal à l'intérieur du conteneur et saisissez par exemple : "pip install new-module"
Il y a plusieurs façons d'ouvrir un terminal,

  • Si vous utilisez les plugins InterSystems, vous pouvez cliquer sur la barre ci-dessous dans VSCode, celle qui ressemble à docker:iris:52795[IRISAPP] et sélectionner Open Shell in Docker (Ouvrir l'enveloppe dans Docker).
  • Dans n'importe quel terminal local, saisissez : docker-compose exec -it iris bash
  • Depuis Docker-Desktop, trouvez le conteneur IRIS et cliquez sur Open in terminal (Ouvrir dans le terminal).

Certains modèles peuvent nécessiter des modifications au niveau de leur pipeline ou de leurs paramètres, par exemple, et c'est à vous qu'il incombe d'ajouter les informations adéquates dans les paramètres et dans la demande.

6. Conclusion

À partir de là, vous devriez pouvoir utiliser n'importe quel modèle dont vous avez besoin ou que vous possédez sur IRIS.
REMARQUE : vous pouvez créer une Python.MLOperation pour chacun de vos modèles et les activer en même temps.

0
0 189
Article Lucas Enard · Sept 19, 2022 5m read

Cet article aborde les questions de Questionnaire et QuestionnaireResponse de FHIR depuis la création du formulaire jusqu'au téléchargement sur le serveur et la façon de les remplir.

tl;dr :

  • En utilisant cet outil en ligne vous pouvez facilement créer votre propre formulaire en partant de zéro ou en utilisant un modèle d'un formulaire existant.
  • En utilisant ce serveur FHIR local d'InterSystems you can easily store your FHIR resources and Questionnaire.
  • En utilisant cet application vous pouvez manipuler, comme si vous étiez un praticien, le questionnaire et la réponse pour chaque patient sur votre serveur FHIR.

Il est à noter que l'application ne communique pas en utilisant le Content-Type 'application/json+fhir' mais juste le Content-Type 'application/json' donc cela ne fonctionnera pas de cette manière avec notre serveur FHIR local d' InterSystems.

C'est pourquoi j'ai créé ce repo GitHub contenant une version modifiée de l'application, fonctionnant avec Content-Type 'application/json+fhir', contenant un serveur FHIR local et un lien vers l'outil de construction de questionnaires avec quelques explications.
Après avoir cloné le repo, en faisant docker-compose up -d, npm ci, npm run build et ensuite npm run start vous serez accueilli avec un accès à l'app, en sélectionnant le serveur FHIR que vous voulez et le Patient avec lequel vous voulez travailler, vous pourrez remplir Questionnaire et les enregistrer sur votre serveur en 2 clics.

Fin de tl;dr Ce qui suit est le ReadMe du GitHub.

1. Application pour les formulaires FHIR utilisant un serveur fhir local

Il s'agit d'une application principalement basée sur ce référentiel qui peut être utilisée pour afficher les éléments suivants
FHIR
SDC
Questionnaire
et collecter les données en tant que ressources FHIR QuestionnaireResponse.
En la développant à l'aide de docker-compose up -d vous aurez accès à un serveur FHIR local qui pourra ensuite être utilisé pour tester l'application.

2. Conditions requises

L'application s'appuie sur le widget de visualisation LHC-Forms pour l'affichage des formulaires. Elle prend partiellement en charge les FHIR Questionnaires (versions STU3 et R4) et le Guide d'implémentation de la capture de données structurées.
Ce widget sera installé avec les dépendances.

Pour essayer des exemples de formulaires, ce référentiel est livré avec des formulaires dans le répertoire e2e-test/data/R4 qui sont automatiquement chargés dans le serveur FHIR local lors de la construction.

2.1. Ajout de Node.js et npm à votre route

Le fichier bashrc.lforms-fhir-app spécifie la version de Node.js utilisée pour le développement. Téléchargez cette version de Node.js, et ajoutez son répertoire bin à votre route.

2.2. Installation des dépendances

En exécutant cette commande, vous serez en mesure d'installer tout ce qui est nécessaire pour que l'application fonctionne.

npm ci

3. Serveur FHIR local

Si vous ne disposez pas d'un serveur FHIR pour essayer cette application, vous pouvez démarrer et utiliser un serveur FHIR local alimenté par les technologies InterSystems en faisant dans le dossier fhir-form :

docker-compose up -d

After some wait, your local FHIR server is up and you can access it by using http://localhost:32783/fhir/r4
Sachez que ce lien est déjà enregistré dans l'application.

4. Utilisation de l'application

Pour utiliser l'application, vous devez la construire et ensuite la lancer.
Vous pouvez maintenant accéder à n'importe quel serveur FHIR à l'aide du menu de l'application, mais si vous le souhaitez, vous pouvez utiliser ce serveur FHIR local

4.1. Construction de l'application

npm run build

Les fichiers pour la production seront créés dans un répertoire "dist", mais certains fichiers nécessaires seront également copiés à partir de node_modules.

4.2. Lancement de l'application

npm run start

va lancer un serveur http fonctionnant sur le port 8000.

Maintenant, naviguez vers l'application à localhost:8000/lforms-fhir-app/.

Ici, vous pouvez choisir un serveur auquel vous voulez vous connecter.
Si vous souhaitez utiliser le serveur FHIR local, démarrez le serveur FHIR local puis, dans l'application, sélectionnez le premier choix http://localhost:32783/fhir/r4

5. Formulaire FHIR / questionnaire

5.1. Développement de votre propre formulaire FHIR

En utilisant this online tool ous pouvez facilement créer votre propre formulaire en partant de zéro ou en utilisant un formulaire existant.
Il est conseillé d'importer l'un de ceux qui existent dans le dossier e2e-tests/data/R4 et de commencer à partir de là pour comprendre le fonctionnement de l'outil.

5.2. Importation de votre propre formulaire FHIR

En utilisant l'application, vous pouvez facilement importer vos formulaires locaux et les utiliser immédiatement en utilisant le bouton de téléchargement upload.

Si vous utilisez l'outil de construction de formulaires [formbuilder tool] (https://lhcformbuilder.nlm.nih.gov/beta/), vous pouvez, si votre serveur FHIR prend en charge le type de contenu 'application/json', exporter le formulaire que vous créez directement vers le serveur FHIR en utilisant le bouton d'exportation export.

Si votre serveur ne supporte pas le Content-Type 'application/json' mais seulement le Content-Type 'application/json+fhir' par exemple, comme notre serveur FHIR local vous devez exporter le formulaire dans un fichier, puis dans l'application, et télécharger par upload le fichier sur le serveur en tant que l'application communique en Content-Type 'application/json+fhir'.

3
0 194
Article Kevin Koloska · Nov 9, 2022 5m read

Nous sommes une startup technologique - Virtual Lab qui développe des solutions utilisant des technologies avancées VR / AR. Nous disposons d’un vaste portefeuille de produits et de solutions personnalisés. Aujourd’hui, nous aimerions vous présenter le projet VR ICU® – une plate-forme de formation pour le personnel médical de l’uci, créée à l’ère du Covid pour les besoins des hôpitaux.

0
0 66
Article Guillaume Rongier · Juil 22, 2022 10m read

Introduction

Depuis la version 2019.2, InterSystems IRIS fournit son API native pour Python comme méthode d'accès aux données haute performance. L'API native vous permet d'interagir directement avec la structure de données IRIS native.

Globales

En tant que développeurs InterSystems, vous êtes probablement déjà familiarisés avec les globales. Nous allons passer en revue les bases au cas où vous souhaiteriez un rafraîchissement, mais n'hésitez pas à passer directement à la section suivante.

InterSystems IRIS utilise des globales pour stocker les données. Une globale est un tableau clairsemé qui se compose de nœuds qui peuvent ou non avoir une valeur et de sous-nœuds. Ce qui suit est un exemple abstrait d'une globale :

Représentation arborescente d'une globale

Dans cet exemple, a il y a un nœud racine, appelé nom global. Chaque nœud possède une adresse de nœud qui se compose du nom global et d'un ou plusieurs indices (noms des sous-nœuds). a possède les indices b and c; l'adresse de ces noeuds est a->b et a->c.

Les noeuds a->b et a->c->g ont une valeur (d et h), les noeuds a->b->e et a->b->f n'ont aucune valeur. Le noeud a->b possède les indices e et f.

Une description approfondie de cette structure peut être trouvée dans le livre InterSystems "Utilisation des globaux" ("Using Globals").

Lecture et écriture dans la globale

Native Python API permet de lire et d'écrire directement des données dans la globale IRIS. Le paquet irisnative est disponible sur GitHub — ou si InterSystems IRIS est installé localement sur votre machine, vous le trouverez dans le sous-répertoire dev/python de votre répertoire d'installation.

La fonction irisnative.createConnection vous permet de créer une connexion à IRIS et la fonction irisnative.createIris vous donne un objet de cette connexion avec lequel nous pouvons manipuler la globale. Cet objet possède les méthodes get et set pour lire/écrire depuis/vers la globale, et une méthode kill pour supprimer un nœud et ses sous-nœuds. Il possède également une méthode isDefined qui renvoie 0 si le noeud demandé n'existe pas ; 1 s'il a une valeur, mais pas de descendants ; 10 s'il n'a pas de valeur et a des descendants ; ou 11 s'il a une valeur et des descendants.

import irisnative conn = irisnative.createConnection("127.0.0.1", 51773, "USER", "", "") iris = irisnative.createIris(conn) iris.set("value", "root", "sub1", "sub2") # sets "value" to root->sub1->sub2 print(iris.get("root", "sub1", "sub2")) print(iris.isDefined("root", "sub1")) iris.kill("root") conn.close()

Il dispose également d'une méthode iterator pour boucler sur les sous-nœuds d'un certain nœud. (L'utilisation sera démontrée dans la section suivante.)

Pour une description complète de chaque méthode, reportez-vous à la documentation de l'interface API .

Les fichiers de données sur le trafic de San Francisco GTFS

Stockage des données dans la globale

La Spécification générale des flux de transport en commun (GTFS) est un format pour les horaires et les itinéraires des transports publics. Regardons comment nous pouvons utiliser l'API native IRIS pour travailler avec les données GTFS de San Francisco à partir du 10 juin 2019.

Tout d'abord, nous allons stocker les informations des fichiers de données dans la globale IRIS. (Tous les fichiers et toutes les colonnes ne seront pas utilisés dans cette démo). Les fichiers sont au format CSV, où la première ligne indique les noms des colonnes et toutes les autres lignes contiennent les données. En Python, nous commencerons par effectuer les importations nécessaires et établir une connexion à IRIS :

import csv import irisnative

conn = irisnative.createConnection("127.0.0.1", 51773, "USER", "", "") iris = irisnative.createIris(conn)

Sur la base des noms de colonnes et des données, nous pouvons construire une arborescence judicieuse pour chaque fichier et utiliser iris.set pour stocker les données dans la globale.

Commençons par le fichier stops.txt, qui contient tous les arrêts de transport public de la ville. Dans ce fichier, nous n'utiliserons que les colonnes stop_id et stop_name. Nous allons les stocker dans une globale nommée stops une structure arborescente avec une couche de nœuds, avec les ID des arrêts comme indices et le nom des arrêts comme valeurs des nœuds. Notre structure ressemble donc à stops → [stop_id]=[stop_name]. (Pour cet article, j'utiliserai des crochets pour indiquer quand un indice n'est pas littéral, mais plutôt une valeur lue dans les fichiers de données.)

with open("stops.txt", "r") as csvfile: reader = csv.reader(csvfile) next(reader) # Ignorez les noms des colonnes

# stops -> [stop_id]=[stop_name]
for row in reader:
    iris.set(row[6], "stops", row[4])

csv.reader retourne un itérateur de listes qui contiennent les valeurs séparées par des virgules. La première ligne contient les noms des colonnes, nous allons donc la sauter avec next(reader). Nous utiliserons iris.set pour définir le nom de l'arrêt comme valeur de stops -> [stop_id].

Ensuite, il y a le fichier routes.txt dont nous utiliserons les colonnes route_type, route_id, route_short_name et route_long_name. Une structure globale raisonnable est routes -> [route_type] -> [route_id] -> [route_short_name]=[route_long_name]. (Le type d'itinéraire est 0 pour un tram, 3 pour un bus et 5 pour un téléphérique.) Nous pouvons lire le fichier CSV et placer les données dans la globale exactement de la même manière.

with open("routes.txt", "r") as csvfile: reader = csv.reader(csvfile) next(reader) # Ignorez les noms des colonnes

# routes -> [route_type] -> [route_id] -> [route_short_name]=[route_long_name]
for row in reader:
    iris.set(row[0], "routes", row[1], row[5], row[8])

Chaque itinéraire a des trajets trips, stockés dans trips.txt, dont nous utiliserons les colonnes route_id, direction_id, trip_headsign et trip_id. Les trajets sont identifiés de manière unique par leur trip ID (que nous verrons plus tard dans le fichier des temps d'arrêt). Les trajets sur une route peuvent être séparés en deux groupes en fonction de leur direction, et les directions sont associées à des panneaux de tête. Cela conduit à la structure arborescente trips -> [route_id] -> [direction_id]=[trip_headsign] -> [trip_id].

Nous avons besoin de deux appels iris.set ici — un pour définir la valeur du nœud ID de la direction, et un pour créer le nœud sans valeur de l'ID du trajet.

with open("trips.txt", "r") as csvfile: reader = csv.reader(csvfile) next(reader) # Ignorez les noms des colonnes

# trips -> [route_id] -> [direction_id]=[trip_headsign] ->[trip_id]
for row in reader:
    iris.set(row[3], "trips", row[1], row[2])
    iris.set(None, "trips", row[1], row[2], row[6])

Enfin, nous allons lire et stocker les temps d'arrêt. Ils sont stockés dans le fichier stop_times.txt et nous allons utiliser les colonnes stop_id, trip_id, stop_sequence et departure_time. Une première option pourrait consister à utiliser stoptimes -> [stop_id] -> [trip_id] -> [departure_time] ou si nous voulons conserver la séquence des arrêts, stoptimes -> [stop_id] -> [trip_id] -> [stop_sequence]=[departure_time].

with open("stop_times.txt", "r") as csvfile: reader = csv.reader(csvfile) next(reader) # Ignorez les noms des colonnes
# stoptimes -> [stop_id] -> [trip_id] -> [stop_sequence]=[departure_time]
for row in reader:
    iris.set(row[2], "stoptimes", row[3], row[0], row[4])

Interrogation des données à l'aide de l'API native

Ensuite, notre objectif est de trouver toutes les heures de départ pour l'arrêt avec le nom donné.

Tout d'abord, nous récupérons l'ID de l'arrêt à partir du nom de l'arrêt donné, puis nous utilisons cet ID pour trouver les heures pertinentes dans le fichier stop_times.

L'appel iris.iterator("stops") nous permet d'itérer sur les sous-nœuds du nœud racine stops. Nous voulons itérer sur les paires d'indices et de valeurs (pour comparer les valeurs avec le nom donné, et connaître immédiatement l'indice s'il correspond), nous appelons donc .items() sur l'itérateur, ce qui définit le type de retour en tuples (indice, valeur). Nous pouvons alors itérer sur tous ces tuples et trouver le bon arrêt.

stop_name = "Silver Ave & Holyoke St"

iter = iris.iterator("stops").items()

stop_id = None

for item in iter: if item[1] == stop_name: stop_id = item[0] break

if stop_id is None: print("Stop not found.") import sys sys.exit()

Il convient de noter que la recherche d'une clé par sa valeur par itération n'est pas très efficace s'il y a beaucoup de nœuds. Une façon d'éviter cela serait d'avoir un autre tableau, où les indices sont les noms des arrêts et les valeurs sont les IDs. La recherche de la valeur --> clé consisterait alors en une requête dans ce nouveau tableau.

Vous pouvez également utiliser le nom de l'arrêt comme identifiant partout dans votre code au lieu de l'ID de l'arrêt - le nom de l'arrêt est également unique.

Comme vous pouvez le voir, si nous avons une quantité importante d'arrêts, cette recherche peut prendre un certain temps - elle est également connue sous le nom de "balayage complet". Mais nous pouvons profiter des globales et construire le tableau inversé où les noms seront les clés et les IDs les valeurs.

iter = iris.iterator("stops").items()

stop_id = None

for item in iter: iris.set(item[0], "stopnames", item[1])

En disposant de la globale de stopnames, où l'index est le nom et la valeur est l'ID, le code ci-dessus pour trouver le stop_id par le nom sera remplacé par le code suivant qui s'exécutera sans une recherche par balayage complet :

stop_name = "Silver Ave & Holyoke St" stop_id=iris.get("stopnames", stop_name) if stop_id is None: print("Stop not found.") import sys sys.exit()

À ce stade, nous pouvons trouver les heures d'arrêt. Le sous-arbre stoptimes -> [stop_id] contient les ID des trajets en tant que sous-nœuds, qui contiennent les temps d'arrêt en tant que sous-nœuds. Nous ne sommes pas intéressés par les ID de trajet - seulement par les temps d'arrêt - donc nous allons itérer sur tous les ID de trajet et collecter tous les temps d'arrêt pour chacun d'eux.

all_stop_times = set()

trips = iris.iterator("stoptimes", stop_id).subscripts() for trip in trips: all_stop_times.update(iris.iterator("stoptimes", stop_id, trip).values())

Nous n'utilisons pas .items() sur l'itérateur ici, mais nous utiliserons .subscripts() et .values() car les ID de trajet sont des subscripts (sans valeurs associées) ou la couche inférieure ([stop_sequence]=[departure_time]), nous sommes seulement intéressés par les valeurs et les heures de départ. L'appel .update ajoute tous les éléments de l'itérateur à notre ensemble existant. L'ensemble contient maintenant toutes les heures d'arrêt (uniques) :

for stop_time in sorted(all_stop_times): print(stop_time)

Rendons les choses un peu plus compliquées. Au lieu de trouver toutes toutes les heures de départ d'un arrêt, nous allons trouver uniquement les heures de départ d'un arrêt pour un itinéraire donné (dans les deux sens) où l'ID de l'itinéraire est donné. Le code permettant de trouver l'ID de l'arrêt à partir du nom de l'arrêt peut être conservé dans son intégralité. Ensuite, tous les ID des arrêts sur l'itinéraire donné seront récupérés.

Le sous-arbre de trips -> [route_id] est divisé en deux directions, qui ont tous les ID de trajets comme sous-nœuds. Nous pouvons itérer sur les directions comme précédemment, et ajouter tous les sous-noeuds des directions à un ensemble.

route = "14334"

selected_trips = set()

directions = iris.iterator("trips", route).subscripts() pour la direction dans les directions : selected_trips.update(iris.iterator("trips", route, direction).subscripts())

L'étape suivante consiste à trouver les valeurs de tous les sous-nœuds de stoptimes -> [stop_id] -> [trip_id][stop_id] est l'identifiant de l'arrêt récupéré et [trip_id] est l'un des identifiants de trajet sélectionnés. Nous itérons sur l'ensemble selected_trips pour trouver toutes les valeurs pertinentes :

all_stop_times = set()

pour le trajet dans selected_trips: all_stop_times.update(iris.iterator("stoptimes", stop_id, trip).values())

pour stop_time dans sorted(all_stop_times): print(stop_time)

Un dernier exemple montre l'utilisation de la fonction isDefined. Nous allons développer le code écrit précédemment : au lieu de coder en dur l'ID de la route, le nom court d'une route est donné, puis l'ID de la route doit être récupéré sur cette base. Les noeuds avec les noms de route sont sur la couche inférieure de l'arbre. La couche supérieure contient les ID des routes. Nous pouvons itérer sur tous les types de route, puis sur tous les ID de route, et si le noeud routes -> [route_type] -> [route_id] -> [route_short_name] existe et a une valeur (isDefined retourne 1), alors nous savons que [route_id] est l'ID que nous recherchons.

route_short_name = "44" route = None

types = iris.iterator("routes").subscripts() for type in types: route_ids = iris.iterator("routes", type).subscripts() for route_id in route_ids: if iris.isDefined("routes", type, route_id, route_short_name) == 1: route = route_id

if route is None: print("No route found.") import sys sys.exit()

Ce code sert à remplacer la ligne route = "14334" codée en dur.

Lorsque toutes les opérations IRIS sont terminées, nous pouvons fermer la connexion à la base de données :

conn.close()

Prochaines étapes

Nous avons couvert comment l'API native de Python peut être utilisée pour accéder à la structure de données d'InterSystems IRIS, puis être appliquée aux données des transports publics de San Francisco. Pour une plongée plus profonde dans l'API, vous pouvez consulter la documentation . L'API native est également disponible pour Java, .NET et Node.js.

0
0 128
Article Guillaume Rongier · Juin 24, 2022 7m read

Dans cette série d'articles en trois parties, il est montré comment vous pouvez utiliser IAM pour ajouter simplement de la sécurité, selon les normes OAuth 2.0, à un service précédemment non authentifié déployé dans IRIS.

Dans la première partie, nous avons fourni des informations sur OAuth 2.0 ainsi que des définitions et des configurations initiales d'IRIS et d'IAM afin de faciliter la compréhension de l'ensemble du processus de sécurisation de vos services.

La deuxième partie discute et montre en détail les étapes nécessaires pour configurer IAM pour valider le jeton d'accès présent dans la demande entrante et transmettre la demande au backend si la validation réussit.

Cette dernière partie de cette série abordera et démontrera les configurations nécessaires pour que IAM génère un jeton d'accès (agissant comme un serveur d'autorisation) et le valide, ainsi que quelques considérations finales importantes.

Si vous voulez essayer IAM, veuillez contacter votre représentant commercial d'InterSystems.

Scénario 2 : IAM comme serveur d'autorisation et validateur de jetons d'accès

Dans ce scénario, contrairement au premier scénario, nous allons utiliser un plugin appelé "OAuth 2.0 Authentication".

Afin d'utiliser IAM comme serveur d'autorisation dans ce flux d'informations d'identification du propriétaire des ressources et du mot de passe, le nom d'utilisateur et le mot de passe doivent être authentifiés par l'application cliente. La demande d'obtention du jeton d'accès auprès d'IAM ne doit être effectuée que si l'authentification est réussie.

Commençons par l'ajouter à notre "SampleIRISService". Comme vous pouvez le voir dans la capture d'écran ci-dessous, nous avons différents champs à remplir afin de configurer ce plugin.

Tout d'abord, nous allons copier l'identifiant de notre service "SampleIRISService" dans le champ "service_id" pour activer ce plugin à notre service.

Dans le champ "config.auth_header_name", nous allons spécifier le nom de l'en-tête qui portera le jeton d'autorisation. Dans ce cas, je vais laisser la valeur par défaut comme "authorization".

Le plugin "OAuth 2.0 Authentication" prend en charge les flux OAuth 2.0 Authorization Code Grant, Client Credentials, Implicit Grant ou Resource Owner Password Credentials Grant (respectivement, Attribution de codes d'autorisation, Identifiants client, Attribution implicite et Attribution des informations d'identification du mot de passe du propriétaire de la ressource OAuth 2.0). Comme nous utilisons dans cet article le flux "Resource Owner Password Credentials" (Identifiants du mot de passe du propriétaire de la ressource), nous allons cocher la case "config.enable_password_grant"..

Dans le champ "config.provision_key", saisissez une chaîne à utiliser comme clé de provision. Cette valeur sera utilisée pour demander un jeton d'accès à IAM.

Dans ce cas, j'ai laissé tous les autres champs avec la valeur par défaut. Vous pouvez vérifier la référence complète de chaque champ dans la documentation du plugin disponible ici.

Voici à quoi ressemble la configuration du plugin à la fin :

Une fois le plugin créé, nous devons créer les informations d'identification de notre consommateur "ClientApp".

Pour ce faire, allez dans "Consumers" dans le menu de gauche et cliquez sur "ClientApp". Ensuite, cliquez sur l'onglet "Credentials" et ensuite sur le bouton "New OAuth 2.0 Application".

Sur la page suivante, entrez un nom quelconque pour identifier votre application dans le champ "name" (nom), définissez un identifiant et un secret de client, respectivement, dans les champs "client_id" et "client_secret" et enfin, entrez l'URL dans votre application où les utilisateurs seront envoyés après autorisation dans le champ "redirect_uri". Ensuite, cliquez sur "Create" (créer).

Maintenant, vous êtes prêt à envoyer des demandes.

La première requête que nous devons faire est d'obtenir le jeton d'accès depuis IAM. Le plugin "OAuth 2.0 Authentication" crée automatiquement un point de terminaison en ajoutant le chemin "/oauth2/token" à l'itinéraire déjà créé.

Note: Assurez-vous que vous utilisez le protocole HTTPS et que le port proxy d'IAM prête attention aux requêtes TLS/SSL (le port par défaut est 8443). Il s'agit d'une exigence d'OAuth 2.0.

Par conséquent, dans ce cas, nous devrions faire une demande POST à l'URL :

https://iamhost:8443/event/oauth2/token

Dans le corps de la requête, vous devez inclure le JSON suivant :

{
   "client_id": "clientid",
   "client_secret": "clientsecret",
   "grant_type": "password",
   "provision_key": "provisionkey",
   "authenticated_userid": "1"
}

Comme vous pouvez le constater, ce JSON contient des valeurs définies à la fois lors de la création du plugin "OAuth 2.0 Authentication", telles que "grant_type" et "provision_key", et lors de la création des informations d'identification du Consommateur, telles que "client_id" et "client_secret".

Le paramètre "authenticated_userid" doit également être ajouté par l'application client lorsque le nom d'utilisateur et le mot de passe fournis sont authentifiés avec succès. Sa valeur doit être utilisée pour identifier de manière unique l'utilisateur authentifié.

La demande et sa réponse respective devraient ressembler à ceci :

Avec cela, nous pouvons maintenant faire une requête pour obtenir les données de l'événement en incluant la valeur "access_token" de la réponse ci-dessus comme "Bearer Token" (jeton de porteur) dans une requête GET vers l'URL

https://iamhost:8443/event/1

Si votre jeton d'accès expire, vous pouvez générer un nouveau jeton d'accès en utilisant le jeton de renouvellement que vous avez reçu avec le jeton d'accès expiré en effectuant une requête POST vers le même point de terminaison que celui utilisé pour obtenir un jeton d'accès, avec un corps quelque peu différent :

{
   "client_id": "clientid",
   "client_secret": "clientsecret",
   "grant_type": "refresh_token",
   "refresh_token": "E50m6Yd9xWy6lybgo3DOvu5ktZTjzkwF"
}

La demande et sa réponse respective devraient ressembler à ceci :

Une fonctionnalité intéressante du plugin "OAuth 2.0 Authentication" est la possibilité d'afficher et d'invalider les jetons d'accès.

Pour répertorier les tokens, envoyez une requête GET au point de terminaison suivant de l'API d'administration d'IAM :

https://iamhost:8444/{workspace_name}/oauth2_tokens

où {workspace_name} est le nom de l'espace de travail IAM utilisé. Veillez à saisir les informations d'identification nécessaires pour appeler l'API d'administration d'IAM si vous avez activé RBAC.

Notez que "credential_id" est l'identifiant de l'application OAuth que nous avons créée dans le consommateur ClientApp (dans ce cas, elle s'appelle SampleApp), et "service_id" est l'identifiant de notre "SampleIRISService" auquel ce plugin est appliqué.

Pour invalider un jeton, vous pouvez envoyer une demande DELETE au point de terminaison suivant

https://iamhost:8444/Sample/oauth2_tokens/{token_id}

où {token_id} est l'identifiant du jeton à invalider.

Si nous essayons d'utiliser le jeton invalidé, nous obtenons un message indiquant que le jeton est invalide ou a expiré si nous envoyons une requête GET contenant ce jeton invalidé comme jeton porteur à l'URL :

https://iamhost:8443/event/1

Considérations finales

Dans cet article, nous avons montré comment vous pouvez ajouter l'authentification OAuth 2.0 dans IAM à un service non authentifié déployé dans IRIS. Vous devez tenir compte du fait que le service lui-même continuera à être non authentifié dans IRIS. Par conséquent, si quelqu'un appelle directement le point de terminaison du service IRIS, en contournant la couche IAM, il pourra voir les informations sans aucune authentification. Pour cette raison, il est important d'avoir des règles de sécurité au niveau du réseau pour empêcher les demandes non désirées de contourner la couche IAM.

Vous pouvez en savoir plus sur IAM ici.

Si vous voulez essayer IAM, veuillez contacter votre représentant commercial d'InterSystems.

0
0 203
Article Guillaume Rongier · Juin 22, 2022 4m read

Dans cette série d'articles en trois parties, il est montré comment vous pouvez utiliser IAM pour ajouter simplement de la sécurité, selon les normes OAuth 2.0, à un service précédemment non authentifié déployé dans IRIS.

Dans la première partie, nous avons fourni des informations sur OAuth 2.0 ainsi que des définitions et des configurations initiales d'IRIS et d'IAM afin de faciliter la compréhension de l'ensemble du processus de sécurisation de vos services.

Cette partie va maintenant discuter et montrer en détail les étapes nécessaires pour configurer IAM pour valider le jeton d'accès présent dans la demande entrante et transmettre la demande au backend si la validation réussit.

La dernière partie de cette série abordera et démontrera les configurations nécessaires pour que IAM génère un jeton d'accès (agissant comme un serveur d'autorisation) et le valide, ainsi que quelques considérations finales importantes.

Si vous voulez essayer IAM, veuillez contacter votre représentant commercial d'InterSystems.

Scénario 1 : IAM comme validateur de jetons d'accès

Dans ce scénario, il sera utilisé un serveur d'autorisation externe qui génère un jeton d'accès au format JWT (JSON Web Token). Ce JWT est signé à l'aide de l'algorithme RS256 et d'une clé privée. Afin de vérifier la signature du JWT, l'autre partie (dans ce cas IAM) doit avoir la clé publique, fournie par le serveur d'autorisation.

Ce JWT généré par le serveur d'autorisation externe comprend également, dans son corps, une déclaration appelée "exp" contenant l'horodatage de la date d'expiration de ce jeton, et une autre déclaration appelée "iss" contenant l'adresse du serveur d'autorisation.

Par conséquent, IAM doit vérifier la signature du JWT avec la clé publique des serveurs d'autorisation et l'horodatage d'expiration contenu dans la déclaration "exp" à l'intérieur du JWT avant de transmettre la demande à IRIS.

Afin de configurer cela dans IAM, commençons par ajouter un plugin appelé "JWT" à notre "SampleIRISService" dans IAM. Pour ce faire, allez sur la page Services dans IAM et copiez l'identifiant du "SampleIRISService", nous allons l'utiliser plus tard.

Ensuite, allez dans Plugins, cliquez sur le bouton "New Plugin", localisez le plugin "JWT" et cliquez sur Enable.

Dans la page suivante, copiez l'identifiant "SampleIRISService" dans le champ "service_id" et cochez la case "exp" dans le paramètre "config.claims_to_verify".


Notez que la valeur du paramètre "config.key_claim_name" est "iss". Nous allons l'utiliser plus tard.

Ensuite, appuyez sur le bouton "Create" (créer).

Cela fait, allez dans la section "Consumers" dans le menu de gauche et cliquez sur notre "ClientApp" précédemment créée. Allez dans l'onglet "Credentials" (identifiants) et cliquez sur le bouton “New JWT Credential” (nouveau Identifiants JWT).

Dans la page suivante, sélectionnez l'algorithme utilisé pour signer le JWT ( ici RS256) et copiez la clé publique dans le champ "rsa_public_key" (il s'agit de la clé publique qui vous a été fournie par le serveur d'autorisation au format PEM).

Dans le champ "key", vous devez insérer le contenu du revendication JWT que vous avez entré dans le champ "config.key_claim_name" lors de l'ajout du plugin JWT. Donc, dans ce cas, je dois insérer le contenu de la revendication iss de mon JWT, qui, dans mon cas, est l'adresse du serveur d'autorisation.

Après cela, cliquez sur le bouton "Créer".

Hint: À des fins de débogage, il existe un outil en ligne permettant de décoder le JWT afin que vous puissiez vérifier les revendications et leurs valeurs et vérifier les signatures en insérant la clé publique. Voici le lien de cet outil en ligne : https://jwt.io/#debugger

Maintenant, avec l'ajout du plugin JWT, il n'est plus possible d'envoyer la requête sans authentification. Comme vous pouvez le voir ci-dessous, une simple demande GET, sans authentification, renvoie à l'URL

http://iamhost:8000/event/1

un message non autorisé avec le code de statut "401 Unauthorized".

Afin d'obtenir les résultats d'IRIS, nous devons ajouter le JWT à la requête.

Par conséquent, nous devons d'abord demander le JWT au serveur d'autorisation. Le serveur d'autorisation personnalisé que nous utilisons ici renvoie un JWT si une demande POST est faite avec quelques paires clé-valeur dans le corps, y compris des informations sur l'utilisateur et le client, à l'URL suivante :

https://authorizationserver:5001/auth

Voici à quoi ressemblent cette requête et sa réponse :

Ensuite, vous pouvez ajouter le JWT obtenu à partir de la réponse ci-dessous dans le header d'autorisation en tant que jeton de porteur Bearer Token et envoyer une requête GET à la même URL utilisée précédemment :

http://iamhost:8000/event/1

Vous pouvez également l'ajouter en tant que paramètre de chaîne de recherche, la clé de la chaîne de recherche étant la valeur spécifiée dans le champ "config.uri_param_names" lors de l'ajout du plugin JWT qui, dans ce cas, est "jwt" :

Enfin, il y a aussi la possibilité d'inclure JWT dans la requête en tant que cookie, si un nom est saisi dans le champ "config.cookie_names".

Passez à la troisième et dernière partie de cette série pour comprendre les configurations nécessaires pour générer un jeton d'accès IAM et le valider, ainsi que quelques considérations finales importantes.

0
0 80
Article Guillaume Rongier · Juin 20, 2022 5m read

Introduction

Aujourd'hui, de nombreuses applications utilisent le cadre d'autorisation ouvert (OAuth) pour accéder aux ressources de toutes sortes de services de manière sûre, fiable et efficace. InterSystems IRIS est déjà compatible avec le cadre OAuth 2.0, en fait, il y a un excellent article dans la communauté concernant OAuth 2.0 et InterSystems IRIS dans le lien suivant ici.

Toutefois, avec l'avènement des outils de gestion des API, certaines organisations l'utilisent comme point unique d'authentification, empêchant les demandes non autorisées d'arriver aux services descendants et découplant les complexités d'autorisation/authentification du service lui-même.

Comme vous le savez peut-être, InterSystems a lancé son outil de gestion des API, appelé InterSystems API Management (IAM), qui est disponible avec la licence IRIS Enterprise (et non IRIS Community Edition). Vous trouverez ici un autre excellent article de la communauté présentant InterSystems API Management.

 Il s'agit de la première partie d'une série d'articles en trois parties qui montrent comment vous pouvez utiliser IAM pour ajouter simplement de la sécurité, selon les normes OAuth 2.0, à un service précédemment non authentifié déployé dans IRIS.

Dans cette première partie, vous trouverez des informations sur OAuth 2.0 ainsi que des définitions et des configurations initiales d'IRIS et d'IAM afin de faciliter la compréhension de l'ensemble du processus de sécurisation de vos services.

Suite à la première partie, cette série d'articles abordera deux scénarios possibles pour sécuriser vos services avec IAM. Dans le premier scénario, IAM validera uniquement le jeton d'accès présent dans la requête entrante et transmettra la requête au backend si la validation réussit. Dans le second scénario, IAM va à la fois générer un jeton d'accès (en agissant comme un serveur d'autorisation) et le valider.

Par conséquent, la deuxième partie abordera et montrera en détail les étapes nécessaires pour configurer le scénario 1, et la troisième partie abordera et démontrera les configurations pour le scénario 2, ainsi que quelques considérations finales.

Si vous voulez essayer IAM, veuillez contacter votre représentant commercial InterSystems.

OAuth 2.0 : contexte

Chaque flux d'autorisation OAuth 2.0 se compose essentiellement de 4 parties :

  1. Utilisateur
  2. Client
  3. Serveur d'autorisation
  4. Propriétaire de la ressource

Pour des raisons de simplicité, cet article utilisera le flux OAuth "Resource Owner Password Credentials" (Identifiants du mot de passe du propriétaire de la ressource), mais vous pouvez utiliser n'importe quel flux OAuth dans IAM. De même, cet article ne spécifiera aucune portée.

Note: Vous ne devez utiliser le flux d'informations d'identification du mot de passe du propriétaire des ressources que lorsque l'application cliente est hautement fiable, car elle traite directement les informations d'identification des utilisateurs. Dans la plupart des cas, le client doit être une application de première partie.

En général, le flux "Resource Owner Password Credentials" (Identifiants du mot de passe du propriétaire de la ressource) suit les étapes suivantes :

  1. L'utilisateur saisit ses identifiants (par exemple le nom d'utilisateur et le mot de passe) dans l'application client.
  2. L'application client envoie les identifiants de l'utilisateur ainsi que sa propre identification (identifiant et secret du client, par exemple) au serveur d'autorisation. Le serveur d'autorisation valide les identifiants de l'utilisateur et l'identification du client et renvoie un jeton d'accès.
  3. Le client utilise le jeton pour accéder aux ressources du serveur de ressources.
  4. Le serveur de ressources valide le jeton d'accès reçu avant de renvoyer toute information au client.

Dans cette optique, il existe deux scénarios dans lesquels vous pouvez utiliser IAM pour traiter OAuth 2.0 :

  1. IAM agit comme un validateur, vérifiant le jeton d'accès fourni par l'application cliente, transmettant la demande au serveur de ressources uniquement si le jeton d'accès est valide ; dans ce cas, le jeton d'accès serait généré par un serveur d'autorisation tiers.
  2. IAM agissant à la fois comme un serveur d'autorisation, fournissant un jeton d'accès au client, et comme un validateur de jeton d'accès, vérifiant le jeton d'accès avant de rediriger la demande vers le serveur de ressources.

Définitions d'IRIS et d'IAM

Dans ce post, il sera utilisé une application Web IRIS appelée "/SampleService". Comme vous pouvez le voir sur la capture d'écran ci-dessous, il s'agit d'un service REST non authentifié déployé dans IRIS :

En outre, dans le côté IAM est configuré un service appelé "SampleIRISService" contenant un itinéraire, comme vous pouvez le voir dans la capture d'écran ci-dessous :

En outre, dans IAM est configuré un consommateur appelé "ClientApp", initialement sans aucun justificatif d'identité, pour identifier celui qui appelle l'API dans IAM :

Avec les configurations ci-dessus, IAM transmet chaque requête GET envoyée à l'URL suivante à IRIS :

http://iamhost:8000/event

À ce stade, aucune authentification n'est encore utilisée. Par conséquent, si nous envoyons une simple requête GET, sans authentification, à l'URL

http://iamhost:8000/event/1

nous obtenons la réponse recherchée.

Dans cet article, nous allons utiliser une application appelée "PostMan" pour envoyer des requêtes et vérifier les réponses. Dans la capture d'écran de PostMan ci-dessous, vous pouvez voir une simple requête GET ainsi que sa réponse.

Passez à la deuxième partie de cette série pour comprendre comment configurer IAM pour valider les jetons d'accès présents dans les demandes entrantes.

0
0 89
Article Lorenzo Scalese · Juin 18, 2022 5m read

InterSystems API Management (IAM) - c'est une nouvelle fonctionnalité de la plate-forme de données InterSystems IRIS, qui vous permet de surveiller, de contrôler et de gérer le trafic vers et à partir des API basées sur le Web au sein de votre infrastructure informatique. Au cas où vous l'auriez manqué, voici le lien vers l'annonce. Et voici un article expliquant comment commencer à travailler avec IAM.

Dans cet article, nous allons utiliser InterSystems API Management pour assurer l'équilibrage de charge d'une API.

Dans notre cas, nous avons 2 instances InterSystems IRIS avec /api/atelier REST API que nous voulons publier pour nos clients.

Il y a de nombreuses raisons différentes pour lesquelles nous pourrions vouloir faire cela, par exemple :

  • Équilibrage de la charge pour répartir la charge de travail entre les serveurs.
  • Déploiement bleu-vert : nous avons deux serveurs, l'un "prod", l'autre "dev" et nous pouvons vouloir passer de l'un à l'autre.
  • Déploiement canary: nous pourrions publier la nouvelle version sur un seul serveur et y transférer 1% des clients.
  • Configuration de haute disponibilité
  • etc.

Pourtant, les mesures que nous devons prendre sont assez similaires.

Conditions préalables

  • 2 instances InterSystems IRIS
  • L'instance InterSystems API Managemen  

Allons-y

Voici ce que nous devons faire :

1. Créer un flux ascendant.

Un flux ascendant représente un nom d'hôte virtuel et peut être utilisé pour équilibrer la charge des demandes entrantes sur plusieurs services (cibles). Par exemple, un flux ascendant nommé service.v1.xyz recevrait des demandes pour un service dont l'hôte est service.v1.xyz. Les requêtes pour ce service seront envoyées par procuration aux cibles définies dans l'amont.

Un flux ascendant comprend également un vérificateur de santé, qui peut activer et désactiver les cibles en fonction de leur capacité ou de leur incapacité à répondre aux demandes.

Pour commencer :

  • Ouvrir le portail d'administration IAM
  • Allez dans Workspaces
  • Choisissez votre espace de travail
  • Ouvrez les flux ascendants (Upstreams)
  • Cliquez sur le bouton "New Upstream"

Après avoir cliqué sur le bouton "New Upstream", vous verrez apparaître un formulaire où vous pourrez saisir quelques informations de base sur le flux ascendant (il y a beaucoup d'autres propriétés) :

Saisissez nom - il s'agit d'un nom d'hôte virtuel que nos services utiliseraient. Il n'est pas lié aux enregistrements DNS. Je recommande de lui attribuer une valeur inexistante pour éviter toute confusion. Si vous voulez en savoir plus sur les autres propriétés, consultez la documentation. Sur la capture d'écran, vous pouvez voir que j'ai nommé de manière imaginative le nouveau flux ascendant comme myupstream.  

2. Créer des cibles.

Les cibles sont des serveurs backend qui exécutent les requêtes et renvoient les résultats au client. Allez dans Upstreams et cliquez sur le nom du flux ascendant que vous venez de créer (et NON sur le bouton de mise à jour) :

Vous verrez toutes les cibles existantes (aucune jusqu'à présent) et le bouton "Nouvelle cible". Cliquez dessus :

Ensuite, définissez une cible dans le nouveau formulaire. Seuls deux paramètres sont disponibles :

  • cible - hôte et port du serveur backend
  • Pondération - priorité relative donnée à ce serveur (plus de pondération - plus de demandes sont envoyées à cette cible)

J'ai ajouté deux cibles :

 

3. Créer un service

A présent que nous avons notre flux ascendant, nous devons lui envoyer des requêtes.  Pour cela, nous utilisons Service.
Les entités Service, comme leur nom l'indique, sont des abstractions de chacun de vos services en amont. Des exemples de services seraient un microservice de transformation des données, une API de facturation, etc. Nous allons créer un service ciblant notre instance IRIS, allez dans Services et cliquez sur le bouton "Nouveau service" :

Définissez les valeurs suivantes :

champvaleurdescription
nommyservicenom logique de ce service
hôtemyupstreamnom en amont
chemin/api/atelierchemin d'accès associé à une racine que nous voulons servir
protocolehttples protocoles que nous voulons supporter

Conservez les valeurs par défaut pour tout le reste (y compris le port : 80).

Après avoir créé le service, vous le verrez dans une liste de services. Copiez l'ID du service quelque part, nous en aurons besoin plus tard.

 

4. Créer un itinéraire

Les Itinéraires définissent les règles permettant de répondre aux demandes des clients. Chaque Itinéraire est associé à un Service, et un Service peut avoir plusieurs Itinéraires associés. Chaque demande correspondant à un Itinéraire donné sera transmise par proxy au Service qui lui est associé.

La combinaison des Itinéraires et des Services (et la séparation des préoccupations entre eux) offre un mécanisme de routage puissant avec lequel il est possible de définir des points d'entrée très fins dans l'IAM menant à différents services en amont de votre infrastructure.

Maintenant, créons un itinéraire. Allez dans le menu Routes et appuyez sur le bouton "New Route".

Définissez les valeurs dans le formulaire de création de l'Itinéraire :

champvaleurdescription
lien/api/atelierlien racine que nous voulons servir
protocolehttp les protocoles que nous voulons supporter
service.idguid de 3valeur de l'identifiant du service (guide de l'étape précédente)
 

Et c'est fini !

Envoyez une requête à http://localhost:8000/api/atelier/ (notez la barre oblique à la fin) et elle sera servie par l'un de nos deux backends.  

Conclusion

IAM offre une infrastructure de gestion des API hautement personnalisable, permettant aux développeurs et aux administrateurs de prendre le contrôle de leurs API.  

Liens

Question

Quelle fonctionnalité souhaitez-vous voir configurée avec IAM ?

0
0 87