新しい投稿

検索

記事
· 2024年9月19日 6m read

eBPF - Cilium on FHIR® - A Star Wars Story

 

Anakin Skywalker challenged the high ground and has been terribly injured on Mustafar.  

 
He is a relatively new employee of the Galatic Empire, covered by a Large Group Planetary Plan and now has an active encounter in progress for emergent medical services in the Grand Medical Facility on Coruscant. The EMR deployed for the Galactic Health System is Powered by InterSystems FHIR Server running on Kubernetes protected by Cilium.

Let's recreate the technical landscape, to be performed in the style of Isovalent Labs...

Kind Cluster

Lets fire up a 3 node cluster, and disable the CNI so we can replace it with Cilium. 

cat <<EOF | kind create cluster --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
  - role: control-plane
  - role: worker
  - role: worker
  - role: worker
networking:
  disableDefaultCNI: true
EOF

This will provision the kind cluster, 3 nodes wide with a single control plane.


Cilium

Cilium is an open-source project that provides networking, security, and observability for containerized environments like Kubernetes clusters. It uses a Linux kernel technology called eBPF (extended Berkeley Packet Filter) to inject security, networking, and observability logic into the kernel.

In other words, wields the force.

cilium install --version v1.16.0
cilium status --wait


Hubble

Hubble is a clown suit for Cilium, providing ridiculous visibility to what powers Cilium are in play in real time.

cilium enable hubble

 

 

InterSystems FHIR Workload

InterSystems is the GOAT of interoperability, and transforms Healthcare Data like a protocol Droid.

kubectl apply -f https://raw.githubusercontent.com/sween/basenube/main/scenarios/ciliumfhir/deploy/cilium-fhir-starwars.yaml

The resulting workload has 4 deployments:

GrandMedicalFacility


Integrated Delivery Network based in Coruscant, with facilities as far as the Outer Rim, runs Epic and utilizes InterSystems I4H as a FHIR Server.

MedicalDroid FX-6


This 1.83-meter-tall droid supplied Vader with a blood transfusion and trained in cybernetic legs procedures.

MedicalDroid DD-13


Also known as the DD-13 tripedal medical droid, this droid has three legs for stability and was designed to install cybernetic implants. 

MedicalDroid 2-1B


2-1B droids have hypodermic injectors and precision-crafted servogrip pincers, and can be upgraded to specialize in areas like cybernetic limb replacement, neurosurgery, and alien biology.

Since we will need it anyway for upcoming interviews, lets tell the story in true STAR (Sithuation, Task, Action, Result) methodology.

Sith-uation

Palpatine accompanied the fallen jedi to the facility, and upon arrival helped registration admit him as Darth Vader.  

cat > vader.json << 'EOF'
{
  "name": [
    {
      "use": "official",
      "family": "Vader",
      "given": [
        "Darth"
      ]
    }
  ],
  "gender": "male",
  "id": "DarthVader",
  "birthDate": "1977-05-25",
  "resourceType": "Patient"
}
EOF
curl -v -X PUT \
  -H "Content-Type: application/fhir+json" \
  -d @vader.json \
  "http://coruscanthealth:52773/intersystems/fhir/r5/Patient/DarthVader"

Darth Vader is now registered, and can be seen throughout the Health System...  

Galactic IT Outage

There is a problem though!  

Shortly after registration, a Galactic IT Outage has occured, making the Identity Provider for the Health System unavailable. The InterSystems FHIR Resource Server is SMART enabled, and the IDP is casters up, making EMR launches impossible with the absence of the jwt token with the applicable scopes to protect the routes.



Sure as Bantha Fodder, we definitely have a problem... the care team cannot access the patient record, nothing but 401's and 403's and were not talking about your Galactic Retirement Plan.

Although the Hubble UI only provides a hint to what is going on, Inspecting the Hubble flows with Layer 7 information reveals the sithuation.





...and after adding some debugs bunny to the InterSystems FHIR endpoint, confirms it.

 
FHIR Debug
zw^FSLOG
...
^FSLOG(379555)="DispatchRequest^HS.FHIRServer.Service^944|Msg|Dispatch interaction read for Patient/DarthVader|09/19/2024 10:48:20.833339AM"
^FSLOG(379556)="DispatchRequest^HS.FHIRServer.Service^944|Msg|Request Completed in .000186 secs: Patient/DarthVader|09/19/2024 10:48:20.833450AM"
^FSLOG(379557)="processRequest^HS.FHIRServer.RestHandler^944|Msg|Response Status: 401, Json: Patient|09/19/2024 10:48:20.833454AM"
...


