New post

Encontrar

Article
· Oct 16, 2024 1m read

第四十九章 解决安全问题 - 可能出现的错误

第四十九章 解决安全问题 - 可能出现的错误

可能出现的错误

本节讨论 IRIS Web 服务和 Web 客户端中可能出现的与安全相关的错误:

  • 如果刚刚生成了 IRIS Web 服务或客户端,则可能尚未配置为识别 WS-Security 标头。在这种情况下,当您尝试执行 Web 方法时,会收到如下一般错误:
<ZSOAP>zInvokeClient+269^%SOAP.WebClient.1

将以下内容添加到Web服务或客户端并重新编译:

Parameter SECURITYIN="REQUIRE";

这种一般错误也可能是由于错误地调用 Web 方法(例如,在 Web 方法没有返回值时引用返回值)造成的。

如果使用 WS-Policy,则此项不适用。

Discussion (0)1
Log in or sign up to continue
Article
· Oct 16, 2024 8m read

Desenvolvendo Integrações com InterSystems IRIS - SOAP OutboundAdapter

Projeto 5 – SOAP Outbound Adapter

Vamos montar nossa próxima integração utilizando o adaptador SOAP Outbound Adapter. Este adaptador permite acessar um serviço SOAP externo e consumir este serviço.

No nosso exemplo vamos publicar um serviço SOAP no barramento de integração simulando um serviço externo. Vamos então consumir o WSDL deste serviço criando o BO automaticamente, e depois montaremos os BP e BS da integração.

O primeiro passo é criar um serviço que será consumido. Imagine que este é um serviço externo que você precisa consumir. Vamos então criar um BS que fará este papel para nós. Primeiro vamos criar as classes de Request e Response do nosso serviço “fake”:

Class ws.soap.msg.Request Extends Ens.Request
{
Property codigo As %Integer;
}

Class ws.soap.msg.Response Extends Ens.Response
{
Property nome As %String;

Property status As %Boolean;

Property mensagem As %String;

Property sessionId As %Integer;
}

Agora vamos criar o nosso BS que irá atender as requisições SOAP do nosso exemplo:

 

Class ws.soap.bs.Service Extends EnsLib.SOAP.Service
{

Parameter ADAPTER = "EnsLib.SOAP.InboundAdapter";

Parameter SERVICENAME = "consulta";

Method entrada(pInput As ws.soap.msg.Request) As ws.soap.msg.Response [ WebMethod ]
{
              //
              // Este serviço simula um serviço SOAP externo para ser utilizado para testes
              //
              Set tResponse=##Class(ws.soap.msg.Response).%New()
              If pInput.codigo<10&(pInput.codigo>0)
              {
              Set nome=$Piece("Julio^Sofia^Marcio^Liana^Julia^Pedro^Fernanda^Abel^Maria","^",pInput.codigo)
                            Set tResponse.nome = nome
                            Set tResponse.status = 1
                            Set tResponse.mensagem=""
              } Else {
                            Set tResponse.nome = ""
                            Set tResponse.status = 0
                            Set tResponse.mensagem = "Codigo fora do limite (1-9)"
              }
              Quit tResponse
}

}

Vamos agora colocar nosso BS na production. Abra o Painel de Administração e vá para a nossa production de teste. Clique no botão (+) ao lado do nome Services e preencha a tela a seguir com os dados apresentados:

Agora volte a production e clique no nome do nosso BS (ws.soap.bs.Service) e veja a configuração dele. Expanda a área Parâmetros de Conexão e marque a caixa Habilitar Requisições Padrão conforme a tela abaixo:

A seguir clique em Atualizar e nosso BS de teste estará pronto.

Agora vamos testar nosso serviço SOAP. Vamos abrir o SoapUI e importar o WSDL. O endereço do WSDL do nosso serviço é http://localhost/iris_iss/csp/integra/ws.soap.bs.Service.cls?WSDL=1 para a minha configuração.

Abra então o SoapUI e importe o WSDL. Vá em File->New SOAP Project e na janela que será apresentada coloque o endereço do WSDL na caixa Initial WSDL e a seguir clique em OK:

Project Name será preenchido automaticamente. Após o OK será disponibilizada a interface de teste do serviço:

Substitua o ? no XML por um valor entre 1 e 9 e veja o resultado:

