新しい投稿

検索

記事
· 2024年5月19日 10m read

Proteger los datos: Se un mejor cerrajero

Buenas a todos,

 

en capítulos anteriores, vimos como "Como controlar el acceso a tus recursos con OAuth2". En este primer artículo explicábamos como preparar un acceso seguro a nuestros recursos utilizando la potente herramienta que nos ofrece Intersytems del servidor de Autenticación. Al finalizar el mismo, comentábamos que si quisiéramos podríamos aplicar un control extra a este acceso y esto nos lleva a este artículo, por lo que seguiremos el siguiente índice:

1.- Introducción

   1.1..- De donde venimos

2.- Problema

   2.1.- ¿Cómo funciona la llave (Token)?

   2.2.- ¿Qué es una hoja de registro (LookUp Table)?

   2.3.- ¿Cómo construyo las cerraduras?

   2.4.- Cómo avisar a la policía de intrusos

 

1.- Introducción

Para empezar, situemos el problema a resolver:

Llevado a una situación más común imaginemos estar en una vivienda compartida, al cual cada inquilino accede al piso con la llave de la puerta de entrada, pero luego dentro de casa, cada habitación no tuviera llave, por lo que cualquier inquilino podría entrar en la habitación de cualquier otro y ¡no creemos que sea para dejar regalos!

Llegados a este punto, tendremos que poner cerraduras en todas las puertas y asegurar que cada inquilino solo pueda acceder a su habitación. ¡Saquemos al cerrajero que llevamos dentro!

Os dejo un pequeño video que de forma conceptual explica nuestro problema y el resultado de nuestra solución:

 

1.1.-De dónde venimos

Partimos de un servidor de autenticación (puerta de entrada) y un servidor de Recursos (la vivienda). En el servidor de autenticación vamos a tener 2 clientes dados de alta, cada uno con su usuario y su contraseña. Por otro lado, nuestro ESB que hace de servidor de recursos tendrá la labor de consultar los recursos determinados (habitaciones) para cada cliente. Por lo tanto, tenemos:

  • Cliente 1 (inquilino 1)
  • Cliente 2 (inquilino 2)
  • Recursos Cliente 1 (habitación de inquilino 1)
  • Recursos Cliente 2 (habitación de inquilino 2)

 

A continuación un diagrama de flujo del problema encontrado:

2.- Problema

Con la solución actual, nos encontramos con el problema de seguridad de datos, pues, si el cliente 2 pudiera conocer los datos de la petición del cliente 1, Con pasar su propia autorización (llave de la puerta de entrada) hacia los recursos, de la puerta hacia dentro, tendría libertad para acceder a los recursos (habitaciones) que quiera. El propietario de la vivienda nos ha pedido que pongamos una cerradura en cada puerta, así que vamos con ello.

A continuación, se indican los pasos a seguir para ser mejores cerrajeros.

2.1.- ¿Cómo funciona la llave (Token)?

            El Servidor de Autenticación, una vez recibe un usuario y una contraseña válidos, nos devolverá un token con el siguiente formato:

{

    "access_token""eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJqdGkiOiJodHRwczovL2F1dGhzcnZyLnNjcy1zYWx1ZC5vcmc6NTc3NzYvb2F1dGgyLmdqQnZqR01JQzJqeVBYZW12dW5EWW1vTnJnMCIsImlzcyI6Imh0dHBzOi8vYXV0aHNydnIuc2NzLXNhbHVkLm9yZzo1Nzc3Ni9vYXV0aDIiLCJzdWIiOiJ5WUZIZElGWDQyZEVEV3FhZHhzWFJxbmZtZW1IVEVZYVFlQ09JbWRKVXpRIiwiZXhwIjoxNzE2MTU0Mjk4LCJhdWQiOiJ5WUZIZElGWDQyZEVEV3FhZHhzWFJxbmZtZW1IVEVZYVFlQ09JbWRKVXpRIn0.",

    "token_type""bearer",

    "expires_in"60,

    "scope""my/scope"
}