Task

What's a great line from Star Wars that doesn't get quoted enough? :  r/StarWarsCantina

Action

With the route enforcement from SMART not applicable, lets do this our way and use Cilium to protect the endpoints while Vader gets immediate attention the Emperor demands.  We will go Rogue One here on the cluster and hand off the endpoint/route protection to Cilium while the Galaxy figures itself out from the outage.

Lets institute a deny all, from everywhere, with a CiliumClusterwideNetworkPolicy, and work backwards zero trust style.
 

cat <<EOF | kubectl apply -n galactic-fhir -f- 
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
  name: "denyall-coruscanthealth"
spec:
  description: "Block all the traffic (except DNS) by default"
  egress:
  - toEndpoints:
    - matchLabels:
        io.kubernetes.pod.namespace: kube-system
        k8s-app: kube-dns
    toPorts:
    - ports:
      - port: '53'
        protocol: UDP
      rules:
        dns:
        - matchPattern: '*'
  endpointSelector:
    matchExpressions:
    - key: io.kubernetes.pod.namespace
      operator: NotIn
      values:
      - kube-system
EOF

Looking good, Cilium dropping it like its hot!



Now, lets open up the FHIR endpoint on the intersystems pod, disabling the oauth2 client.

set app = "/intersystems/fhir/r5"
Set strategy = ##class(HS.FHIRServer.API.InteractionsStrategy).GetStrategyForEndpoint(app)
// 7 = Mass Openness
Set configData.DebugMode = 7
Set configData = strategy.GetServiceConfigData()
Do strategy.SaveServiceConfigData(configData)

Lastly, lets create a CiliumNetworkPolicy to allow anybody from the org:empire, access to the route for DarthVaders record in the galactic-fhir namespace.

apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "l7-visibility"
spec:
  endpointSelector:
    matchLabels:
      org: empire
  egress:
  - toPorts:
    - ports:
      - port: "53"
        protocol: ANY
      rules:
        dns:
        - matchPattern: "*"
  - toEndpoints:
    - matchLabels:
        "k8s:io.kubernetes.pod.namespace": galactic-fhir
    toPorts:
    - ports:
      - port: "52773"
        protocol: TCP
      rules:
        http:
          - method: "GET"
            path: "/intersystems/fhir/r5/Patient/DarthVader"
          - method: "HEAD"
            path: "/intersystems/fhir/r5/Patient/DarthVader"
EOF

Looks like we may be able to get back to iRacing, I think we are good.



...except

 

Yeah, looks like the payer is getting dropped...



Policy verdict = DROPPED



Let's add another policy, allowing org:payer access to Vaders route:

 

cat <<EOF | kubectl apply -n galactic-fhir -f- 
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "l7-visibility-payer"
spec:
  endpointSelector:
    matchLabels:
      org: payer
  egress:
  - toPorts:
    - ports:
      - port: "53"
        protocol: ANY
      rules:
        dns:
        - matchPattern: "*"
  - toEndpoints:
    - matchLabels:
        "k8s:io.kubernetes.pod.namespace": galactic-fhir
    toPorts:
    - ports:
      - port: "52773"
        protocol: TCP
      rules:
        http:
          - method: "GET"
            path: "/intersystems/fhir/r5/Patient/DarthVader"
          - method: "HEAD"
            path: "/intersystems/fhir/r5/Patient/DarthVader"
EOF

Welp, that did not quite cut it, and we can see why.



 

So we gave the payer a call and told them to access the "correct" patient record, and Anakin Vader gets his legs.

Rant time...




Result

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

EOF forced to LF in VS Code since version 2.12.6 of "Intersystems ObjectScript" extension

Hello,

Since version 2.12.6 of "Intersystems ObjectScript" extension in VS Code, the compile process force the EOF automatically to LF.
Have you encountered this issue and do you know how to resolve it?

Thank you,

Maxime

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

Latency with VS Code 1.93 for "Import and Compile"

Hello,

Since version 1.93 of VS Code, the “import and compile” process has been very slow (more than an hour).
Have you encountered this issue and do you know how to resolve it?

Thank you,

Maxime

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

第二十八章 添加数字签名 - 指定摘要方法

第二十八章 添加数字签名 - 指定摘要方法

指定摘要方法

默认情况下,签名的摘要值是通过 SHA-1 算法计算的,安全标头中的 <Signature> 元素包含如下内容:

   <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod>
   <DigestValue>waSMFeYMruQn9XHx85HqunhMGIA=</DigestValue>