Veja que recebemos o nome que corresponde ao código informado. Agora que temos nosso serviço pronto vamos então construir nossa integração para consumi-lo. Lembre do endereço do WSDL do serviço que criamos. Vamos utiliza-lo novamente para criar o nosso BO. Para isso vá no Studio e no menu selecione Ferramentas->Suplementos->Assistente SOAP:

Informe o endereço do WSDL que se deseja consumir e clique em Avançar:

Marque as caixas Criar Serviço Web e Criar Business Operation. Preencha as caixas Pacote do Business Operation, Pacote o Objeto de Requisição, Pacote do Objeto de Resposta e Pacote da Classe proxy conforme a tela acima. A seguir clique em Avançar:

Nesta próxima tela clique em Avançar:

E nesta última tela em Terminar. Pronto, já temos o código do nosso BO pronto. Abrindo a árvore do namespace no Studio veremos as classes e pacotes criados:

Navegue em ws->nome->bo->Operation e localize a classde consultaSoap. Abra a classe no studio e veja o adaptador que ela utiliza:

Veja que estamos utilizando o SOAP Outbound Adapter. Toda a construção do nosso BO foi feita pelo Wizard do Studio baseado no WSDL que nós informamos.

Vamos agora criar o nosso BS. Ele será também um BS que utiliza o adaptador SOAP Inbound. Vamos primeiro criar as classes de Request e Response do nosso serviço e depois o próprio BS:

Abaixo o código do Request:

Class ws.nome.msg.Request Extends Ens.Request
{


Property codigo As %Integer;
 

}

 

E a seguir o código do Response:

 

Class ws.nome.msg.Response Extends Ens.Response
{

Property nome As %String;

Property status As %Boolean;

Property mensagem As %String;

Property sessionId As %Integer;

}

Agora o código do BS:

Class ws.nome.bs.Service Extends EnsLib.SOAP.Service
{

Parameter ADAPTER = "EnsLib.SOAP.InboundAdapter";

Parameter SERVICENAME = "nome";

Method entrada(pInput As ws.nome.msg.Request) As ws.nome.msg.Response [ WebMethod ]
{
              Set tSC=..SendRequestSync("bpNome",pInput,.tResponse)
              If $$$ISERR(tSC) Do ..ReturnMethodStatusFault(tSC)
              Quit tResponse
}

}

Note que Request tem como superclasse Ens.Request e Response tem como superclasse Ens.Response. Isso é importante para que as funcionalidades do barramento estejam disponíveis nas mensagens.

Note também que nosso BS usa o adaptador EnsLib.SOAP.InboundAdapter. Isso habilita nosso BS a publicar o serviço SOAP. Vamos precisar depois realizar algumas configurações no BS, mas faremos isso quando formos coloca-lo na produção.

Agora, por fim, vamos montar nosso BP, que é o orquestrador das chamadas da integração.

Configure nosso componente CALL da seguinte forma:

O código do nosso BP ficará assim:

/// 
Class ws.nome.bp.Process Extends Ens.BusinessProcessBPL [ ClassType = persistent, ProcedureBlock ]
{

/// BPL Definition
XData BPL [ XMLNamespace = "http://www.intersystems.com/bpl" ]
{
<process language='objectscript' request='ws.nome.msg.Request' response='ws.nome.msg.Response' height='2000' width='2000' >
<context>
<property name='valido' type='%Boolean' initialexpression='0' instantiate='0' />
</context>
<sequence xend='200' yend='350' >
<call name='boNome' target='boNome' async='0' xpos='200' ypos='250' >
<request type='ws.nome.bo.Request.entradaRequest' >
<assign property="callrequest.pInput.codigo" value="request.codigo" action="set" languageOverride="" />
</request>
<response type='ws.nome.bo.Response.entradaResponse' >
<assign property="response.nome" value="callresponse.entradaResult.nome" action="set" languageOverride="" />
<assign property="response.status" value="callresponse.entradaResult.status" action="set" languageOverride="" />
<assign property="response.mensagem" value="callresponse.entradaResult.mensagem" action="set" languageOverride="" />
<assign property="response.sessionId" value="..%Process.%SessionId" action="set" languageOverride="" />
</response>
</call>
</sequence>
</process>
}

Storage Default
{
<Type>%Storage.Persistent</Type>
}

}