Este “Access_token” que viene en base64 se compone de información interesante para nuestro objetivo. Sabiendo que este token se genera por JWT, una vez tratado, vemos que se compone de:

  • Header
  • Payload

Header

Se compone de:

{

  "typ": "JWT",

  "alg": "none"
}

 

Payload

Se compone de:

{

  "jti": "https://authsrvr.org:57775/oauth2.gjBvjGMIC2jyPXemvunDYmoNrg0",

  "iss": "https://authsrvr.org:57775/oauth2",

  "sub": "yYFHdIFX42dEDWqadxsXRqnfmemHTEYaQeCOImdJUzQ",

  "exp": 1716154298,

  "aud": "yYFHdIFX42dEDWqadxsXRqnfmemHTEYaQeCOImdJUzQ"
}

 

Del payload el dato que nos vamos a quedar es el “aud”, ya que este dato es el usuario registrado en el servidor de autenticación que hemos creado previamente.

Para más información sobre este contenido, podéis consultar la documentación oficial de IS: (https://docs.intersystems.com/irisforhealthlatest/csp/documatic/%25CSP.Documatic.cls?LIBRARY=%25SYS&CLASSNAME=%25SYS.OAuth2.Validation)

 

2.2.- ¿Qué es una hoja de registro (LookUp Table)?

No profundizaremos en este momento en las LoopUp Tables, lo que, si nos interesa saber en este punto, es que son unas tablas internas de cada namespace, en las cuales podemos guardar datos en el formato “clave/valor”.

Para más información sobre este contenido, podéis consultar la documentación oficial de IS:

https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=ECONFIG_other_lookup_tables

 

2.3.- ¿Cómo construyo las cerraduras?

En este punto juntemos los 2 puntos anteriores, es decir, con el escenario actual, tenemos:

                -              Un dato del Token: “aud”

                -              Una tabla interna que almacena datos: “clave/valor”

Como responsables de la seguridad, sabemos que a este cliente solo hay que dejarle acceder a sus propios recursos, por lo que para ello, en la LookUp table, vamos a guardar:

-              Clave: el “aud”

-              Valor: el condicionante de acceso a los recursos. En este ejemplo pongamos “1”.

 

Ahora que ya tenemos preparados los "materiales", nos toca construir la cerradura. Para ello explicamos a continuación los pasos a Seguir:

2.3.1.-  Recepción del Token

2.3.2.-  Extracción y validación del “aud”

 

2.3.1.-  Recepción del Token

Partimos para el ejemplo de un servicio REST que tendrá los siguientes parámetros:

Method MISERVICIO(pInput As %Stream.Object, Output pOutput As %Stream.Object, indicadorRecursos As %String(MAXLEN=""))As %Status

La información que vamos a requerir viene en el pInput y el indicadorRecursos. En el inicio de nuestro servicio observemos las siguientes líneas y lo que hace cada una:

{
    //Necesitamos sacar la cabecera "Authorization" de la petición REST
    set authorization = $tr(pInput.GetAttribute("authorization"),"")

    //Necesitamos sacar Token
    set token = $PIECE(authorization,"Bearer ",2)

    //Necesitamos validar el Token. Este apartado lo vamos a obviar en esta ocasión.
    set respuesta = ..ResServer(token)
    if (respuesta = 1){ Avanzar en el servicio } else{ Devolver error }

    //Necesitamos validar el “aud”
    set audValidado = ..ValidarUsernameOAUTH2(token,indicadorRecursos,.pOutput)

    //Si el “aud” es válido, podemos avanzar, sino salimos con el mensaje de respuesta que configuremos
    if (audValidado = 0)
    {
        quit ERROR            
    }
}

Como podemos ver, en la línea de validación del "aud" nos encontramos con la llamada a un método (ValidarUsernameOAUTH2) el cual os expongo a continuación.

 

2.3.2.-  Extracción del “aud”

En el siguiente método podemos ver paso a paso como se extrae y valida el "aud".

ClassMethod ValidarUsernameOAUTH2(token As %String(MAXLEN=""), indicadorRecursos As %String(MAXLEN=""), Output pOutput As %Stream.Object) As %Boolean
{
 set claseAux = ##class(%ZEN.Auxiliary.jsonProvider).%New()
   
 // Buscamos el cliente de recursos
 Set client = ##class(OAuth2.Client).Open("resserver",.sc)
 If client  = "" Quit      
 // Inicializamos nuestra referencia para acceder a los recursos, pues si no cambia de valor, nunca podremos acceder a los recursos
 set codigoRecursosOAUTH2 = ""
 try{
  // Convertir JWT a objeto 
  set sc = ..JWTToObject(client,token,.securityParameters,.jsonObject)

  // Extraemos el “aud” del JSON que generamos al convertir el Token
  set usuarioOAUTH2 = jsonObject.aud

  // Extraemos de la LookUpTable que creamos en el paso anterior, el Valor que nos da el usuario que hemos extraído del Token. Si este valor es “”, quiere decir que no existe el usuario. Si existe, extraemos el Valor. Este valor es el que tendremos que enfrentar con el indicadorRecursos que tenemos en la entrada. Pues si estos no coinciden, querrá decir que el usuario está intentando acceder a recursos a los cuales no le hemos autorizado acceder.
  set codigoRecursosOAUTH2 = ##class(Util.TablasMaestras).getValorMaestra("SERVIDORAUTH.VALIDACION",usuarioOAUTH2)

 }catch{
  // Si hay errores, devolvemos una respuesta de error de acceso
  set response             = ##class(Mensajes.Response.Autorización.DatosResponse).%New()
  set response.codigo      = "-4"
  set response.descripcion = “Error de acceso"

  set tSC = claseAux.%WriteJSONStreamFromObject(.pOutput,.response,,,,"aeloqtuw")
   
  // Enviamos el JSON con cabeceras
  Do:$$$ISOK(tSC) pOutput.SetAttribute("Content-Type","application/json")
  do pOutput.SetAttribute("Access-Control-Allow-Origin","*")
  do pOutput.SetAttribute("Access-Control-Allow-Credentials","true")
  do pOutput.SetAttribute("Access-Control-Allow-Methods","GET")
  do pOutput.SetAttribute("Access-Control-Allow-Headers","request,Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers")
 }

 // Si hubo error, significa que el token es incorrecto. Por lo tanto devolvemos un 0
 if (codigoRecursosOAUTH2 = ""){
    Quit '$$$OK                           
 }
 // Si la consulta a la LoopUp Table nos devolvió datos, debemos hacer ahora la validación de este valor.
 if (codigoRecursosOAUTH2 '= ""){
    // Si son distintos, significa que el aud NO es de estos recursos
    if (codigoRecursosOAUTH2 '= indicadorRecursos){
     set response             = ##class(Mensajes.Response.Autorización.DatosResponse).%New()
     set response.codigo      = "-3"
     set response.descripcion = “Consulta no Autorizada"
     set tSC = claseAux.%WriteJSONStreamFromObject(.pOutput,.response,,,,"aeloqtuw")
    
     // Enviamos el JSON con cabeceras
     Do:$$$ISOK(tSC) pOutput.SetAttribute("Content-Type","application/json")
     do pOutput.SetAttribute("Access-Control-Allow-Origin","*")
     do pOutput.SetAttribute("Access-Control-Allow-Credentials","true")
     do pOutput.SetAttribute("Access-Control-Allow-Methods","GET")
     do pOutput.SetAttribute("Access-Control-Allow-Headers","request,Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers")

  // Si son distintos, el método responde un 0
     Quit '$$$OK                                                          
    }
 }

 // Si son iguales, el método responde un 1
 quit $$$OK
}

Aclarando este apartado:

Supongamos que el indicadorRecursos de entrada viene a "2". Cuando vayamos a comparar el valor obtenido de la LoopUpTable ("1") con este valor, no coincidirán, por lo que no será posible acceder a los recursos. En cambio, si este valor de entrada es "1", si coincidirá y podrá acceder a los mismos.

Llegados a este punto, ya habríamos aplicado la cerradura (seguridad) a nuestra primera habitación (recursos). Para el resto de habitaciones, bastaría con repetir los mismos pasos para el resto de clientes/recursos.

2.4.- Cómo avisar a la policía de intrusos

Una vez detectado quien puede acceder o no a los recursos, podemos plantearnos monitorizar si alguien se esta pasando de listillo intentando acceder a recursos que no le corresponden. Para ello, podemos hacer uso de las herramientas de Intersystems para el envío de emails, notificaciones push, o incluso alimentar cuadros de mando y tener un mayor control de estos accesos incorrectos. Estas alertas deben configurarse en el momento que vamos a devolver un "0", pues es el momento donde tenemos los datos de acceso así como la respuesta del acceso no permitido.

 

La redacción de este artículo se ha planteado de forma esquematizada para que pueda ser adaptada a cualquier aplicación que puedan plantear. Se ha dejado indicado el código mínimo para que puedan entender y reutilizar de forma lo mas práctica posible. Os prometo que si seguís las indicaciones paso a paso para entender el proceso, ¡empezareis a poner cerraduras por doquier!

Finalmente espero que les sea de utilidad, ¡y que se conviertan en mejores cerrajeros!

Muchas gracias por el tiempo que han dedicado a esta lectura.

PD:Por favor, no duden en plantear cuestiones que ayuden a mejorar la redacción y explicación del mismo por si algo no ha quedado correctamente entendido.

3 Comments
ディスカッション (3)3
続けるにはログインするか新規登録を行ってください
記事
· 2024年5月19日 7m read

IRIS BI開発者向けチュートリアルを試してみる(10)

はじめに

IRIS BIチュートリアル試してみたシリーズの10回目です。
今回はチュートリアル最後のページ「ピボット・テーブルおよびダッシュボードの作成とパッケージ化」についてです。
これまでアーキテクトとアナライザを使用してきましたが、今回はユーザポータル画面を使ってダッシュボードを作成していきます。
では、早速はじめていきましょう。

ピボット・テーブルの作成

ダッシュボードはピボットテーブルをソースデータとして作成することができます。ですので、まずはソースとなるピボットテーブルを作成します。
アナライザ画面を開き、Tutorial キューブを開きます。
AgeD ディメンジョン内の Age Group レベルを [行] にドラッグ&ドロップし、続いて Age Bucket レベルを Age Group レベルの矢印記号 ↘ のところにドラッグ&ドロップします。
 
そうしますと、Age Group レベルの隣に Age Bucket レベルが表示されます。[行] の表示も、Age Bucket レベルが一段下げられた形で表示されています。

※注意:サンプルデータはランダムに作成されるため、こちらの画面表示とみなさまの実行結果は一致しないことがあります。
 
さらに Count メジャーを [列] に追加し、All Patients メンバを [行] に追加します。
All Patients をドラッグ&ドロップする場所ですが、2つある「行をここにドロップ」のうちの下の方になります。Age Group と同じレベルになるところです。
 
そうしますと、以下のようなピボットテーブルができあがります。

 
では、このピボットテーブルに名前を付けて保存します。画面上部の [保存] ボタンをクリックしてダイアログを開きます。
ダイアログにて、[フォルダ] に Tutorial 、[ピボット名] に Patients by Age Group と入力して保存します。
 
保存のメッセージが表示されたら完了です。

 
では、もう1つピボットテーブルを作ります。[新規] ボタンで新しい画面を開き、以下のように設定します。

  • 行:Diagnoses レベル(DiagD ディメンジョン)
  • 列:Count メジャー、Avg Age メジャー

以下のような感じのピボットテーブルになります。
 
こちらも名前を付けて保存します。[フォルダ] は Tutorial 、[ピボット名] は Patients by Diagnosis とします。
 
これでダッシュボード作成に必要なアイテムが揃いました。

ダッシュボードの作成

ダッシュボードの作成はユーザーポータル画面から行います。管理ポータルより Analytics → ユーザポータル と選択します。
 
以下のような画面が表示されます。既にいくつかのダッシュボードがありますね。

これらは1回目の記事でチュートリアルの準備作業を実施したときに作成されたものです。ダッシュボード作成時の参考になりますので、お時間のある時にのぞいてみてください。
では、新しいダッシュボードを作成します。画面左上の [メニュー] リンクをクリックし、 [新規ダッシュボード] を選択します。
 
ダイアログが開いたら、[フォルダ] に Tutorial を入力(またはドロップダウンリストから選択)し、[ダッシュボード名] に Sample Dashboard と入力して [OK] をクリックします。
 
そうしますと、空のダッシュボード画面が表示されます。
ダッシュボード・エディターのメニューを表示するには、画面左端にある [>] のところをクリックします。 
 
ダッシュボード・エディターのメニューが出てきました。まずウィジェットの設定を行いますので、[ウィジェット] をクリックします。

 
ウィジェットのメニューが表示されます。ここではダッシュボードに使われているウィジェットのリストが表示されますが、作成したばかりですので今はなにもありません。
画面上部の [+] をクリックしてウィジェットの追加設定をしていきます。

 
ウィジェット・ウィザードのダイアログが開きます。左側のメニューから [ピボットとグラフ] をクリックします。
 
展開されたメニューから、[テーブル] を選択します。

 
データソースの指定を行います。虫眼鏡アイコンをクリックします。

 
選択ダイアログから Tutorial → Patients by Age Group と選択します。

 
データソースが設定されます。[OK] で完了します。

 
もし、以下のダイアログが表示されたら、[Reload] をクリックします。

 
先ほど作成したピボットテーブルが画面に表示されました。これで Patients by Age Group の追加は完了です。

 
続いて、もう1つのピボットテーブル Patients by Diagnosis も追加します。先ほどと同様の手順ですが、ピボットテーブルの選択のみ異なります。

 
Patients by Diagnosis ピボットテーブルの追加もできました。が、画面では Patients by Diagnosis しか表示されていません。

 
これは、先に設定した Patients by Age Group の上にかぶさるように Patients by Diagnosis が表示されているためです。
Patients by Diagnosis の上部(メニューバー)にマウスカーソルを合わせるとアイコンが上下左右の矢印に変わりますので、その場所でドラッグし、ピボットテーブル全体を下の方にずらしていきます。
 
これで、隠れていた Patients by Age Group も表示されました。

 
また、各ウィジェットの右下のところをドラッグしながら、ウィジェットのサイズを変えることができます。
 
では、この状態でダッシュボードを保存します。画面上部の [保存] リンクをクリックします。
 
保存されました、というダイアログ等の表示はありません。ただし、先ほどまで表示されていた「変更されました」が消えました。未保存の変更が無くなったということです。
 

続いては、このダッシュボードにフィルタのコントロールを追加します。

ダッシュボード・エディターを開き、ウィジェットの一覧から ウィジェット1(Patients by Age Group)を選択します。
 
ウィジェット1のメニューから [コントロール] メニューをクリックします。
 
コントロールの追加を行いますので、画面上部の [+] をクリックします。
 
コントロール・ウィザードのダイアログが表示されますので、以下のように設定します。ドロップダウンリストから選択可能なものは、選択して設定します。

  • 場所:ダッシュボード
  • ターゲット:* 
  • アクション:フィルタを適用
  • フィルタ:ZIP Code
  • ラベルまたはアイコンを制御:ZIP Code

 
[OK] で設定を完了すると、ダッシュボード画面にフィルタコントロールが追加されます。
 
同様に Allergies と Favorite Color のフィルタを追加します。コントロール上部の [+] から足していきます。

 
 
3つのフィルタコントロールを追加した画面は、以下のようになります。
 

作成した各々のフィルタに規定値を設定します。先ほどのコントロールのメニューまで進み、ZIP Code をクリックします。
 
ZIP Code のコントロール設定メニューが表示されました。この中の [デフォルト値] の虫眼鏡アイコンをクリックします。
 
デフォルト値エディタのダイアログが開きます。[フィルタの値を選択] の横にある虫眼鏡アイコンをクリックします。

 
ZIP Code のメンバ値が一覧表示されます。今回は 32007 を既定値としますので、32007 にチェックを入れ、上部の ✓ アイコンをクリックします。

 
32007の値が設定できたら、[OK] で完了します。

 
もし、以下のダイアログが表示されたら [Leave] をクリックします。

 
ZIP Code の既定値に 32007 が設定されました。また、ピボットテーブルも、その条件によりフィルタされた値に変わりました。

 
同様に、Allergies フィルタには既定値として「soy」を、Favorite Color フィルタには既定値として「Blue」を設定します。
ダッシュボード・エディターのメニューを最初からたどるときは、ウィジェット → ウィジェット1 → コントロール → 設定したいフィルタコントロール と選んでいきます。
最終的な姿は、以下のようになりました。

 
当然、ダッシュボードの上からフィルタ条件の変更は可能です。例えば ZIP Code のフィルタ条件を 32007→34577 に変えてみます。
 
ピボットテーブルの結果が変わったことが分かります。
 

おわりに

今回は、アナライザ画面で作成したピボットテーブルを基に、簡単なダッシュボードを作成しました。また、2つのピボットテーブルに対するフィルタコントロールも追加しました。
今回はピボットテーブルだけでしたが、ウィジェットには各種グラフやスコアカードなど、多様なコントロールが用意されています。それらをうまく組み合わせて、より分かりやすいダッシュボードを作成することが可能です。
次回は、いよいよ最終回となります。最後のトピック「ピボット・テーブルおよびダッシュボードのエクスポートとパッケージ化」について触れます。お楽しみに!

ディスカッション (0)1
続けるにはログインするか新規登録を行ってください
記事
· 2024年5月19日 2m read

Reviews on Open Exchange - #44

If one of your packages on OEX receives a review you get notified by OEX only of YOUR own package.   
The rating reflects the experience of the reviewer with the status found at the time of review.   
It is kind of a snapshot and might have changed meanwhile.   
Reviews by other members of the community are marked by * in the last column.

I also placed a bunch of Pull Requests on GitHub when I found a problem I could fix.    
Some were accepted and merged, and some were just ignored.     
So if you made a major change and expect a changed review just let me know.

# Package Review Stars IPM Docker *
1 AlertDashboard now with Docker 5.0   y  
2 Document Converter really useful tool + Docker 5.0   y  
3 IRIS OData Client now with Docker 5.0   y  
4 IRISDocDBRESTAPIPostmanCollectionSample interesting experience 5.0      
5 ISC-operationaldashboard With DOCKER as base for testing 5.0   y  
6 Database Growth - Data Collection and Analysis Docker support added 4.5   y  
7 Enhanced Monitor Manager now with Docker for testing 4.5   y  
8 Student score query Docker + IPM added 4.0   y  
9 COS-MQTTClient with DOCKER + IPM 4.0   y  
10 XList - for declarative and functional programming docker + IPM added 4.0   y  

.

The missing IPM flag may have 2 reasons
- the related Pull Request was ignored
- publishing in IPM wasn't flagged during Update of OEX
Both are decisions of the owner of the package

ディスカッション (0)1
続けるにはログインするか新規登録を行ってください
質問
· 2024年5月19日

Pooling exception: Unable to find original pool for connection and IRIS Security Error

I created a Dotnet api to connect with IRIS database to do some task.
"InterSystems.Data.IRISClient.dll" (NativeAPI) is used in dotnet api to connect IRIS.
I used following code in dotnet to open and close the IRIS connection.

Open Connection
---------------------------
IRISConnection iRISConnect = new IRISConnection();
IRISCommand command = new IRISCommand();
iRISConnect.ConnectionString = "Server=xxxx.com; Port=1972; Namespace=aaa; Password=yyyy; User ID=xxxxxx;";
IRIS NativeAPI = IRIS.CreateIRIS(iRISConnect);
iRISConnect.Open();

Connection Close
--------------------------
command.Dispose();
iRISConnect.Close();
IRISPoolManager.RemoveAllIdleConnections();

For single API call this code is working, But when I call the dotnet API mutliple times, getting following errors. Anyone faced the same issue or is there any solution for this issue.

1. "Pooling exception: Unable to find original pool for connection"
    {"severityLevel":"Error","outerId":"0","message":"Pooling exception: Unable to find original pool for connection","type":"InterSystems.Data.IRISClient.IRISException","id":"5416676","parsedStack":[{"assembly":"InterSystems.Data.IRISClient, Version=4.5.1.0, Culture=neutral, PublicKeyToken=ad350a26c4a4447c","method":"InterSystems.Data.IRISClient.IRISPoolManager.ReleaseConnection","level":0,"line":0},{"assembly":"InterSystems.Data.IRISClient, Version=4.5.1.0, Culture=neutral, PublicKeyToken=ad350a26c4a4447c","method":"InterSystems.Data.IRISClient.IRISADOConnection.Close","level":1,"line":0},{"assembly":"GHIS.Claims.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null","method":"GHIS.Claims.Domain.Common.DBConnect.ClearPool"
2. "IRIS Security Error"
   {"severityLevel":"Error","outerId":"0","message":"IRIS Security Error","type":"InterSystems.Data.IRISClient.IRISException","id":"60962899","parsedStack":[{"assembly":"InterSystems.Data.IRISClient, Version=4.5.1.0, Culture=neutral, PublicKeyToken=ad350a26c4a4447c","method":"InterSystems.Data.IRISClient.IRISADOConnection.GetServerError","level":0,"line":0},{"assembly":"InterSystems.Data.IRISClient, Version=4.5.1.0, Culture=neutral, PublicKeyToken=ad350a26c4a4447c","method":"InterSystems.Data.IRISClient.IRISADOConnection.processError","level":1,"line":0},{"assembly":"InterSystems.Data.IRISClient, Version=4.5.1.0, Culture=neutral, PublicKeyToken=ad350a26c4a4447c","method":"InterSystems.Data.IRISClient.InStream.readHeader","level":2,"line":0},{"assembly":"InterSystems.Data.IRISClient, Version=4.5.1.0, Culture=neutral, PublicKeyToken=ad350a26c4a4447c","method":"InterSystems.Data.IRISClient.IRISADOConnection.Login","level":3,"line":0},{"assembly":"InterSystems.Data.IRISClient, Version=4.5.1.0, Culture=neutral, PublicKeyToken=ad350a26c4a4447c","method":"InterSystems.Data.IRISClient.IRISPool.CreateNewPooledConnection"

1 Comment
ディスカッション (1)2
続けるにはログインするか新規登録を行ってください
記事
· 2024年5月19日 4m read

Como separar código fuente y datos en diferentes bases de datos

   

 

📜 Santa Tecla, versículo 8: "Extiende tu ratón sobre la pantalla, y el mar de datos abrirá un sendero delante de ti!!"

 

Hola comunidad, lo primero perdón si a alguien le ha ofendido la blasfemia 😔 

 

¿Alguna vez has pensado que sería interesante tener separado el código fuente de los datos de la base de datos?. Quizás te gustaría poder hacer copias de seguridad de tu código sin tener que copiar gigas de información de los datos de tus clientes.

 

A continuación os explico los pasos para separar en 2 bases de datos distintas vuestro mar formado por el código fuente y los datos de un namespace.

Para este ejemplo voy a partir de un nuevo Namespace que voy a crear para el ejemplo.

 

Primero crearemos 2 nuevos Databases:

Accedemos al portal y vamos al apartado de Base de datos locales:

 

Pulsaremos el botón crear nueva base de datos:

 

Le pondremos un nombre e indicaremos la carpeta donde se va a almacenar (Le he puesto el prefijo Tutorial porque el Namespace tengo planeado llamarlo Tutorial):

 

Ahora nos permite elegir el tamaño que queremos asignarle y si queremos hacer Journal del mismo:

 

Seleccionamos crear un nuevo recurso:

 

Asignamos el nombre del nuevo Recurso, ponemos la descripción y si lo consideramos oportuno le marcamos los permisos de acceso públicos:

 

A continuación seguimos seguimos los mismos pasos para el otro Database para los datos:

Seleccionamos crear un nuevo recurso también:

 

Ya tendríamos nuestros 2 base de datos creadas:

 

Ahora crearemos el nuevo Namespace y le asignamos los 2 Databases que acabamos de crear.

Accedemos a la sección Namespaces:

 

 

Pulsamos en el botón Crear nuevo Namespace:

 

Le damos un nombre y elegimos la base de datos para los datos y para el código fuente, a continuación pulsamos el botón Guardar.

 

Y voila, ya tendremos nuestro flamante nuevo namespace creado con 2 bases de datos separadas, una para datos y otra para código fuente:

Esto mismo también podría ser muy útil para situaciones como... Imagina que tienes una base de datos con un tamaño enorme de datos que es compartido por todos los integrantes del equipo de desarrollo.

Puede que estos integrantes tengan portátiles que llevan de un lado para otro y no te gustaría que esos portátiles pudiesen tener una copia de los datos de la base de datos en local, bien por seguridad o bien porque habría que crear quizás datos de prueba en todos ellos.

En ese caso podría ser buena idea crear el Namespace de código fuente en local y las rutinas en una base de datos remota. ¿Que? ¿Qué como se conectaría una base de datos remota? Chupado!

 

Conectando a una base de datos remota. **Hay que configurar previamente el servidor remoto como ECP (lo explico al final del tutorial).

Nos vamos al apartado de servidores remotos para configurarlo (si no lo tenemos configurado ya):

 

Pulsamos sobre el botón Servidores de datos:

 

Y añadimos el nuevo Servidor:

 

Rellenamos la información:

Por defecto lo creará como desactivado, pulsamos el botón Cambiar estado para activarlo:

 

 

 

 

 

Ahora nos vamos al apartado de Base de datos Remotas:

 

Y pulsamos en el botón Crear base de datos remota:

Seleccionaremos el servidor que tiene la base de datos remota y elegiremos la misma en el desplegable:

 

A continuación vamos a crear un nuevo Namespace "Hibrido" con la información del código fuente en el equipo local y los datos en un servidor remoto.

Accedemos al apartado Namespaces y pulsamos el botón crear Namespace, pero esta vez en el apartado de base de datos para los globales marcaremos la opción Base de datos remota y elegiremos el Database remoto que hemos creado:

 

Y ya tendríamos nuestro increíble Namespace hibrido configurado!

**Configurar servidor como ECP (para poder servir bases de datos remotas, requiere una licencia de pago):

 

Establecemos el nº máximo de servidores de datos, SSL, etc.. y pulsamos en los botones Guardar y Activar:

 

Ahora si, ya podríamos tener nuestros datos separados dentro de un mismo servidor o incluso en distintos servidores.

Os dejo aquí un video de como crear los databases y crear y configurar en Namespace:

Espero que este tutorial os haga mas ameno el largo camino por el  desierto 🌴🐪  para conseguir el perdón del CTO / CIO hasta llegar a la jubilación prometida.

Nos vemos en el siguiente post! Hacedme saber si os ha parecido interesante este artículo, todos vuestros comentarios o dudas son siempre bienvenidos. 🙌

ディスカッション (0)1
続けるにはログインするか新規登録を行ってください