可以为签名指定不同的摘要方法。为此,调用 %XML.Security.Signature 实例的 SetDigestMethod() 方法。对于参数,请使用以下宏之一(包含在 %soap.inc 文件中):

  • $$$SOAPWSsha1 (the default)

-$$$SOAPWSsha256

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

Desenvolvendo SMART em aplicações FHIR com Auth0 e InterSystems IRIS FHIR Server - Configuração

No último artigo nós apresentamos a arquitetura do nosso projeto SMART On FHIR, então agora é o momento de colocar a mão na massa e começar a configurar os elementos que vamos precisar. 

Vamos começar com Auth0.

Configuração AUTH0

Vamos começar criando uma conta Auth0 com um email válido. Uma vez registrada, vamos criar nossa primeira aplicação e faremos isso do menu a esquerda:

Application menu

Em nosso exemplo, a aplicação será do tipo Single Page Web Application, como é uma aplicação desenvolvida em Angular 16. Selecionamos esta opção e clicamos em Create.

Single Page Web Application

Na próxima pagina devemos definir os seguintes campos:

ATENÇÃO! URLs devem ser HTTPS, é uma das necessidades para conexões OAuth2

Com isso temos configuradas as URLs que o Auth0 necessita para redirecionar o usuário após os processos de autenticação e autorização. Se você vir as URLs, elas não têm nenhuma porta definida. Isso é porque com a entrega do projeto Angular no Docker por meio do NGINX, indicamos que será acessível pela porta default HTTPS, 443. Você pode colocar o nome que preferir.

Application configuration

Para as configurações subsequentes de nosso projeto Angular, escreva os valores que achamos tanto no Domain quanto no Client ID.

Com nossa aplicação configurada, é hora de definir a API que vai receber as requisições da nossa aplicação Angular e de novo faremos isso pelo menu à esquerda:

Essa opção nos mostra uma nova tela para entrar com todos os dados necessários:

API configuration

Você vai precisar definir um identificador para a API que posteriormente será usado pela aplicação Angular como um "ambiente" para conectar corretamente. Como você pode ver, eles recomendam que você insira uma URL, mas não é necessário que essa URL seja funcional, já que só vai ser usada como um identificador. No nosso caso, podemos definir:

https://localhost/smart/fhir/r5

Finalmente, configuamos o algoritmo de assinatura para RS256 e vamos à aba de Permissões, onde definimos o escopo do FHIR para usuários conectados:

API permission