Agora vamos utilizar a production que criamos no exemplo anterior e colocar as classes nela e realizar algumas configurações. Vamos colocar nossos componentes na production. Clique no botão (+) ao lado do título Services e inclua o nosso BS conforme a tela abaixo:

Clique em OK e a seguir clique sobre o nome do nosso BS para completarmos a configuração. Expanda a área Parâmetros de Conexão e marque a caixa Habilitar Requisições Padrão:

 

Clique agora em Aplicar e pronto. Nosso BS está configurado.

Agora vamos passar para o nosso BO. O processo é o mesmo, ou seja, clique no botão (+) ao lado do título Operations e preencha a tela que será apresentada:

Pronto. Nosso BO está configurado na production.

A seguir clique no botão (+) ao lado do título Process para incluir o nosso BP:

 

Preencha a tela conforme acima e clique em OK.

Temos nossos 3 componentes configurados na produção. Clique na bola verde ao lado de bpGlobalIncluir para ver as conexões entre os componentes:

Agora vamos verificar o WSDL do nosso BS. Abra no navegador e vá para o endereço http://localhost/iris_iss/csp/integra/ws.nome.bs.Service.cls?WSDL=1 e veja o WSDL do nosso serviço:

 

Volte ao SoapUI e novamente clique em File->Create a SOAP Project e preencha a tela:

Preencha a caixa Initial WSDL e a caixa Project Name será preenchida automaticamente. Clique em OK e veja a interface de teste criada:

Informe um código e clique no icone de Play. Veja o resultado ao ladoa:

Podemos ver o trace de execução desta chamada:

Com isso concluímos esta integração. Utilizamos em nosso teste o IRIS 2024.1 que está disponível para download na sua versão Community na internet.

Discussion (0)1
Log in or sign up to continue
Question
· Oct 16, 2024

Error Executing Stored Procedure in InterSystems Cache using SQL

I am experiencing an issue while executing a stored procedure in InterSystems Cache. Here’s the procedure I created

CREATE PROCEDURE Silk.sp_InsertRecord (
    IN RecordDate TIMESTAMP,
    IN UserName VARCHAR(50),
    IN RecordType INT,
    IN RecordID VARCHAR(50),
    IN CategoryID INT,
    IN ApprovalDate TIMESTAMP,
    IN FileSize BIGINT,
    IN WorkstationName VARCHAR(50)
)
BEGIN 
    INSERT INTO DummyRecords (
        RecordKey, 
        FilePath, 
        RecordDate, 
        UserName, 
        RecordType, 
        RecordID, 
        CategoryID, 
        FileSize
    ) 
    VALUES (
        'd4a4e44b-4b56-4a74-b7f5-e44716fa5a13', 
        '', 
        RecordDate, 
        UserName, 
        RecordType, 
        RecordID, 
        CategoryID, 
        FileSize
    ); 
END

This creates an SP of Function type.

Issue:

I encounter the following error upon execution:

Namespace: SILK
Process: 29088
Error:
2024-10-17 12:25:54 [SQLCODE: <-400>:<Fatal error occurred>] [Cache Error: <<UNDEFINED>zspInsertObject+50^Silk.procspInsertObject.1 *%ROWCOUNT>] [Location: <SPFunction>] [%msg: <Unexpected error occurred: <UNDEFINED>%0Ao+3^Silk.procspInsertObject.1 *%mmmsqld(3)>]

However, when I execute the stored procedure without passing any parameters and hardcode the values directly, it executes without any errors. Then it usually creates a query type procedure.

Additional Information:

  • I am new to Cache and not entirely sure why I'm getting this error.
  • The stored procedure compiles without any syntax errors. This is just an example..

Can someone help me understand why this error is occurring and how I can resolve it? Any guidance on how to properly debug or fix this issue would be greatly appreciated.

Discussion (0)0
Log in or sign up to continue
Question
· Oct 16, 2024

JWT Signature Creation for OAuth Call

Working on a project where I'm needing to make FHIR calls from my HealthConnect Interop production to Epic. 

My issue is I'm not able to construct a valid JWT for the OAuth token retrieval that Epic will accept. I have the below code where I'm able to create a valid header and payload that I'm base64URL encoding and then trying to sign with my .pem private key file. However, Epic is not liking the signature portion of my JWT.

As such, I wanted to present my code to see if I'm performing the signature steps correctly? I've seen some posts where the %Net.JSON JWT specific classes were used to generate the token, but I am thinking this method should work?