Se você quiser ir mais a fundo no tópico de contextos FHIR, você pode consultar a URL da página oficial clicando aqui. Para o nosso exemplo, definimos o escopo user/*.*  que permite que o usuário validado performe operações CRUD em todos os recursos do servidor FHIR.

Perfeito! Nós já configuramos nossa conta Auth0 para funcionar como um servidor OAuth2.

Configuração Angular app

Eu gostaria de ter desenvolvido a aplicação em Angular 17, que introduz algumas mudanças, mas infelizmente a documentação associada para Auth0 e suas livrarias só estão disponíveis para Angular 16, então eu decidi seguir o caminho mais fácil e desenvolvi na versão 16.

Para configurar nosso projeto Angular, vamos precisar abrir a página app.module.ts e procurar o seguinte fragmento de código:

Vamos ver o que cada parâmetro a configurar significa:

  • domain: corresponde ao valor Domain que foi gerado quando criamos nossa aplicação em Auth0.
  • clientId: o mesmo que acima, mas com o valor gerado Client ID
  • audience: correspondente à URL que configuramos como identificador da nossa API.
  • uri: com esse valor, vamos dizer à livraria Auth0 TypeScript para interceptar todas as chamadas que fizermos à URLs que contém essa URI e incluir o Acess_token que Auth0 vai retornar quando validarmos (adicionando o parâmeto de Authorização para a header a chamada: Bearer ...).

Uma vez que esses valores fossem modificados, teríamos nossa aplicação Angular configurada para funcionar com Auth0. No próximo artigo vamos ver em mais detalhes como invocar um Auth0 da nossa interface de usuário.

Configuração InterSystems IRIS for Health 

Esse projeto é configurado para instalar automaticamente o servidor FHIR durante o processo de desenvolvimento, isso vai nos salvar um passo. No nosso caso, temos definida a URI /smart/fhir/r5 como endpoint do nosso servidor FHIR. Para aqueles que não estão familiarizados com a terminologia FHIR, r5 se refere À versão mais recente do FHIR, disponível há alguns meses no IRIS.

Para configurar nossa instância IRIS, precisaremos primeiro iniciar nosso Docker e entregar os 3 containers disponíveis no projeto. Precisaremos primeiro executar o comando a seguir no terminal a partir da raiz do projeto:

docker-compose up -d --build

Isso faz com que possamos construir e rodar os containers presentes no projeto. Para usuários Windows, se você usa o Docker Desktop você deve ver uma tela como a seguinte:

Docker Desktop

Aqui nós temos 3 containers:

  • iris: com a instância IRIS onde nosso servidor FHIR está localizado.
  • smart-ui: com o código de nossa aplicação web entregue via NGINX configurada de tal maneira que todas as conexões são por SSL com seus certificados associados.
  • webgateway: com esse servidor associado Apache (lembre que desde a versão oficial 2023.1 o Private Web Server foi eliminado, embora esteja ainda disponível nas versões de comunidade).

Web Gateway

Como eu venho repetindo, para usar o OAuth2 com nosso servidor FHIR, é obrigatório que todas as conexões sejam feitas por HTTPS, então o servidor Apache deve ser configurado para aceitar apenas chamadas desse tipo. Se você der uma olhada no arquivo /webgateway/shared/CSP.conf você poderá ver a seção a seguir responsável por configurar o servidor Apache:

# SSL SECTION #
# Enable SSL/TLS (https://) on the Apache web server.
# The user is responsible for providing valid SSL certificates.
LoadModule ssl_module /usr/lib/apache2/modules/mod_ssl.so
LoadModule headers_module /usr/lib/apache2/modules/mod_headers.so
<VirtualHost *:443>
SSLEngine on
SSLCertificateFile "/webgateway-shared/apache_webgateway.cer"
SSLCertificateKeyFile "/webgateway-shared/apache_webgateway.key"
Header add ACCESS-CONTROL-ALLOW-ORIGIN "*"
</VirtualHost>

Você pode ver como está configurada de tal maneira que as chamadas somente venham pela porta 443, ou seja, a URL do nosso webgateway será https://webgatwaye as chamadas que lançamos da nossa aplicação web ao nosso servidor FHIR devem ser redirecionadas a essa URL (webgateway é a máscara dada à network do container Docker criada por ele).

Todas as chamadas ao servidor do Angular chegarão com a URL https://localhost/smart/fhir/r5 e o NGINX terá a função de redirecionar esse localhost ao webgateway. Se você abrir o arquivo /smart-ui/nginx.conf você poderá ver a seguinte configuração:

 

Nessa configuração, vemos que nossa aplicação web ouvirá a porta 443 e todas as chamadas que têm o valor / na URL serão manuseadas pela aplicação Angular, enquanto aquelas que incluem /smart/ serão redirecionadas ao https://webgateway.

Be careful with proxy_set_header, which will be the value that avoids headaches with CORS. To prevent our Web Gateway from rejecting calls from other servers, we must modify the value of the Host header to configure it with the address of the Web Gateway.

InterSystems IRIS

Agora precisamos configurar nosso IRIS para funcionar com Auth0. Para isso vamos configurá-lo como um cliente Oauth2. E para isso, só precisaremos acessar o Portal de Administração com as credenciais superuser/SYS e acessar a opção Administração do Sistema > Segurança > OAuth 2.0 > Cliente, então clicar em Criar Descrição do Servidor e preencher o endpoint Issuer com o valor de domínio que obtivemos criando a aplicação para Auth0 (https://[MY_DOMAIN]/). Cuidado! A URL deve terminar com "/". Finalmente selecionamos a configuração SSL/TLS e clicamos em Descobrir e Salvar:

IRIS client

Automaticamente nossa instância IRIS vai retornar as informações que precisa do Auth0:

Issuer endpoint

Nós só precisamos adicionar um cliente ao servidor que acabamos de configurar. Ao clicar em Client Configuration vamos acessar uma nova tela onde podemos definir o nome da aplicação e do cliente. Esse nome de cliente será o que posteriormente vamos usar para configurar nosso servidor FHIR.

Servidor FHIR

O último passo para finalizar a configuração do nosso projeto é dizer ao servidor FHIR qual cliente OAuth2 será usado para a conexão. Para acessar a configuração vamos abrir o Portal de Administração e selecionar Health > FHIR > FHIR Configuration > Server Configuration  e então vamos abrir o endpoint mostrado na tela. Vamos para o final dele e clicaremos em Editar. Finalmente, adicionamos no campo OAuth Client Name o nome com o qual criamos a configuração do cliente.

FHIR OAuth Configuration

Conclusão

Bom, já temos nosso projeto configurado, no próximo artigo vamos ver como a aplicação Angular interopera com cada um dos atores.

Obrigado pela sua atenção!

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