Any thoughts on this issue, or insight from other folks who have made OAuth calls from HealthConnect to Epic before, would be greatly appreciated! 

 

ClassMethod CreateJWT(pHostIn As %String) As Epic.Utils.JWTHeader
{
        
//Set Headers using message class I created.
set Header = ##class(Epic.Utils.JWTHeader).%New()
set Header.alg = "RS384"
Set Header.typ = "JWT"

//Set Epic payload values using message class I created.
Set Payload = ##class(Epic.Utils.JWTPayload).%New()
Set Payload.iss = "<Client ID>"
set Payload.sub = "<Client ID>"
set Payload.aud = pHostIn
Set Payload.jti = $SYSTEM.Util.CreateGUID()
Set Payload.exp = ##class(%Library.UTC).SecondsSinceUnixEpoch($ztimestamp)+3500

//Convert the Header and Payload JSON to stings.
do Header.%JSONExportToString(.HeaderString)
do Payload.%JSONExportToString(.PayloadString)

//Concat the Header and Payload together with period and Base64URL encode them.
set PayloadToSign = $$$BASE64URLENCODE(HeaderString)_"."_$$$BASE64URLENCODE(PayloadString)

//Open the private key pem file to be used for the RSA signature.
Set File=##class(%Stream.FileBinary).%New()
set File.Filename = "/PrivateKey.pem"
set PVKey = File.Read($$$MaxLocalLength)

//sign the concatenated Header and Payload using the PVKey from the file.
Set RSASig=##class(%SYSTEM.Encryption).RSASHASign(384,PayloadToSign,PVKey)

//Base64URL encode the returned RSA signature.
set Signature = $$$BASE64URLENCODE(RSASig)

//Concat the original Header/Payload string with the Base64URL encoded signature.
Set JWT = PayloadToSign_"."_Signature

//Return the fully constructed JWT for the token call.
       Quit JWT
}

1 Comment
Discussion (1)1
Log in or sign up to continue
Article
· Oct 16, 2024 2m read

configuração do recurso de Python Flexível em Tempo de Execução no IRIS 2024.2

Olá Comunidade,

Este artigo tem como objetivo guiá-lo pelo processo de configuração e utilização do recurso Python Runtime Flexível para Python embutido. Antes da versão 2024.2, o instalador do InterSystems IRIS incluía uma versão pré-instalada do Python. Você pode encontrar as bibliotecas Python e os arquivos de aplicação localizados no diretório \lib\python dentro da sua pasta de instalação do IRIS (por exemplo, C:\InterSystems\IRIS20242\lib\python).

No entanto, a partir da versão 2024.2, o instalador do IRIS não mais inclui a instalação do Python por padrão. Consequentemente, você não encontrará esses arquivos no diretório mencionado. É necessário que você instale a versão necessária do Python para trabalhar eficazmente com Python embutido no IRIS.

Vamos proceder à configuração do recurso runtime flexível dentro do meu ambiente IRIS.

Eu instalei a versão comunitária 2024.2 na minha máquina e tentei conectar o shell python imediatamente no terminal IRIS.

USER>Write $ZV
IRIS for Windows (x86-64) 2024.2 (Build 247U) Tue Jul 16 2024 09:57:03 EDT
USER>Do $SYSTEM.Python.Shell()
ERROR #5002: ObjectScript error: <OBJECT DISPATCH>Shell+16^%SYS.Python.1 *Failed to Load Python: Check documentation and messages.log, Check CPF parameters:[PythonRuntimeLibrary,PythonRuntimeLibraryVersion], Check sys.path setup in: $INSTANCE/lib/python/iris_site.py.

Ele lança um erro devido à configuração ausente dos valores PythonRuntimeLibrary  e PythonRuntimeLibraryVersion (nota: eu já defini a versão PythonRuntimeLibraryVersion)

Agora, eu já instalei o python 3.12.5 no meu sistema e configurei os valores nas configurações.

PythonRuntimeLibrary  - “C:\Program Files\Python312\python3.dll”
PythonRuntimeLibraryVersion - 3.12

Depois de configurado, executei o Do $SYSTEM.Python.Shell() novamente e consegui entrar no shell Python com sucesso.

Observação: O recurso de tempo de execução flexível do Python, de acordo com a documentação, não é suportado para todos os sistemas operacionais.

Discussion (0)1
Log in or sign up to continue